Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jer3m01 committed May 15, 2024
1 parent 50026fc commit 16b5756
Show file tree
Hide file tree
Showing 8 changed files with 490 additions and 12 deletions.
10 changes: 0 additions & 10 deletions packages/core/src/menubar/menubar-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,6 @@ import { MenuRoot, MenuRootOptions } from "../menu";
import { useMenubarContext } from "./menubar-context";

export interface MenubarMenuOptions extends MenuRootOptions {
/**
* Whether the menu should be the only visible content for screen readers.
* When set to `true`:
* - interaction with outside elements will be disabled.
* - scroll will be locked.
* - focus will be locked inside the menu content.
* - elements outside the menu content will not be visible for screen readers.
* Default false
*/
modal?: boolean;
}

export interface MenubarMenuProps extends ParentProps<MenubarMenuOptions> {}
Expand Down
14 changes: 12 additions & 2 deletions packages/core/src/menubar/menubar-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
createUniqueId,
onCleanup,
splitProps,
Setter,
} from "solid-js";
import { isServer } from "solid-js/web";

Expand All @@ -48,6 +49,9 @@ export interface MenubarRootOptions {

/** When true, click on alt by itsef will focus this Menubar (some browsers interfere) */
focusOnAlt?: boolean;

autoFocusMenu?: boolean;
onAutoFocusMenuChange?: Setter<boolean>;
}

export interface MenubarRootCommonProps {
Expand Down Expand Up @@ -84,6 +88,8 @@ export function MenubarRoot<T extends ValidComponent = "div">(
"onValueChange",
"loop",
"focusOnAlt",
"autoFocusMenu",
"onAutoFocusMenuChange",
]);

const [value, setValue] = createControllableSignal<string | undefined>({
Expand All @@ -103,7 +109,11 @@ export function MenubarRoot<T extends ValidComponent = "div">(
"data-closed": value() === undefined ? "" : undefined,
}));

const [autoFocusMenu, setAutoFocusMenu] = createSignal(false);
const [autoFocusMenu, setAutoFocusMenu] = createControllableSignal({
value: () => local.autoFocusMenu,
defaultValue: () => false,
onChange: local.onAutoFocusMenuChange,
})

const context: MenubarContextValue = {
dataset,
Expand Down Expand Up @@ -163,7 +173,7 @@ export function MenubarRoot<T extends ValidComponent = "div">(
setAutoFocusMenu(false);
setValue(undefined);
},
autoFocusMenu,
autoFocusMenu: () => autoFocusMenu()!,
setAutoFocusMenu,
generateId: createGenerateId(() => others.id!),
};
Expand Down
228 changes: 228 additions & 0 deletions packages/core/src/navigation-menu/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import {
MenuCheckboxItem as CheckboxItem,
type MenuCheckboxItemCommonProps as NavigationMenuCheckboxItemCommonProps,
type MenuCheckboxItemOptions as NavigationMenuCheckboxItemOptions,
type MenuCheckboxItemProps as NavigationMenuCheckboxItemProps,
type MenuCheckboxItemRenderProps as NavigationMenuCheckboxItemRenderProps,
MenuGroup as Group,
type MenuGroupCommonProps as NavigationMenuGroupCommonProps,
MenuGroupLabel as GroupLabel,
type MenuGroupLabelCommonProps as NavigationMenuGroupLabelCommonProps,
type MenuGroupLabelOptions as NavigationMenuGroupLabelOptions,
type MenuGroupLabelProps as NavigationMenuGroupLabelProps,
type MenuGroupLabelRenderProps as NavigationMenuGroupLabelRenderProps,
type MenuGroupOptions as NavigationMenuGroupOptions,
type MenuGroupProps as NavigationMenuGroupProps,
type MenuGroupRenderProps as NavigationMenuGroupRenderProps,
MenuIcon as Icon,
type MenuIconCommonProps as NavigationMenuIconCommonProps,
type MenuIconOptions as NavigationMenuIconOptions,
type MenuIconProps as NavigationMenuIconProps,
type MenuIconRenderProps as NavigationMenuIconRenderProps,
MenuItem as Item,
type MenuItemCommonProps as NavigationMenuItemCommonProps,
MenuItemDescription as ItemDescription,
type MenuItemDescriptionCommonProps as NavigationMenuItemDescriptionCommonProps,
type MenuItemDescriptionOptions as NavigationMenuItemDescriptionOptions,
type MenuItemDescriptionProps as NavigationMenuItemDescriptionProps,
type MenuItemDescriptionRenderProps as NavigationMenuItemDescriptionRenderProps,
MenuItemIndicator as ItemIndicator,
type MenuItemIndicatorCommonProps as NavigationMenuItemIndicatorCommonProps,
type MenuItemIndicatorOptions as NavigationMenuItemIndicatorOptions,
type MenuItemIndicatorProps as NavigationMenuItemIndicatorProps,
type MenuItemIndicatorRenderProps as NavigationMenuItemIndicatorRenderProps,
MenuItemLabel as ItemLabel,
type MenuItemLabelCommonProps as NavigationMenuItemLabelCommonProps,
type MenuItemLabelOptions as NavigationMenuItemLabelOptions,
type MenuItemLabelProps as NavigationMenuItemLabelProps,
type MenuItemLabelRenderProps as NavigationMenuItemLabelRenderProps,
type MenuItemOptions as NavigationMenuItemOptions,
type MenuItemProps as NavigationMenuItemProps,
type MenuItemRenderProps as NavigationMenuItemRenderProps,
MenuPortal as Portal,
type MenuPortalProps as NavigationMenuPortalProps,
MenuRadioGroup as RadioGroup,
type MenuRadioGroupCommonProps as NavigationMenuRadioGroupCommonProps,
type MenuRadioGroupOptions as NavigationMenuRadioGroupOptions,
type MenuRadioGroupProps as NavigationMenuRadioGroupProps,
type MenuRadioGroupRenderProps as NavigationMenuRadioGroupRenderProps,
MenuRadioItem as RadioItem,
type MenuRadioItemCommonProps as NavigationMenuRadioItemCommonProps,
type MenuRadioItemOptions as NavigationMenuRadioItemOptions,
type MenuRadioItemProps as NavigationMenuRadioItemProps,
type MenuRadioItemRenderProps as NavigationMenuRadioItemPRenderrops,
MenuSub as Sub,
MenuSubContent as SubContent,
type MenuSubContentCommonProps as NavigationMenuSubContentCommonProps,
type MenuSubContentOptions as NavigationMenuSubContentOptions,
type MenuSubContentProps as NavigationMenuSubContentProps,
type MenuSubContentRenderProps as NavigationMenuSubContentRenderProps,
type MenuSubOptions as NavigationMenuSubOptions,
type MenuSubProps as NavigationMenuSubProps,
MenuSubTrigger as SubTrigger,
type MenuSubTriggerCommonProps as NavigationMenuSubTriggerCommonProps,
type MenuSubTriggerOptions as NavigationMenuSubTriggerOptions,
type MenuSubTriggerProps as NavigationMenuSubTriggerProps,
type MenuSubTriggerRenderProps as NavigationMenuSubTriggerRenderProps,
} from "../menu";
import {
Arrow,
type PopperArrowCommonProps as NavigationMenuArrowCommonProps,
type PopperArrowOptions as NavigationMenuArrowOptions,
type PopperArrowProps as NavigationMenuArrowProps,
type PopperArrowRenderProps as NavigationMenuArrowRenderProps,
} from "../popper";
import {
Root as Separator,
type SeparatorRootCommonProps as NavigationMenuSeparatorCommonProps,
type SeparatorRootOptions as NavigationMenuSeparatorOptions,
type SeparatorRootProps as NavigationMenuSeparatorProps,
type SeparatorRootRenderProps as NavigationMenuSeparatorRenderProps,
} from "../separator";
import {
NavigationMenuMenu as Menu,
type NavigationMenuMenuOptions,
type NavigationMenuMenuProps,
} from "./navigation-menu-menu";
import {
NavigationMenuRoot as Root,
type NavigationMenuRootCommonProps,
type NavigationMenuRootOptions,
type NavigationMenuRootProps,
type NavigationMenuRootRenderProps,
} from "./navigation-menu-root";
import {
NavigationMenuTrigger as Trigger,
type NavigationMenuTriggerOptions,
type NavigationMenuTriggerCommonProps,
type NavigationMenuTriggerRenderProps,
type NavigationMenuTriggerProps,
} from "./navigation-menu-trigger";
import {
NavigationMenuContent as Content,
type NavigationMenuContentCommonProps,
type NavigationMenuContentOptions,
type NavigationMenuContentProps,
type NavigationMenuContentRenderProps,
} from "./navigation-menu-content";

export type {
NavigationMenuRootOptions,
NavigationMenuRootCommonProps,
NavigationMenuRootRenderProps,
NavigationMenuRootProps,
NavigationMenuMenuOptions,
NavigationMenuMenuProps,
NavigationMenuArrowOptions,
NavigationMenuArrowCommonProps,
NavigationMenuArrowRenderProps,
NavigationMenuArrowProps,
NavigationMenuCheckboxItemOptions,
NavigationMenuCheckboxItemCommonProps,
NavigationMenuCheckboxItemRenderProps,
NavigationMenuCheckboxItemProps,
NavigationMenuContentOptions,
NavigationMenuContentCommonProps,
NavigationMenuContentRenderProps,
NavigationMenuContentProps,
NavigationMenuGroupLabelOptions,
NavigationMenuGroupLabelCommonProps,
NavigationMenuGroupLabelRenderProps,
NavigationMenuGroupLabelProps,
NavigationMenuGroupOptions,
NavigationMenuGroupCommonProps,
NavigationMenuGroupRenderProps,
NavigationMenuGroupProps,
NavigationMenuIconOptions,
NavigationMenuIconCommonProps,
NavigationMenuIconRenderProps,
NavigationMenuIconProps,
NavigationMenuItemDescriptionOptions,
NavigationMenuItemDescriptionCommonProps,
NavigationMenuItemDescriptionRenderProps,
NavigationMenuItemDescriptionProps,
NavigationMenuItemIndicatorOptions,
NavigationMenuItemIndicatorCommonProps,
NavigationMenuItemIndicatorRenderProps,
NavigationMenuItemIndicatorProps,
NavigationMenuItemLabelOptions,
NavigationMenuItemLabelCommonProps,
NavigationMenuItemLabelRenderProps,
NavigationMenuItemLabelProps,
NavigationMenuItemOptions,
NavigationMenuItemCommonProps,
NavigationMenuItemRenderProps,
NavigationMenuItemProps,
NavigationMenuPortalProps,
NavigationMenuRadioGroupOptions,
NavigationMenuRadioGroupCommonProps,
NavigationMenuRadioGroupRenderProps,
NavigationMenuRadioGroupProps,
NavigationMenuRadioItemOptions,
NavigationMenuRadioItemCommonProps,
NavigationMenuRadioItemPRenderrops,
NavigationMenuRadioItemProps,
NavigationMenuSeparatorOptions,
NavigationMenuSeparatorCommonProps,
NavigationMenuSeparatorRenderProps,
NavigationMenuSeparatorProps,
NavigationMenuSubContentOptions,
NavigationMenuSubContentCommonProps,
NavigationMenuSubContentRenderProps,
NavigationMenuSubContentProps,
NavigationMenuSubOptions,
NavigationMenuSubProps,
NavigationMenuSubTriggerOptions,
NavigationMenuSubTriggerCommonProps,
NavigationMenuSubTriggerRenderProps,
NavigationMenuSubTriggerProps,
NavigationMenuTriggerOptions,
NavigationMenuTriggerCommonProps,
NavigationMenuTriggerRenderProps,
NavigationMenuTriggerProps,
};

export {
Arrow,
CheckboxItem,
Content,
Group,
GroupLabel,
Icon,
Item,
ItemDescription,
ItemIndicator,
ItemLabel,
Portal,
RadioGroup,
RadioItem,
Root,
Menu,
Separator,
Sub,
SubContent,
SubTrigger,
Trigger,
};

export const NavigationMenu = Object.assign(Root, {
Arrow,
CheckboxItem,
Content,
Group,
GroupLabel,
Icon,
Item,
ItemDescription,
ItemIndicator,
ItemLabel,
Portal,
RadioGroup,
RadioItem,
Menu,
Separator,
Sub,
SubContent,
SubTrigger,
Trigger,
});
55 changes: 55 additions & 0 deletions packages/core/src/navigation-menu/navigation-menu-content.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { callHandler } from "@kobalte/utils";
import { Component, ValidComponent, splitProps, JSX } from "solid-js";

import { MenuContent, MenuContentCommonProps, MenuContentOptions, MenuContentRenderProps } from "../menu";
import { PolymorphicProps } from "../polymorphic";
import { useNavigationMenuContext } from "./navigation-menu-context";
import { useMenuContext } from "../menu/menu-context";
export interface NavigationMenuContentOptions extends MenuContentOptions {}

export interface NavigationMenuContentCommonProps extends MenuContentCommonProps {
onPointerEnter: JSX.EventHandlerUnion<HTMLElement, PointerEvent>;
onPointerLeave: JSX.EventHandlerUnion<HTMLElement, PointerEvent>;
}

export interface NavigationMenuContentRenderProps extends MenuContentRenderProps, NavigationMenuContentCommonProps {}

export type NavigationMenuContentProps = NavigationMenuContentOptions &
Partial<NavigationMenuContentCommonProps>;

export function NavigationMenuContent<T extends ValidComponent = "div">(
props: PolymorphicProps<T, NavigationMenuContentProps>,
) {
const context = useNavigationMenuContext();
const menuContext = useMenuContext();

const [local, others] = splitProps(props as NavigationMenuContentProps, ["onPointerEnter", "onPointerLeave"]);

const onPointerEnter: JSX.EventHandlerUnion<HTMLElement, PointerEvent> = (
e,
) => {
callHandler(e, local.onPointerEnter);

context.cancelLeaveTimer();
};

const onPointerLeave: JSX.EventHandlerUnion<HTMLElement, PointerEvent> = (
e,
) => {
callHandler(e, local.onPointerLeave);

context.startLeaveTimer();

menuContext.close(true);
};

return (
<MenuContent<
Component<Omit<NavigationMenuContentRenderProps, keyof MenuContentRenderProps>>
>
onPointerEnter={onPointerEnter}
onPointerLeave={onPointerLeave}
{...others}
/>
);
}
28 changes: 28 additions & 0 deletions packages/core/src/navigation-menu/navigation-menu-context.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Accessor, createContext, Setter, useContext } from "solid-js";

export interface NavigationMenuContextValue {
delayDuration: Accessor<number>;
skipDelayDuration: Accessor<number>;
autoFocusMenu: Accessor<boolean>;
setAutoFocusMenu: Setter<boolean>;
startLeaveTimer: () => void;
cancelLeaveTimer: () => void;
}

export const NavigationMenuContext = createContext<NavigationMenuContextValue>();

export function useOptionalNavigationMenuContext() {
return useContext(NavigationMenuContext);
}

export function useNavigationMenuContext() {
const context = useOptionalNavigationMenuContext();

if (context === undefined) {
throw new Error(
"[kobalte]: `useNavigationMenuContext` must be used within a `NavigationMenu` component",
);
}

return context;
}
17 changes: 17 additions & 0 deletions packages/core/src/navigation-menu/navigation-menu-menu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { MenubarMenuOptions, MenubarMenuProps } from "../menubar";
import { MenubarMenu } from "../menubar/menubar-menu";
import { useNavigationMenuContext } from "./navigation-menu-context";

export interface NavigationMenuMenuOptions extends MenubarMenuOptions {
}

export interface NavigationMenuMenuProps extends MenubarMenuProps {}

/**
* Displays a menu to the user —such as a set of actions or functions— triggered by a button.
*/
export function NavigationMenuMenu(props: NavigationMenuMenuProps) {
const menubarContext = useNavigationMenuContext();

return <MenubarMenu {...props} />;
}
Loading

0 comments on commit 16b5756

Please sign in to comment.