diff --git a/packages/bits-ui/src/lib/bits/context-menu/index.ts b/packages/bits-ui/src/lib/bits/context-menu/index.ts index 4e5ec7739..a3f352acf 100644 --- a/packages/bits-ui/src/lib/bits/context-menu/index.ts +++ b/packages/bits-ui/src/lib/bits/context-menu/index.ts @@ -2,7 +2,7 @@ export { default as Root } from "$lib/bits/menu/components/menu.svelte"; export { default as Sub } from "$lib/bits/menu/components/menu-sub.svelte"; export { default as Item } from "$lib/bits/menu/components/menu-item.svelte"; export { default as Group } from "$lib/bits/menu/components/menu-group.svelte"; -export { default as Label } from "$lib/bits/menu/components/menu-label.svelte"; +export { default as Label } from "$lib/bits/menu/components/menu-group-label.svelte"; export { default as Arrow } from "$lib/bits/menu/components/menu-arrow.svelte"; export { default as Content } from "./components/context-menu-content.svelte"; export { default as Trigger } from "./components/context-menu-trigger.svelte"; @@ -19,7 +19,7 @@ export type { ContextMenuCheckboxItemProps as CheckboxItemProps, ContextMenuGroupProps as GroupProps, ContextMenuItemProps as ItemProps, - ContextMenuLabelProps as LabelProps, + ContextMenuGroupLabelProps as GroupLabelProps, ContextMenuRootProps as RootProps, ContextMenuRadioGroupProps as RadioGroupProps, ContextMenuRadioItemProps as RadioItemProps, diff --git a/packages/bits-ui/src/lib/bits/context-menu/types.ts b/packages/bits-ui/src/lib/bits/context-menu/types.ts index 6e73f6282..8463ba88e 100644 --- a/packages/bits-ui/src/lib/bits/context-menu/types.ts +++ b/packages/bits-ui/src/lib/bits/context-menu/types.ts @@ -25,7 +25,7 @@ export type { CheckboxItemProps as ContextMenuCheckboxItemProps, GroupProps as ContextMenuGroupProps, ItemProps as ContextMenuItemProps, - LabelProps as ContextMenuLabelProps, + GroupLabelProps as ContextMenuGroupLabelProps, RootProps as ContextMenuRootProps, RadioGroupProps as ContextMenuRadioGroupProps, RadioItemProps as ContextMenuRadioItemProps, @@ -42,7 +42,7 @@ export type { MenuCheckboxItemPropsWithoutHTML as ContextMenuCheckboxItemPropsWithoutHTML, MenuGroupPropsWithoutHTML as ContextMenuGroupPropsWithoutHTML, MenuItemPropsWithoutHTML as ContextMenuItemPropsWithoutHTML, - MenuLabelPropsWithoutHTML as ContextMenuLabelPropsWithoutHTML, + MenuGroupLabelPropsWithoutHTML as ContextMenuLabelPropsWithoutHTML, MenuRadioGroupPropsWithoutHTML as ContextMenuRadioGroupPropsWithoutHTML, MenuRadioItemPropsWithoutHTML as ContextMenuRadioItemPropsWithoutHTML, MenuSeparatorPropsWithoutHTML as ContextMenuSeparatorPropsWithoutHTML, diff --git a/packages/bits-ui/src/lib/bits/dropdown-menu/index.ts b/packages/bits-ui/src/lib/bits/dropdown-menu/index.ts index db8eb7702..ebc2427bd 100644 --- a/packages/bits-ui/src/lib/bits/dropdown-menu/index.ts +++ b/packages/bits-ui/src/lib/bits/dropdown-menu/index.ts @@ -2,7 +2,7 @@ export { default as Root } from "$lib/bits/menu/components/menu.svelte"; export { default as Sub } from "$lib/bits/menu/components/menu-sub.svelte"; export { default as Item } from "$lib/bits/menu/components/menu-item.svelte"; export { default as Group } from "$lib/bits/menu/components/menu-group.svelte"; -export { default as Label } from "$lib/bits/menu/components/menu-label.svelte"; +export { default as GroupLabel } from "$lib/bits/menu/components/menu-group-label.svelte"; export { default as Arrow } from "$lib/bits/menu/components/menu-arrow.svelte"; export { default as Content } from "./components/dropdown-menu-content.svelte"; export { default as Trigger } from "$lib/bits/menu/components/menu-trigger.svelte"; @@ -20,7 +20,7 @@ export type { DropdownMenuContentProps as ContentProps, DropdownMenuGroupProps as GroupProps, DropdownMenuItemProps as ItemProps, - DropdownMenuLabelProps as LabelProps, + DropdownMenuGroupLabelProps as GroupLabelProps, DropdownMenuRootProps as RootProps, DropdownMenuRadioGroupProps as RadioGroupProps, DropdownMenuRadioItemProps as RadioItemProps, diff --git a/packages/bits-ui/src/lib/bits/dropdown-menu/types.ts b/packages/bits-ui/src/lib/bits/dropdown-menu/types.ts index 96cd15353..8e5b729a4 100644 --- a/packages/bits-ui/src/lib/bits/dropdown-menu/types.ts +++ b/packages/bits-ui/src/lib/bits/dropdown-menu/types.ts @@ -4,7 +4,7 @@ export type { ContentProps as DropdownMenuContentProps, GroupProps as DropdownMenuGroupProps, ItemProps as DropdownMenuItemProps, - LabelProps as DropdownMenuLabelProps, + GroupLabelProps as DropdownMenuGroupLabelProps, RootProps as DropdownMenuRootProps, RadioGroupProps as DropdownMenuRadioGroupProps, RadioItemProps as DropdownMenuRadioItemProps, @@ -23,7 +23,7 @@ export type { MenuContentPropsWithoutHTML as DropdownMenuContentPropsWithoutHTML, MenuGroupPropsWithoutHTML as DropdownMenuGroupPropsWithoutHTML, MenuItemPropsWithoutHTML as DropdownMenuItemPropsWithoutHTML, - MenuLabelPropsWithoutHTML as DropdownMenuLabelPropsWithoutHTML, + MenuGroupLabelPropsWithoutHTML as DropdownMenuLabelPropsWithoutHTML, MenuRadioGroupPropsWithoutHTML as DropdownMenuRadioGroupPropsWithoutHTML, MenuRadioItemPropsWithoutHTML as DropdownMenuRadioItemPropsWithoutHTML, MenuSeparatorPropsWithoutHTML as DropdownMenuSeparatorPropsWithoutHTML, diff --git a/packages/bits-ui/src/lib/bits/menu/components/menu-label.svelte b/packages/bits-ui/src/lib/bits/menu/components/menu-group-label.svelte similarity index 72% rename from packages/bits-ui/src/lib/bits/menu/components/menu-label.svelte rename to packages/bits-ui/src/lib/bits/menu/components/menu-group-label.svelte index 7ef3ac847..023464753 100644 --- a/packages/bits-ui/src/lib/bits/menu/components/menu-label.svelte +++ b/packages/bits-ui/src/lib/bits/menu/components/menu-group-label.svelte @@ -1,6 +1,6 @@ {#if child} diff --git a/packages/bits-ui/src/lib/bits/menu/index.ts b/packages/bits-ui/src/lib/bits/menu/index.ts index 1ab2e66ef..204dec8a8 100644 --- a/packages/bits-ui/src/lib/bits/menu/index.ts +++ b/packages/bits-ui/src/lib/bits/menu/index.ts @@ -4,7 +4,7 @@ export { default as CheckboxItem } from "./components/menu-checkbox-item.svelte" export { default as Content } from "./components/menu-content.svelte"; export { default as Group } from "./components/menu-group.svelte"; export { default as Item } from "./components/menu-item.svelte"; -export { default as Label } from "./components/menu-label.svelte"; +export { default as GroupLabel } from "./components/menu-group-label.svelte"; export { default as Portal } from "$lib/bits/utilities/portal/portal.svelte"; export { default as RadioGroup } from "./components/menu-radio-group.svelte"; export { default as RadioItem } from "./components/menu-radio-item.svelte"; @@ -24,7 +24,7 @@ export type { MenuSeparatorProps as SeparatorProps, MenuArrowProps as ArrowProps, MenuCheckboxItemProps as CheckboxItemProps, - MenuLabelProps as LabelProps, + MenuGroupLabelProps as GroupLabelProps, MenuGroupProps as GroupProps, MenuRadioGroupProps as RadioGroupProps, MenuRadioItemProps as RadioItemProps, diff --git a/packages/bits-ui/src/lib/bits/menu/menu.svelte.ts b/packages/bits-ui/src/lib/bits/menu/menu.svelte.ts index 557f94257..aa822bd9e 100644 --- a/packages/bits-ui/src/lib/bits/menu/menu.svelte.ts +++ b/packages/bits-ui/src/lib/bits/menu/menu.svelte.ts @@ -20,7 +20,7 @@ import { addEventListener } from "$lib/internal/events.js"; import type { AnyFn, WithRefProps } from "$lib/internal/types.js"; import { executeCallbacks } from "$lib/internal/callbacks.js"; import { useTypeahead } from "$lib/internal/useTypeahead.svelte.js"; -import { isBrowser, isElement, isHTMLElement } from "$lib/internal/is.js"; +import { isElement, isHTMLElement } from "$lib/internal/is.js"; import { useRovingFocus } from "$lib/internal/useRovingFocus.svelte.js"; import { kbd } from "$lib/internal/kbd.js"; import { @@ -61,6 +61,8 @@ const [setMenuMenuContext, getMenuMenuContext] = createContext( const [setMenuContentContext, getMenuContentContext] = createContext("Menu.Content"); +const [setMenuGroupContext, getMenuGroupContext] = createContext("Menu.Group"); + const [setMenuRadioGroupContext, getMenuRadioGroupContext] = createContext("Menu.RadioGroup"); @@ -698,6 +700,7 @@ type MenuGroupStateProps = WithRefProps; class MenuGroupState { #id: MenuGroupStateProps["id"]; #ref: MenuGroupStateProps["ref"]; + labelNode = $state(null); constructor(props: MenuGroupStateProps) { this.#id = props.id; @@ -714,23 +717,33 @@ class MenuGroupState { ({ id: this.#id.current, role: "group", + "aria-labelledby": this.labelNode?.id ?? undefined, [GROUP_ATTR]: "", }) as const ); + + createGroupLabel(props: MenuGroupLabelStateProps) { + return new MenuGroupLabelState(props, this); + } } -type MenuLabelStateProps = WithRefProps; -class MenuLabelState { - #id: MenuLabelStateProps["id"]; - #ref: MenuLabelStateProps["ref"]; +type MenuGroupLabelStateProps = WithRefProps; +class MenuGroupLabelState { + #id: MenuGroupLabelStateProps["id"]; + #ref: MenuGroupLabelStateProps["ref"]; + #group: MenuGroupState; - constructor(props: MenuLabelStateProps) { + constructor(props: MenuGroupLabelStateProps, group: MenuGroupState) { this.#id = props.id; this.#ref = props.ref; + this.#group = group; useRefById({ id: this.#id, ref: this.#ref, + onRefChange: (node) => { + this.#group.labelNode = node; + }, }); } @@ -1114,11 +1127,11 @@ export function useMenuRadioItem(props: MenuRadioItemStateProps & MenuItemCombin } export function useMenuGroup(props: MenuGroupStateProps) { - return new MenuGroupState(props); + return setMenuGroupContext(new MenuGroupState(props)); } -export function useMenuLabel(props: MenuLabelStateProps) { - return new MenuLabelState(props); +export function useMenuLabel(props: MenuGroupLabelStateProps) { + return getMenuGroupContext().createGroupLabel(props); } export function useMenuSeparator(props: MenuSeparatorStateProps) { diff --git a/packages/bits-ui/src/lib/bits/menu/types.ts b/packages/bits-ui/src/lib/bits/menu/types.ts index c90c37085..150faf253 100644 --- a/packages/bits-ui/src/lib/bits/menu/types.ts +++ b/packages/bits-ui/src/lib/bits/menu/types.ts @@ -125,9 +125,9 @@ export type MenuGroupPropsWithoutHTML = WithChild; export type MenuGroupProps = MenuGroupPropsWithoutHTML & Without; -export type MenuLabelPropsWithoutHTML = WithChild; -export type MenuLabelProps = MenuLabelPropsWithoutHTML & - Without; +export type MenuGroupLabelPropsWithoutHTML = WithChild; +export type MenuGroupLabelProps = MenuGroupLabelPropsWithoutHTML & + Without; export type MenuRadioGroupPropsWithoutHTML = WithChild<{ /** diff --git a/packages/bits-ui/src/lib/bits/menubar/index.ts b/packages/bits-ui/src/lib/bits/menubar/index.ts index ee7ec284f..6ce7763aa 100644 --- a/packages/bits-ui/src/lib/bits/menubar/index.ts +++ b/packages/bits-ui/src/lib/bits/menubar/index.ts @@ -5,7 +5,7 @@ export { default as Trigger } from "./components/menubar-trigger.svelte"; export { default as Sub } from "$lib/bits/menu/components/menu-sub.svelte"; export { default as Item } from "$lib/bits/menu/components/menu-item.svelte"; export { default as Group } from "$lib/bits/menu/components/menu-group.svelte"; -export { default as Label } from "$lib/bits/menu/components/menu-label.svelte"; +export { default as Label } from "$lib/bits/menu/components/menu-group-label.svelte"; export { default as Arrow } from "$lib/bits/menu/components/menu-arrow.svelte"; export { default as RadioItem } from "$lib/bits/menu/components/menu-radio-item.svelte"; export { default as Separator } from "$lib/bits/menu/components/menu-separator.svelte"; @@ -25,7 +25,7 @@ export type { MenuSubPropsWithoutHTML as SubProps, MenuItemProps as ItemProps, MenuGroupProps as GroupProps, - MenuLabelProps as LabelProps, + MenuGroupLabelProps as LabelProps, MenuArrowProps as ArrowProps, MenuRadioItemProps as RadioItemProps, MenuSeparatorProps as SeparatorProps, diff --git a/packages/bits-ui/src/lib/bits/menubar/types.ts b/packages/bits-ui/src/lib/bits/menubar/types.ts index dfb728945..dde65b005 100644 --- a/packages/bits-ui/src/lib/bits/menubar/types.ts +++ b/packages/bits-ui/src/lib/bits/menubar/types.ts @@ -1,7 +1,8 @@ -import type { MenuContentProps, MenuContentPropsWithoutHTML } from "../menu/types.js"; import type { OnChangeFn, WithChild, WithChildren, Without } from "$lib/internal/types.js"; import type { PrimitiveButtonAttributes, PrimitiveDivAttributes } from "$lib/shared/attributes.js"; import type { Direction } from "$lib/shared/index.js"; +import type { ArrowPropsWithoutHTML } from "../utilities/arrow/types.js"; +import type { ArrowProps } from "../menu/index.js"; export type MenubarRootPropsWithoutHTML = WithChild<{ /** @@ -51,6 +52,30 @@ export type MenubarTriggerPropsWithoutHTML = WithChild<{ export type MenubarTriggerProps = MenubarTriggerPropsWithoutHTML & Without; -export type MenubarContentPropsWithoutHTML = MenuContentPropsWithoutHTML; +export type { + MenuContentPropsWithoutHTML as MenubarContentPropsWithoutHTML, + MenuContentProps as MenubarContentProps, + MenuItemPropsWithoutHTML as MenubarItemPropsWithoutHTML, + MenuItemProps as MenubarItemProps, + MenuGroupPropsWithoutHTML as MenubarGroupPropsWithoutHTML, + MenuGroupProps as MenubarGroupProps, + MenuGroupLabelPropsWithoutHTML as MenubarGroupLabelPropsWithoutHTML, + MenuGroupLabelProps as MenubarGroupLabelProps, + MenuCheckboxItemPropsWithoutHTML as MenubarCheckboxItemPropsWithoutHTML, + MenuCheckboxItemProps as MenubarCheckboxItemProps, + MenuRadioGroupPropsWithoutHTML as MenubarRadioGroupPropsWithoutHTML, + MenuRadioGroupProps as MenubarRadioGroupProps, + MenuRadioItemPropsWithoutHTML as MenubarRadioItemPropsWithoutHTML, + MenuRadioItemProps as MenubarRadioItemProps, + MenuSeparatorPropsWithoutHTML as MenubarSeparatorPropsWithoutHTML, + MenuSeparatorProps as MenubarSeparatorProps, + MenuSubContentPropsWithoutHTML as MenubarSubContentPropsWithoutHTML, + MenuSubContentProps as MenubarSubContentProps, + MenuSubTriggerPropsWithoutHTML as MenubarSubTriggerPropsWithoutHTML, + MenuSubTriggerProps as MenubarSubTriggerProps, + MenuSubPropsWithoutHTML as MenubarSubPropsWithoutHTML, +} from "../menu/types.js"; -export type MenubarContentProps = MenuContentProps; +export type MenubarArrowPropsWithoutHTML = ArrowPropsWithoutHTML; + +export type MenubarArrowProps = ArrowProps; diff --git a/packages/bits-ui/src/lib/bits/navigation-menu/types.ts b/packages/bits-ui/src/lib/bits/navigation-menu/types.ts index 485131c8e..a1506a7de 100644 --- a/packages/bits-ui/src/lib/bits/navigation-menu/types.ts +++ b/packages/bits-ui/src/lib/bits/navigation-menu/types.ts @@ -25,16 +25,22 @@ export type NavigationMenuRootPropsWithoutHTML = WithChild<{ /** * The duration from when the mouse enters a trigger until the content opens. + * + * @defaultValue 200 */ delayDuration?: number; /** * How much time a user has to enter another trigger without incurring a delay again. + * + * @defaultValue 300 */ skipDelayDuration?: number; /** * The reading direction of the content. + * + * @defaultValue "ltr" */ dir?: Direction; diff --git a/packages/bits-ui/src/lib/bits/select/types.ts b/packages/bits-ui/src/lib/bits/select/types.ts index bf59c11c9..e3228585f 100644 --- a/packages/bits-ui/src/lib/bits/select/types.ts +++ b/packages/bits-ui/src/lib/bits/select/types.ts @@ -64,7 +64,7 @@ export type SelectRootPropsWithoutHTML = WithChildren<{ export type SelectRootProps = SelectRootPropsWithoutHTML; export type SelectContentImplPropsWithoutHTML = WithChild< - PopperLayerProps & { + Omit & { /** * The positioning mode to use * diff --git a/packages/bits-ui/src/lib/bits/switch/types.ts b/packages/bits-ui/src/lib/bits/switch/types.ts index 20e8bb132..3027bfc38 100644 --- a/packages/bits-ui/src/lib/bits/switch/types.ts +++ b/packages/bits-ui/src/lib/bits/switch/types.ts @@ -47,10 +47,6 @@ export type SwitchRootPropsWithoutHTML = WithChild< * A callback function called when the checked state changes. */ onCheckedChange?: OnChangeFn; - - onclick?: EventCallback; - - onkeydown?: EventCallback; }, SwitchRootSnippetProps >; diff --git a/packages/bits-ui/src/lib/bits/tabs/types.ts b/packages/bits-ui/src/lib/bits/tabs/types.ts index 4897791e3..fa909a844 100644 --- a/packages/bits-ui/src/lib/bits/tabs/types.ts +++ b/packages/bits-ui/src/lib/bits/tabs/types.ts @@ -35,7 +35,7 @@ export type TabsRootPropsWithoutHTML = WithChild<{ * will be activated when the trigger is focused. If set to `'manual'`, * the tabs will be activated when the trigger is pressed. * - * @defaultValue true + * @defaultValue "automatic" */ activationMode?: TabsActivationMode; diff --git a/packages/bits-ui/src/lib/bits/utilities/focus-scope/types.ts b/packages/bits-ui/src/lib/bits/utilities/focus-scope/types.ts index e7e3c8cb3..352885b5f 100644 --- a/packages/bits-ui/src/lib/bits/utilities/focus-scope/types.ts +++ b/packages/bits-ui/src/lib/bits/utilities/focus-scope/types.ts @@ -14,6 +14,13 @@ export type FocusScopeProps = { * Can be prevented. */ onDestroyAutoFocus?: EventCallback; + + /** + * When `true` will loop through the tabbable elements in the focus scope. + * + * @defaultValue false + */ + loop?: boolean; }; export type FocusScopeImplProps = { @@ -29,12 +36,5 @@ export type FocusScopeImplProps = { */ trapped?: boolean; - /** - * When `true` will loop through the tabbable elements in the focus scope. - * - * @defaultValue false - */ - loop?: boolean; - focusScope?: Snippet<[{ props: FocusScopeContainerProps }]>; } & FocusScopeProps; diff --git a/packages/bits-ui/src/tests/dropdown-menu/DropdownMenuTest.svelte b/packages/bits-ui/src/tests/dropdown-menu/DropdownMenuTest.svelte index 508b34383..2163c1520 100644 --- a/packages/bits-ui/src/tests/dropdown-menu/DropdownMenuTest.svelte +++ b/packages/bits-ui/src/tests/dropdown-menu/DropdownMenuTest.svelte @@ -35,7 +35,7 @@ - Stuff + Stuff item diff --git a/sites/docs/src/lib/content/api-reference/helpers.ts b/sites/docs/src/lib/content/api-reference/helpers.ts index 37432fed6..3ccf7288c 100644 --- a/sites/docs/src/lib/content/api-reference/helpers.ts +++ b/sites/docs/src/lib/content/api-reference/helpers.ts @@ -21,6 +21,8 @@ type ElementKind = | "HTMLHeadingElement" | "HTMLImageElement" | "HTMLInputElement" + | "HTMLUListElement" + | "HTMLLiElement" | "HTMLElement"; export function domElProps(elType: ElementKind) { diff --git a/sites/docs/src/lib/content/api-reference/index.ts b/sites/docs/src/lib/content/api-reference/index.ts index ebb16fff5..285f112ec 100644 --- a/sites/docs/src/lib/content/api-reference/index.ts +++ b/sites/docs/src/lib/content/api-reference/index.ts @@ -16,6 +16,7 @@ import { dialog } from "./dialog.js"; import { dropdownMenu } from "./dropdown-menu.js"; import { label } from "./label.js"; import { linkPreview } from "./link-preview.js"; +import { navigationMenu } from "./navigation-menu.js"; import { pagination } from "./pagination.js"; import { pinInput } from "./pin-input.js"; import { popover } from "./popover.js"; @@ -33,6 +34,7 @@ import { toggle } from "./toggle.js"; import { toolbar } from "./toolbar.js"; import { tooltip } from "./tooltip.js"; import type { APISchema } from "$lib/types/index.js"; +import { menubar } from "./menubar.js"; export const bits = [ "accordion", @@ -53,7 +55,6 @@ export const bits = [ "dropdown-menu", "label", "link-preview", - "listbox", "menubar", "navigation-menu", "pagination", @@ -101,7 +102,8 @@ export const apiSchemas: Record = { "dropdown-menu": dropdownMenu, label, "link-preview": linkPreview, - listbox: linkPreview, + menubar: menubar, + "navigation-menu": navigationMenu, pagination, "pin-input": pinInput, popover, diff --git a/sites/docs/src/lib/content/api-reference/menu.ts b/sites/docs/src/lib/content/api-reference/menu.ts index fafa5ebfe..027e2427d 100644 --- a/sites/docs/src/lib/content/api-reference/menu.ts +++ b/sites/docs/src/lib/content/api-reference/menu.ts @@ -93,20 +93,18 @@ const contentProps = { forceMount: forceMountProp, preventOverflowTextSelection: preventOverflowTextSelectionProp, dir: dirProp, + loop: { + default: C.FALSE, + type: C.BOOLEAN, + description: + "Whether or not to loop through the menu items in when navigating with the keyboard.", + }, ...withChildProps({ elType: "HTMLDivElement" }), } satisfies PropObj; -const subContentProps = { - ...floatingProps(), - ...escapeLayerProps, - ...dismissableLayerProps, - ...focusScopeProps, - forceMount: forceMountProp, - preventScroll: preventScrollProp(), - preventOverflowTextSelection: preventOverflowTextSelectionProp, - ...withChildProps({ elType: "HTMLDivElement" }), - dir: dirProp, -} satisfies PropObj>; +const subContentProps = contentProps satisfies PropObj< + Omit +>; const checkboxItemProps = { disabled: { diff --git a/sites/docs/src/lib/content/api-reference/menubar.ts b/sites/docs/src/lib/content/api-reference/menubar.ts index 4f08d0424..a4cff4672 100644 --- a/sites/docs/src/lib/content/api-reference/menubar.ts +++ b/sites/docs/src/lib/content/api-reference/menubar.ts @@ -1,172 +1,165 @@ -// import type { -// MenubarArrowPropsWithoutHTML, -// MenubarCheckboxIndicatorPropsWithoutHTML, -// MenubarCheckboxItemPropsWithoutHTML, -// MenubarContentPropsWithoutHTML, -// MenubarGroupPropsWithoutHTML, -// MenubarItemPropsWithoutHTML, -// MenubarLabelPropsWithoutHTML, -// MenubarMenuPropsWithoutHTML, -// MenubarPropsWithoutHTML, -// MenubarRadioGroupPropsWithoutHTML, -// MenubarRadioIndicatorPropsWithoutHTML, -// MenubarRadioItemPropsWithoutHTML, -// MenubarSeparatorPropsWithoutHTML, -// MenubarSubContentPropsWithoutHTML, -// MenubarSubPropsWithoutHTML, -// MenubarSubTriggerPropsWithoutHTML, -// MenubarTriggerPropsWithoutHTML, -// } from "bits-ui"; -// import { builderAndAttrsSlotProps, domElProps } from "./helpers.js"; -// import { menu as m } from "./menu.js"; -// import { idsSlotProp } from "$lib/content/api-reference/helpers.js"; -// import * as C from "$lib/content/constants.js"; -// import type { APISchema } from "$lib/types/index.js"; - -// export const root: APISchema = { -// title: "Root", -// description: "The root menubar component which manages & scopes the state of the menubar.", -// props: { -// closeOnEscape: { -// default: C.TRUE, -// type: C.BOOLEAN, -// description: "Whether to close the open menubar menu when the escape key is pressed.", -// }, -// loop: { -// default: C.TRUE, -// type: C.BOOLEAN, -// description: -// "Whether or not to loop through the menubar menu triggers when navigating with the keyboard.", -// }, -// preventScroll: { -// default: C.FALSE, -// type: C.BOOLEAN, -// description: -// "Whether or not to prevent scrolling the body while a menu in the menubar is open.", -// }, -// ...domElProps("HTMLDivElement"), -// }, -// slotProps: { ...builderAndAttrsSlotProps, ids: idsSlotProp }, -// }; - -// export const menu: APISchema = { -// title: "Menu", -// description: "A menu within the menubar.", -// ...m.root, -// }; - -// export const trigger: APISchema = { -// title: "Trigger", -// description: "The button element which toggles the dropdown menu.", -// ...m.trigger, -// }; - -// export const content: APISchema = { -// title: "Content", -// description: "The content displayed when the dropdown menu is open.", -// ...m.content, -// }; - -// export const item: APISchema = { -// title: "Item", -// description: "A menu item within the dropdown menu.", -// ...m.item, -// }; - -// export const separator: APISchema = { -// title: "Separator", -// description: "A horizontal line to visually separate menu items.", -// ...m.separator, -// }; - -// export const arrow: APISchema = { -// title: "Arrow", -// description: "An optional arrow which points to the dropdown menu's anchor/trigger point.", -// ...m.arrow, -// }; - -// export const checkboxItem: APISchema = { -// title: "CheckboxItem", -// description: "A menu item that can be controlled and toggled like a checkbox.", -// ...m.checkboxItem, -// }; - -// export const checkboxIndicator: APISchema = { -// title: "CheckboxIndicator", -// description: -// "A visual indicator of the checkbox menu item's checked state. It passed the item's checked state as a slot prop `checked` and can be used to render a custom indicator.", -// ...m.checkboxIndicator, -// }; - -// export const radioGroup: APISchema = { -// title: "RadioGroup", -// description: "A group of radio menu items, where only one can be checked at a time.", -// ...m.radioGroup, -// }; - -// export const radioItem: APISchema = { -// title: "RadioItem", -// description: -// "A menu item that can be controlled and toggled like a radio button. It must be a child of a `RadioGroup`.", -// ...m.radioItem, -// }; - -// export const radioIndicator: APISchema = { -// title: "RadioIndicator", -// description: -// "A visual indicator helper for `RadioItem`s. It only renders it's children when the radio item is checked.", -// ...m.radioIndicator, -// }; - -// export const sub: APISchema = { -// title: "Sub", -// description: -// "A submenu belonging to the parent dropdown menu. Responsible for managing the state of the submenu.", -// ...m.sub, -// }; - -// export const subTrigger: APISchema = { -// title: "SubTrigger", -// description: "A menu item which when pressed or hovered, opens the submenu.", -// ...m.subTrigger, -// }; - -// export const subContent: APISchema = { -// title: "SubContent", -// description: "The submenu content displayed when the parent submenu is open.", -// ...m.subContent, -// }; - -// export const group: APISchema = { -// title: "Group", -// description: -// "A group of menu items. It can be used along with the `Menu.Label` component to provide a visual label for a group of menu items. When a label is within a group, appropriate aria attributes will be applied to the group.", -// ...m.group, -// }; - -// export const label: APISchema = { -// title: "Label", -// description: -// "A label which will be skipped when navigating with the keyboard. It is used to provide a visual label for a group of menu items. When a label is within a `Menu.Group`, appropriate aria attributes will be applied to the group.", -// ...m.label, -// }; - -// export const menubar = [ -// root, -// menu, -// trigger, -// content, -// item, -// checkboxItem, -// checkboxIndicator, -// radioGroup, -// radioItem, -// radioIndicator, -// separator, -// arrow, -// group, -// label, -// sub, -// subTrigger, -// subContent, -// ]; +import type { + MenubarArrowPropsWithoutHTML, + MenubarCheckboxItemPropsWithoutHTML, + MenubarContentPropsWithoutHTML, + MenubarGroupPropsWithoutHTML, + MenubarItemPropsWithoutHTML, + MenubarGroupLabelPropsWithoutHTML, + MenubarMenuPropsWithoutHTML, + MenubarRootPropsWithoutHTML, + MenubarRadioGroupPropsWithoutHTML, + MenubarRadioItemPropsWithoutHTML, + MenubarSeparatorPropsWithoutHTML, + MenubarSubContentPropsWithoutHTML, + MenubarSubPropsWithoutHTML, + MenubarSubTriggerPropsWithoutHTML, + MenubarTriggerPropsWithoutHTML, +} from "bits-ui"; +import { builderAndAttrsSlotProps, dirProp, domElProps, withChildProps } from "./helpers.js"; +import { menu as m } from "./menu.js"; +import { idsSlotProp } from "$lib/content/api-reference/helpers.js"; +import * as C from "$lib/content/constants.js"; +import type { APISchema } from "$lib/types/index.js"; + +export const root: APISchema = { + title: "Root", + description: "The root menubar component which manages & scopes the state of the menubar.", + props: { + value: { + type: C.STRING, + description: "The value of the currently active menu.", + bindable: true, + }, + dir: dirProp, + onValueChange: { + type: { + type: C.FUNCTION, + definition: "(value: string | undefined) => void", + }, + description: "A callback function called when the active menu value changes.", + }, + loop: { + default: C.TRUE, + type: C.BOOLEAN, + description: + "Whether or not to loop through the menubar menu triggers when navigating with the keyboard.", + }, + + ...withChildProps({ elType: "HTMLDivElement" }), + }, + slotProps: { ...builderAndAttrsSlotProps, ids: idsSlotProp }, +}; + +export const menu: APISchema = { + title: "Menu", + description: "A menu within the menubar.", + ...m.root, + props: { + value: { + type: C.STRING, + description: + "The value of this menu within the menubar, used to identify it when determining which menu is active.", + }, + ...m.root.props, + }, +}; + +export const trigger: APISchema = { + title: "Trigger", + description: "The button element which toggles the dropdown menu.", + ...m.trigger, +}; + +export const content: APISchema = { + title: "Content", + description: "The content displayed when the dropdown menu is open.", + ...m.content, +}; + +export const item: APISchema = { + title: "Item", + description: "A menu item within the dropdown menu.", + ...m.item, +}; + +export const separator: APISchema = { + title: "Separator", + description: "A horizontal line to visually separate menu items.", + ...m.separator, +}; + +export const arrow: APISchema = { + title: "Arrow", + description: "An optional arrow which points to the dropdown menu's anchor/trigger point.", + ...m.arrow, +}; + +export const checkboxItem: APISchema = { + title: "CheckboxItem", + description: "A menu item that can be controlled and toggled like a checkbox.", + ...m.checkboxItem, +}; + +export const radioGroup: APISchema = { + title: "RadioGroup", + description: "A group of radio menu items, where only one can be checked at a time.", + ...m.radioGroup, +}; + +export const radioItem: APISchema = { + title: "RadioItem", + description: + "A menu item that can be controlled and toggled like a radio button. It must be a child of a `RadioGroup`.", + ...m.radioItem, +}; + +export const sub: APISchema = { + title: "Sub", + description: + "A submenu belonging to the parent dropdown menu. Responsible for managing the state of the submenu.", + ...m.sub, +}; + +export const subTrigger: APISchema = { + title: "SubTrigger", + description: "A menu item which when pressed or hovered, opens the submenu.", + ...m.subTrigger, +}; + +export const subContent: APISchema = { + title: "SubContent", + description: "The submenu content displayed when the parent submenu is open.", + ...m.subContent, +}; + +export const group: APISchema = { + title: "Group", + description: + "A group of menu items. It can be used along with the `Menu.Label` component to provide a visual label for a group of menu items. When a label is within a group, appropriate aria attributes will be applied to the group.", + ...m.group, +}; + +export const groupLabel: APISchema = { + title: "GroupLabel", + description: + "A label which will be skipped when navigating with the keyboard. It is used to provide a visual label for a group of menu items. When a label is within a `Menu.Group`, appropriate aria attributes will be applied to the group.", + ...m.label, +}; + +export const menubar = [ + root, + menu, + trigger, + content, + item, + checkboxItem, + radioGroup, + radioItem, + separator, + arrow, + group, + groupLabel, + sub, + subTrigger, + subContent, +]; diff --git a/sites/docs/src/lib/content/api-reference/navigation-menu.ts b/sites/docs/src/lib/content/api-reference/navigation-menu.ts new file mode 100644 index 000000000..2b0d5d8d6 --- /dev/null +++ b/sites/docs/src/lib/content/api-reference/navigation-menu.ts @@ -0,0 +1,150 @@ +import type { + NavigationMenuRootPropsWithoutHTML, + NavigationMenuContentPropsWithoutHTML, + NavigationMenuIndicatorPropsWithoutHTML, + NavigationMenuItemPropsWithoutHTML, + NavigationMenuLinkPropsWithoutHTML, + NavigationMenuListPropsWithoutHTML, + NavigationMenuTriggerPropsWithoutHTML, + NavigationMenuViewportPropsWithoutHTML, +} from "bits-ui"; +import { + dirProp, + dismissableLayerProps, + enums, + escapeLayerProps, + floatingProps, + forceMountProp, + withChildProps, +} from "./helpers.js"; +import * as C from "$lib/content/constants.js"; +import type { APISchema } from "$lib/types/index.js"; + +export const root: APISchema = { + title: "Root", + description: + "The root navigation menu component which manages & scopes the state of the navigation menu.", + props: { + value: { + type: C.STRING, + description: "The value of the currently active menu.", + bindable: true, + }, + onValueChange: { + type: { + type: C.FUNCTION, + definition: "(value: string | undefined) => void", + }, + description: "A callback function called when the active menu value changes.", + }, + dir: dirProp, + skipDelayDuration: { + type: C.NUMBER, + default: "300", + description: + "How much time a user has to enter another trigger without incurring a delay again.", + }, + delayDuration: { + type: C.NUMBER, + default: "200", + description: + "The duration from when the mouse enters a trigger until the content opens.", + }, + orientation: { + type: { + type: C.ENUM, + definition: enums("horizontal", "vertical"), + }, + default: "horizontal", + description: "The orientation of the menu.", + }, + ...withChildProps({ elType: "HTMLDivElement" }), + }, +}; + +export const list: APISchema = { + title: "List", + description: "A menu within the menubar.", + props: { + ...withChildProps({ elType: "HTMLUListElement" }), + }, +}; + +export const item: APISchema = { + title: "Item", + description: "A list item within the navigation menu.", + props: { + value: { + type: C.STRING, + description: "The value of the item.", + }, + ...withChildProps({ elType: "HTMLLiElement" }), + }, +}; + +export const trigger: APISchema = { + title: "Trigger", + description: "The button element which toggles the dropdown menu.", + props: { + disabled: { + default: C.FALSE, + type: C.BOOLEAN, + description: "Whether or not the trigger is disabled.", + }, + ...withChildProps({ elType: "HTMLButtonElement" }), + }, +}; + +export const content: APISchema = { + title: "Content", + description: "The content displayed when the dropdown menu is open.", + props: { + ...floatingProps(), + ...dismissableLayerProps, + ...escapeLayerProps, + forceMount: forceMountProp, + ...withChildProps({ elType: "HTMLDivElement" }), + }, +}; + +export const link: APISchema = { + title: "Link", + description: "A link within the navigation menu.", + props: { + active: { + type: C.BOOLEAN, + default: C.FALSE, + description: "Whether or not the link is active.", + }, + onSelect: { + type: { + type: C.FUNCTION, + definition: "() => void", + }, + description: "A callback function called when the link is selected.", + }, + ...withChildProps({ elType: "HTMLAnchorElement" }), + }, +}; + +export const indicator: APISchema = { + title: "Indicator", + description: + "The indicator element for the navigation menu, which is used to indicate the current active item.", + props: { + forceMount: forceMountProp, + ...withChildProps({ elType: "HTMLSpanElement" }), + }, +}; + +export const viewport: APISchema = { + title: "Viewport", + description: + "The viewport element for the navigation menu, which is used to contain the menu items.", + props: { + forceMount: forceMountProp, + ...withChildProps({ elType: "HTMLDivElement" }), + }, +}; + +export const navigationMenu = [root, list, item, trigger, content, link, viewport, indicator]; diff --git a/sites/docs/src/lib/content/api-reference/select.ts b/sites/docs/src/lib/content/api-reference/select.ts index 7bd9519a0..d855efd06 100644 --- a/sites/docs/src/lib/content/api-reference/select.ts +++ b/sites/docs/src/lib/content/api-reference/select.ts @@ -1,24 +1,30 @@ import type { SelectArrowPropsWithoutHTML, SelectContentPropsWithoutHTML, + SelectGroupLabelPropsWithoutHTML, SelectGroupPropsWithoutHTML, SelectItemPropsWithoutHTML, SelectRootPropsWithoutHTML, SelectSeparatorPropsWithoutHTML, SelectTriggerPropsWithoutHTML, } from "bits-ui"; -import { floatingPositioning } from "./floating.js"; import { arrowProps, asChild, attrsSlotProp, builderAndAttrsSlotProps, - domElProps, + childrenSnippet, + dirProp, + dismissableLayerProps, enums, + escapeLayerProps, + floatingProps, + focusScopeProps, + forceMountProp, idsSlotProp, - onOutsideClickProp, - portalProp, - transitionProps, + preventOverflowTextSelectionProp, + preventScrollProp, + withChildProps, } from "$lib/content/api-reference/helpers.js"; import * as C from "$lib/content/constants.js"; import type { APISchema } from "$lib/types/index.js"; @@ -32,31 +38,25 @@ export const root: APISchema = { type: C.BOOLEAN, description: "Whether or not the select menu is disabled.", }, - multiple: { - default: C.FALSE, - type: C.BOOLEAN, - description: "Whether or not the select menu allows multiple selections.", - }, - preventScroll: { - default: C.TRUE, - type: C.BOOLEAN, - description: "Whether or not to prevent scrolling the body when the menu is open.", + autocomplete: { + type: C.STRING, + description: "The autocomplete attribute of the select.", }, - closeOnEscape: { - default: C.TRUE, - type: C.BOOLEAN, - description: "Whether to close the select menu when the escape key is pressed.", + dir: dirProp, + form: { + type: C.STRING, + description: "The form attribute of the select.", }, - closeOnOutsideClick: { - type: C.BOOLEAN, - default: C.TRUE, - description: "Whether to close the select menu when a click occurs outside of it.", + value: { + type: C.STRING, + description: "The value of the currently selected select item.", }, - loop: { - type: C.BOOLEAN, - default: C.FALSE, - description: - "Whether or not to loop through the menu items when navigating with the keyboard.", + onValueChange: { + type: { + type: C.FUNCTION, + definition: "(value: string | undefined) => void", + }, + description: "A callback that is fired when the select menu's value changes.", }, open: { type: C.BOOLEAN, @@ -70,26 +70,6 @@ export const root: APISchema = { }, description: "A callback that is fired when the select menu's open state changes.", }, - selected: { - type: { - type: C.OBJECT, - definition: "{ value: unknown; label?: string }", - }, - description: "The value of the currently selected item.", - }, - onSelectedChange: { - type: { - type: C.FUNCTION, - definition: "(value: unknown | undefined) => void", - }, - description: "A callback that is fired when the select menu's value changes.", - }, - portal: { ...portalProp("select menu") }, - highlightOnHover: { - type: C.BOOLEAN, - default: C.TRUE, - description: "Whether or not to highlight the currently hovered item.", - }, name: { type: C.STRING, description: "The name to apply to the hidden input element for form submission.", @@ -99,28 +79,7 @@ export const root: APISchema = { type: C.BOOLEAN, description: "Whether or not the select menu is required.", }, - scrollAlignment: { - default: "'nearest'", - type: { - type: C.ENUM, - definition: enums("nearest", "center"), - }, - description: "The alignment of the highlighted item when scrolling.", - }, - typeahead: { - type: C.BOOLEAN, - default: C.TRUE, - description: - "Whether or not to enable typeahead functionality. When enabled, the user can type to navigate to menu items.", - }, - items: { - type: { - type: "Selected[]", - definition: "Array<{ value: T; label?: string }>", - }, - description: "An array of items to add type-safety to the `onSelectedChange` callback.", - }, - onOutsideClick: onOutsideClickProp, + children: childrenSnippet(), }, slotProps: { ids: idsSlotProp }, }; @@ -128,7 +87,14 @@ export const root: APISchema = { export const trigger: APISchema = { title: "Trigger", description: "The button element which toggles the select menu's open state.", - props: domElProps("HTMLButtonElement"), + props: { + disabled: { + default: C.FALSE, + type: C.BOOLEAN, + description: "Whether or not the select menu trigger is disabled.", + }, + ...withChildProps({ elType: "HTMLButtonElement" }), + }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ { @@ -151,7 +117,26 @@ export const trigger: APISchema = { export const content: APISchema = { title: "Content", description: "The content/menu element which contains the select menu's items.", - props: { ...transitionProps, ...floatingPositioning, ...domElProps("HTMLDivElement") }, + props: { + position: { + type: { + type: C.ENUM, + definition: enums("floating", "item-aligned"), + }, + default: "floating", + description: + "The positioning strategy to use for the content. If set to 'item-aligned', the content will be positioned relative to the trigger, similar to a native select. If set to `floating`, the content will use Floating UI to position itself similar to other popover-like components.", + }, + dir: dirProp, + ...floatingProps(), + ...dismissableLayerProps, + ...escapeLayerProps, + ...focusScopeProps, + preventOverflowTextSelection: preventOverflowTextSelectionProp, + preventScroll: preventScrollProp(), + forceMount: forceMountProp, + ...withChildProps({ elType: "HTMLDivElement" }), + }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ { @@ -165,13 +150,14 @@ export const item: APISchema = { title: "Item", description: "A select item, which must be a child of the `Select.Content` component.", props: { - label: { + textValue: { type: C.STRING, - description: "The label of the select item, which is displayed in the menu.", + description: "The text value of the select item, which is used for typeahead purposes.", }, value: { - type: C.UNKNOWN, + type: C.STRING, description: "The value of the select item.", + required: true, }, disabled: { type: C.BOOLEAN, @@ -179,7 +165,7 @@ export const item: APISchema = { description: "Whether or not the select item is disabled. This will prevent interaction/selection.", }, - ...domElProps("HTMLDivElement"), + ...withChildProps({ elType: "HTMLDivElement" }), }, slotProps: { isSelected: { @@ -241,18 +227,10 @@ export const value: APISchema = { ], }; -export const input: APISchema = { - title: "Input", - description: - "A hidden input element which is used to store the select menu's value, used for form submission. It receives the same value as the `Select.Value` component and can receive any props that a normal input element can receive.", - props: domElProps("HTMLInputElement"), - slotProps: { ...builderAndAttrsSlotProps }, -}; - export const group: APISchema = { title: "Group", description: "An accessible group of select menu items.", - props: domElProps("HTMLDivElement"), + props: withChildProps({ elType: "HTMLDivElement" }), slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ { @@ -262,11 +240,11 @@ export const group: APISchema = { ], }; -export const label: APISchema = { - title: "Label", +export const groupLabel: APISchema = { + title: "GroupLabel", description: "A label for the select menu which will be skipped when navigating with the keyboard. This must be a child of the `Select.Group` component to be accessible.", - props: domElProps("HTMLLabelElement"), + props: withChildProps({ elType: "HTMLDivElement" }), slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ { @@ -279,7 +257,7 @@ export const label: APISchema = { export const separator: APISchema = { title: "Separator", description: "A visual separator for use between select items or groups.", - props: domElProps("HTMLDivElement"), + props: withChildProps({ elType: "HTMLDivElement" }), slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ { @@ -289,25 +267,6 @@ export const separator: APISchema = { ], }; -export const indicator: APISchema = { - title: "Separator", - description: "A visual separator for use between select items or groups.", - props: domElProps("HTMLDivElement"), - slotProps: { - attrs: attrsSlotProp, - isSelected: { - type: C.BOOLEAN, - description: "Whether or not the item is selected.", - }, - }, - dataAttributes: [ - { - name: "select-indicator", - description: "Present on the indicator element.", - }, - ], -}; - export const arrow: APISchema = { title: "Arrow", description: "An optional arrow element which points to the trigger when open.", @@ -321,4 +280,4 @@ export const arrow: APISchema = { ], }; -export const select = [root, trigger, content, item, value, group, label, input, separator, arrow]; +export const select = [root, trigger, content, item, value, group, groupLabel, separator, arrow]; diff --git a/sites/docs/src/lib/content/api-reference/separator.ts b/sites/docs/src/lib/content/api-reference/separator.ts index fcc91e697..9aee8df00 100644 --- a/sites/docs/src/lib/content/api-reference/separator.ts +++ b/sites/docs/src/lib/content/api-reference/separator.ts @@ -1,9 +1,14 @@ -import type { SeparatorPropsWithoutHTML } from "bits-ui"; -import { builderAndAttrsSlotProps, domElProps, enums } from "$lib/content/api-reference/helpers.js"; +import type { SeparatorRootPropsWithoutHTML } from "bits-ui"; +import { + builderAndAttrsSlotProps, + domElProps, + enums, + withChildProps, +} from "$lib/content/api-reference/helpers.js"; import * as C from "$lib/content/constants.js"; import type { APISchema } from "$lib/types/index.js"; -export const root: APISchema = { +export const root: APISchema = { title: "Root", description: "An element used to separate content.", props: { @@ -21,7 +26,7 @@ export const root: APISchema = { description: "Whether the separator is decorative or not, which will determine if it is announce by screen readers.", }, - ...domElProps("HTMLDivElement"), + ...withChildProps({ elType: "HTMLDivElement" }), }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ diff --git a/sites/docs/src/lib/content/api-reference/slider.ts b/sites/docs/src/lib/content/api-reference/slider.ts index 524bd37f3..e56cb6930 100644 --- a/sites/docs/src/lib/content/api-reference/slider.ts +++ b/sites/docs/src/lib/content/api-reference/slider.ts @@ -1,14 +1,18 @@ import type { - SliderPropsWithoutHTML, + SliderRootPropsWithoutHTML, SliderRangePropsWithoutHTML, SliderThumbPropsWithoutHTML, SliderTickPropsWithoutHTML, } from "bits-ui"; -import { builderAndAttrsSlotProps, domElProps, enums } from "$lib/content/api-reference/helpers.js"; +import { + builderAndAttrsSlotProps, + enums, + withChildProps, +} from "$lib/content/api-reference/helpers.js"; import * as C from "$lib/content/constants.js"; import type { APISchema } from "$lib/types/index.js"; -const root: APISchema = { +const root: APISchema = { title: "Root", description: "The root slider component which contains the remaining slider components.", props: { @@ -16,6 +20,7 @@ const root: APISchema = { default: "[]", type: "number[]", description: "The current value of the slider.", + bindable: true, }, onValueChange: { type: { @@ -24,6 +29,14 @@ const root: APISchema = { }, description: "A callback function called when the value state of the slider changes.", }, + onValueChangeEnd: { + type: { + type: C.FUNCTION, + definition: "(value: number[]) => void", + }, + description: + "A callback function called when the user finishes dragging the thumb and the value changes. This is different than the `onValueChange` callback because it waits until the user stops dragging before calling the callback, where the `onValueChange` callback is called immediately after the user starts dragging.", + }, disabled: { default: C.FALSE, type: C.BOOLEAN, @@ -61,7 +74,14 @@ const root: APISchema = { description: "The reading direction of the slider. If set to 'rtl', the slider will be reversed for both `'horizontal'` and `'vertical'` orientations.", }, - ...domElProps("HTMLSpanElement"), + autoSort: { + type: C.BOOLEAN, + default: C.TRUE, + description: + "Whether to automatically sort the values in the array when moving thumbs past one another.", + }, + + ...withChildProps({ elType: "HTMLSpanElement" }), }, slotProps: { ticks: { @@ -92,12 +112,17 @@ const thumb: APISchema = { title: "Thumb", description: "A thumb on the slider.", props: { - thumb: { - type: "Thumb", + index: { + type: C.NUMBER, description: - "An individual thumb builder from the `thumbs` slot prop provided by the `Slider.Root` component.", + "The index of the thumb in the array of thumbs provided by the `thumbs` `children` snippet prop.", + }, + disabled: { + default: C.FALSE, + type: C.BOOLEAN, + description: "Whether or not the thumb is disabled.", }, - ...domElProps("HTMLSpanElement"), + ...withChildProps({ elType: "HTMLSpanElement" }), }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ @@ -111,7 +136,7 @@ const thumb: APISchema = { const range: APISchema = { title: "Range", description: "The range of the slider.", - props: domElProps("HTMLSpanElement"), + props: withChildProps({ elType: "HTMLSpanElement" }), slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ { @@ -125,12 +150,12 @@ const tick: APISchema = { title: "Tick", description: "A tick mark on the slider.", props: { - tick: { - type: "Tick", + index: { + type: "number", description: - "An individual tick builder from the `ticks` slot prop provided by the `Slider.Root` component.", + "The index of the tick in the array of ticks provided by the `ticks` `children` snippet prop.", }, - ...domElProps("HTMLSpanElement"), + ...withChildProps({ elType: "HTMLSpanElement" }), }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ diff --git a/sites/docs/src/lib/content/api-reference/switch.ts b/sites/docs/src/lib/content/api-reference/switch.ts index 4c4ef152e..905bfba50 100644 --- a/sites/docs/src/lib/content/api-reference/switch.ts +++ b/sites/docs/src/lib/content/api-reference/switch.ts @@ -1,10 +1,10 @@ -import type { SwitchPropsWithoutHTML, SwitchThumbPropsWithoutHTML } from "bits-ui"; -import { builderAndAttrsSlotProps, domElProps } from "./helpers.js"; +import type { SwitchRootPropsWithoutHTML, SwitchThumbPropsWithoutHTML } from "bits-ui"; +import { builderAndAttrsSlotProps, withChildProps } from "./helpers.js"; import { attrsSlotProp, enums } from "$lib/content/api-reference/helpers.js"; import * as C from "$lib/content/constants.js"; import type { APISchema } from "$lib/types/index.js"; -const root: APISchema = { +const root: APISchema = { title: "Root", description: "The root switch component used to set and manage the state of the switch.", props: { @@ -12,6 +12,7 @@ const root: APISchema = { default: C.FALSE, type: C.BOOLEAN, description: "Whether or not the switch is checked.", + bindable: true, }, onCheckedChange: { type: { @@ -25,16 +26,6 @@ const root: APISchema = { type: C.BOOLEAN, description: "Whether or not the switch is disabled.", }, - includeInput: { - default: C.FALSE, - type: C.BOOLEAN, - description: - "Whether or not to include the input element in the switch. This will automatically add a hidden input element to the switch that will be checked when the switch is checked.", - }, - inputAttrs: { - type: C.OBJECT, - description: "Attributes to be spread onto the hidden input element.", - }, name: { type: C.STRING, description: @@ -50,7 +41,7 @@ const root: APISchema = { description: "The value of the hidden input element to be used in form submissions when the switch is checked.", }, - ...domElProps("HTMLButtonElement"), + ...withChildProps({ elType: "HTMLButtonElement" }), }, slotProps: { ...builderAndAttrsSlotProps, @@ -80,7 +71,7 @@ const root: APISchema = { const thumb: APISchema = { title: "Thumb", description: "The thumb on the switch used to indicate the switch's state.", - props: domElProps("HTMLSpanElement"), + props: withChildProps({ elType: "HTMLSpanElement" }), slotProps: { attrs: attrsSlotProp, checked: { diff --git a/sites/docs/src/lib/content/api-reference/tabs.ts b/sites/docs/src/lib/content/api-reference/tabs.ts index 768143a58..d47c95db7 100644 --- a/sites/docs/src/lib/content/api-reference/tabs.ts +++ b/sites/docs/src/lib/content/api-reference/tabs.ts @@ -1,7 +1,7 @@ import type { TabsContentPropsWithoutHTML, TabsListPropsWithoutHTML, - TabsPropsWithoutHTML, + TabsRootPropsWithoutHTML, TabsTriggerPropsWithoutHTML, } from "bits-ui"; import { @@ -9,11 +9,12 @@ import { domElProps, enums, union, + withChildProps, } from "$lib/content/api-reference/helpers.js"; import * as C from "$lib/content/constants.js"; import type { APISchema } from "$lib/types/index.js"; -const root: APISchema = { +const root: APISchema = { title: "Root", description: "The root tabs component which contains the other tab components.", props: { @@ -23,6 +24,7 @@ const root: APISchema = { definition: union("string", "undefined"), }, description: "The active tab value.", + bindable: true, }, onValueChange: { type: { @@ -31,17 +33,21 @@ const root: APISchema = { }, description: "A callback function called when the active tab value changes.", }, - activateOnFocus: { - default: C.TRUE, - type: C.BOOLEAN, - description: "Whether or not to activate the tab when it receives focus.", + activationMode: { + type: { + type: C.ENUM, + definition: enums("manual", "automatic"), + }, + description: + "How the activation of tabs should be handled. If set to `'automatic'`, the tab will be activated when the trigger is focused. If set to `'manual'`, the tab will be activated when the trigger is pressed.", + default: "automatic", }, - autoSet: { - default: C.TRUE, + disabled: { + default: C.FALSE, type: C.BOOLEAN, - description: - "Whether or not to automatically set the tab value when it receives focus.", + description: "Whether or not the tabs are disabled.", }, + loop: { default: C.TRUE, type: C.BOOLEAN, @@ -55,7 +61,7 @@ const root: APISchema = { }, description: "The orientation of the tabs.", }, - ...domElProps("HTMLDivElement"), + ...withChildProps({ elType: "HTMLDivElement" }), }, slotProps: { ...builderAndAttrsSlotProps, @@ -80,7 +86,7 @@ const root: APISchema = { const list: APISchema = { title: "List", description: "The component containing the tab triggers.", - props: domElProps("HTMLDivElement"), + props: withChildProps({ elType: "HTMLDivElement" }), slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ { @@ -109,7 +115,7 @@ const trigger: APISchema = { type: C.BOOLEAN, description: "Whether or not the tab is disabled.", }, - ...domElProps("HTMLButtonElement"), + ...withChildProps({ elType: "HTMLButtonElement" }), }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ @@ -149,7 +155,7 @@ const content: APISchema = { type: "string", description: "The value of the tab this content represents.", }, - ...domElProps("HTMLDivElement"), + ...withChildProps({ elType: "HTMLDivElement" }), }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ diff --git a/sites/docs/src/lib/content/api-reference/toggle-group.ts b/sites/docs/src/lib/content/api-reference/toggle-group.ts index 58a1b716a..d07dc886a 100644 --- a/sites/docs/src/lib/content/api-reference/toggle-group.ts +++ b/sites/docs/src/lib/content/api-reference/toggle-group.ts @@ -1,14 +1,15 @@ -import type { ToggleGroupItemPropsWithoutHTML, ToggleGroupPropsWithoutHTML } from "bits-ui"; +import type { ToggleGroupItemPropsWithoutHTML, ToggleGroupRootPropsWithoutHTML } from "bits-ui"; import { builderAndAttrsSlotProps, domElProps, enums, union, + withChildProps, } from "$lib/content/api-reference/helpers.js"; import * as C from "$lib/content/constants.js"; import type { APISchema } from "$lib/types/index.js"; -const root: APISchema> = { +const root: APISchema = { title: "Root", description: "The root component which contains the toggle group items.", props: { @@ -16,6 +17,7 @@ const root: APISchema> = { type: union(C.STRING, "string[]"), description: "The value of the toggle group. If the type is multiple, this will be an array of strings, otherwise it will be a string.", + bindable: true, }, onValueChange: { type: { @@ -50,7 +52,7 @@ const root: APISchema> = { description: "The type of toggle group.", type: enums("single", "multiple"), }, - ...domElProps("HTMLDivElement"), + ...withChildProps({ elType: "HTMLDivElement" }), }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ @@ -78,7 +80,7 @@ const item: APISchema = { type: C.BOOLEAN, description: "Whether or not the switch is disabled.", }, - ...domElProps("HTMLButtonElement"), + ...withChildProps({ elType: "HTMLButtonElement" }), }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ diff --git a/sites/docs/src/lib/content/api-reference/toggle.ts b/sites/docs/src/lib/content/api-reference/toggle.ts index 8c13a1919..a4fd1f9d8 100644 --- a/sites/docs/src/lib/content/api-reference/toggle.ts +++ b/sites/docs/src/lib/content/api-reference/toggle.ts @@ -1,9 +1,13 @@ -import type { TogglePropsWithoutHTML } from "bits-ui"; -import { builderAndAttrsSlotProps, domElProps, enums } from "$lib/content/api-reference/helpers.js"; +import type { ToggleRootPropsWithoutHTML } from "bits-ui"; +import { + builderAndAttrsSlotProps, + enums, + withChildProps, +} from "$lib/content/api-reference/helpers.js"; import * as C from "$lib/content/constants.js"; import type { APISchema } from "$lib/types/index.js"; -const root: APISchema = { +const root: APISchema = { title: "Root", description: "The toggle button.", props: { @@ -11,6 +15,7 @@ const root: APISchema = { default: C.FALSE, type: C.BOOLEAN, description: "Whether or not the toggle button is pressed.", + bindable: true, }, onPressedChange: { type: { @@ -24,7 +29,7 @@ const root: APISchema = { type: C.BOOLEAN, description: "Whether or not the switch is disabled.", }, - ...domElProps("HTMLButtonElement"), + ...withChildProps({ elType: "HTMLButtonElement" }), }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ diff --git a/sites/docs/src/lib/content/api-reference/toolbar.ts b/sites/docs/src/lib/content/api-reference/toolbar.ts index 5fc8d5021..3ca9fa0bb 100644 --- a/sites/docs/src/lib/content/api-reference/toolbar.ts +++ b/sites/docs/src/lib/content/api-reference/toolbar.ts @@ -3,18 +3,19 @@ import type { ToolbarGroupItemPropsWithoutHTML, ToolbarGroupPropsWithoutHTML, ToolbarLinkPropsWithoutHTML, - ToolbarPropsWithoutHTML, + ToolbarRootPropsWithoutHTML, } from "bits-ui"; import { builderAndAttrsSlotProps, domElProps, enums, union, + withChildProps, } from "$lib/content/api-reference/helpers.js"; import * as C from "$lib/content/constants.js"; import type { APISchema } from "$lib/types/index.js"; -const root: APISchema = { +const root: APISchema = { title: "Root", description: "The root component which contains the toolbar.", props: { @@ -31,7 +32,7 @@ const root: APISchema = { }, description: "The orientation of the toolbar.", }, - ...domElProps("HTMLDivElement"), + ...withChildProps({ elType: "HTMLDivElement" }), }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ @@ -49,7 +50,14 @@ const root: APISchema = { const button: APISchema = { title: "Button", description: "A button in the toolbar.", - props: domElProps("HTMLButtonElement"), + props: { + disabled: { + default: C.FALSE, + type: C.BOOLEAN, + description: "Whether or not the button is disabled.", + }, + ...withChildProps({ elType: "HTMLButtonElement" }), + }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ { @@ -62,7 +70,7 @@ const button: APISchema = { const link: APISchema = { title: "Link", description: "A link in the toolbar.", - props: domElProps("HTMLAnchorElement"), + props: withChildProps({ elType: "HTMLAnchorElement" }), slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ { @@ -72,7 +80,7 @@ const link: APISchema = { ], }; -const group: APISchema> = { +const group: APISchema = { title: "Group", description: "A group of toggle items in the toolbar.", props: { @@ -83,6 +91,7 @@ const group: APISchema> = { }, description: "The value of the toggle group. If the type is multiple, this will be an array of strings, otherwise it will be a string.", + bindable: true, }, onValueChange: { type: C.FUNCTION, @@ -101,7 +110,7 @@ const group: APISchema> = { definition: enums("single", "multiple"), }, }, - ...domElProps("HTMLDivElement"), + ...withChildProps({ elType: "HTMLDivElement" }), }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ @@ -126,7 +135,7 @@ const groupItem: APISchema = { type: C.BOOLEAN, description: "Whether or not the item is disabled.", }, - ...domElProps("HTMLButtonElement"), + ...withChildProps({ elType: "HTMLButtonElement" }), }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ diff --git a/sites/docs/src/lib/content/api-reference/tooltip.ts b/sites/docs/src/lib/content/api-reference/tooltip.ts index c9ba0f0e9..ffdc8da9f 100644 --- a/sites/docs/src/lib/content/api-reference/tooltip.ts +++ b/sites/docs/src/lib/content/api-reference/tooltip.ts @@ -1,63 +1,95 @@ import type { TooltipArrowPropsWithoutHTML, TooltipContentPropsWithoutHTML, - TooltipPropsWithoutHTML, + TooltipProviderPropsWithoutHTML, + TooltipRootPropsWithoutHTML, TooltipTriggerPropsWithoutHTML, } from "bits-ui"; import { floatingPositioning } from "./floating.js"; import { arrowProps, builderAndAttrsSlotProps, + childrenSnippet, + dirProp, + dismissableLayerProps, domElProps, enums, + escapeLayerProps, + floatingProps, + forceMountProp, idsSlotProp, portalProp, transitionProps, + withChildProps, } from "$lib/content/api-reference/helpers.js"; import * as C from "$lib/content/constants.js"; -import type { APISchema } from "$lib/types/index.js"; +import type { APISchema, PropSchema } from "$lib/types/index.js"; -export const root: APISchema = { +const delayDuration: PropSchema = { + type: C.NUMBER, + default: "700", + description: + "The amount of time in milliseconds to delay opening the tooltip when hovering over the trigger.", +}; + +const disableHoverableContent: PropSchema = { + type: C.BOOLEAN, + default: C.FALSE, + description: + "Whether or not to disable the hoverable content. This is useful when the content contains interactive elements.", +}; + +const disabled: PropSchema = { + type: C.BOOLEAN, + default: C.FALSE, + description: "Whether or not the tooltip is disabled.", +}; + +const disableCloseOnTriggerClick: PropSchema = { + type: C.BOOLEAN, + default: C.FALSE, + description: + "Whether or not to close the tooltip when pressing the escape key. This is useful when the content contains interactive elements.", +}; + +const skipDelayDuration: PropSchema = { + type: C.NUMBER, + default: "300", + description: + "The amount of time in milliseconds to delay opening the tooltip when the user has used their mouse to hover over the trigger.", +}; + +const ignoreNonKeyboardFocus: PropSchema = { + type: C.BOOLEAN, + default: C.FALSE, + description: + "Whether or not to ignore the tooltip when the focus is not on the trigger. This is useful when the content contains interactive elements.", +}; + +export const provider: APISchema = { + title: "Provider", + description: + "A provider component which contains shared state and logic for the tooltips within its subtree.", + props: { + delayDuration, + disableHoverableContent, + disabled, + disableCloseOnTriggerClick, + skipDelayDuration, + ignoreNonKeyboardFocus, + children: childrenSnippet(), + }, +}; + +export const root: APISchema = { title: "Root", description: "The root component containing the parts of the tooltip.", props: { - openDelay: { - type: C.NUMBER, - default: "700", - description: - "The amount of time in milliseconds to delay opening the tooltip when hovering over the trigger.", - }, - closeDelay: { - type: C.NUMBER, - default: "300", - description: - "The amount of time in milliseconds to delay closing the tooltip when the mouse leaves the trigger.", - }, - closeOnEscape: { - type: C.BOOLEAN, - default: C.TRUE, - description: "Whether or not to close the tooltip when pressing the escape key.", - }, - closeOnPointerDown: { - type: C.BOOLEAN, - default: C.TRUE, - description: - "Whether or not to close the tooltip when clicking outside of the tooltip.", - }, - disableHoverableContent: { - type: C.BOOLEAN, - default: C.FALSE, - description: - "Whether or not to disable the hoverable content. This is useful when the content contains interactive elements.", - }, - group: { - type: C.STRING, - description: "The group the tooltip belongs to.", - }, open: { type: C.BOOLEAN, default: "false", description: "The open state of the tooltip component.", + bindable: true, }, onOpenChange: { type: { @@ -66,7 +98,12 @@ export const root: APISchema = { }, description: "A callback that fires when the open state changes.", }, - portal: { ...portalProp("tooltip") }, + disabled, + delayDuration, + disableHoverableContent, + disableCloseOnTriggerClick, + ignoreNonKeyboardFocus, + children: childrenSnippet(), }, slotProps: { ids: idsSlotProp, @@ -77,7 +114,14 @@ export const trigger: APISchema = { title: "Trigger", description: "A component which triggers the opening and closing of the tooltip on hover or focus.", - props: domElProps("HTMLButtonElement"), + props: { + disabled: { + default: C.FALSE, + type: C.BOOLEAN, + description: "Whether or not the tooltip trigger is disabled.", + }, + ...withChildProps({ elType: "HTMLButtonElement" }), + }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ { @@ -96,7 +140,14 @@ export const trigger: APISchema = { export const content: APISchema = { title: "Content", description: "The contents of the tooltip which are displayed when the tooltip is open.", - props: { ...transitionProps, ...floatingPositioning, ...domElProps("HTMLDivElement") }, + props: { + ...floatingProps(), + ...dismissableLayerProps, + ...escapeLayerProps, + forceMount: forceMountProp, + dir: dirProp, + ...withChildProps({ elType: "HTMLDivElement" }), + }, slotProps: { ...builderAndAttrsSlotProps }, dataAttributes: [ { diff --git a/sites/docs/src/lib/types/api.ts b/sites/docs/src/lib/types/api.ts index 33554887f..5be75a2e9 100644 --- a/sites/docs/src/lib/types/api.ts +++ b/sites/docs/src/lib/types/api.ts @@ -8,6 +8,7 @@ export type PropSchema = { type: PropType | string; description: string; required?: boolean; + bindable?: boolean; }; export type PropObj> = {