Skip to content

Commit

Permalink
add controlled popover focus prop (huntabyte#143)
Browse files Browse the repository at this point in the history
  • Loading branch information
huntabyte authored Oct 27, 2023
1 parent 7cc6622 commit 7020075
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/dry-sheep-explode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"bits-ui": patch
---

add controlled popover focus prop
33 changes: 26 additions & 7 deletions src/lib/bits/popover/components/Popover.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<script lang="ts">
import type { Props } from "../types.js";
import { setCtx } from "../ctx.js";
import { isBrowser } from "$lib/internal/is.js";
import { tick } from "svelte";
type $$Props = Props;
export let positioning: $$Props["positioning"] = undefined;
Expand All @@ -12,12 +14,14 @@
export let portal: $$Props["portal"] = undefined;
export let open: $$Props["open"] = undefined;
export let onOpenChange: $$Props["onOpenChange"] = undefined;
export let focusTriggerOnClose: $$Props["focusTriggerOnClose"] = false;
export let openFocus: $$Props["openFocus"] = undefined;
export let closeFocus: $$Props["closeFocus"] = undefined;
const {
updateOption,
states: { open: localOpen }
states: { open: localOpen },
ids: { trigger }
} = setCtx({
positioning,
arrowSize,
Expand All @@ -29,16 +33,31 @@
defaultOpen: open,
openFocus,
closeFocus,
onOpenChange: ({ next }) => {
if (open !== next) {
onOpenChange?.(next);
open = next;
}
return next;
onOpenChange: ({ next, curr }) => {
return customOnOpenChange({ next, curr });
}
});
type ChangeFn = ({ curr, next }: { curr: boolean; next: boolean }) => boolean;
const customOnOpenChange: ChangeFn = ({ next }) => {
if (open === next) return next;
if (next === false && focusTriggerOnClose && isBrowser) {
tick().then(() => {
const triggerEl = document.getElementById(trigger);
if (triggerEl) {
triggerEl.focus();
}
});
}
onOpenChange?.(next);
open = next;
return next;
};
$: open !== undefined && localOpen.set(open);
$: updateOption("positioning", positioning);
$: updateOption("arrowSize", arrowSize);
$: updateOption("disableFocusTrap", disableFocusTrap);
Expand Down
8 changes: 8 additions & 0 deletions src/lib/bits/popover/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ type Props = Expand<
OmitOpen<CreatePopoverProps> & {
open?: boolean;
onOpenChange?: OnChangeFn<boolean>;
/**
* Focus the trigger when `open` is programmatically set to false.
* This is in addition to the automatic focus that occurs when you
* don't programmatically set `open` to false.
*
* @default false;
*/
focusTriggerOnClose?: boolean;
}
>;

Expand Down

0 comments on commit 7020075

Please sign in to comment.