Files
games-frontend-js/src/components/ui/menu.tsx
T
john-okeefe 4574dfb8f1 feat(theme): migrate to Chakra v3 system with v2 look restoration
- Replace extendTheme/ColorModeScript with createSystem Provider +
  Toaster shims (components/ui, provider, color-mode) and next-themes;
  index.tsx renders Provider, App reads useColorMode from the shim and
  clears both chakra and legacy theme storage keys on preference change
- theme.tsx restores the v2 identity on v3 primitives: v2 gray/blue/
  green/red scales, v2 solid/contrast fills, v2 text-per-size for
  button/input/native-select/tag, v2 input heights, v2 heading scale
  (xl->4xl etc), v2 switch track/thumb, brighter link underlines
  (currentColor/60), +1px tag top padding, 17px body base font
- Default new-user theme light -> dark to match the established dark UI
- App.test rewritten around Provider + MemoryRouter + Home (old CRA
  'learn react' assertion no longer applies)
2026-09-06 10:29:04 -04:00

113 lines
3.1 KiB
TypeScript

"use client"
import { AbsoluteCenter, Menu as ChakraMenu, Portal } from "@chakra-ui/react"
import * as React from "react"
import { LuCheck, LuChevronRight } from "react-icons/lu"
interface MenuContentProps extends ChakraMenu.ContentProps {
portalled?: boolean
portalRef?: React.RefObject<HTMLElement | null>
}
export const MenuContent = React.forwardRef<HTMLDivElement, MenuContentProps>(
function MenuContent(props, ref) {
const { portalled = true, portalRef, ...rest } = props
return (
<Portal disabled={!portalled} container={portalRef}>
<ChakraMenu.Positioner>
<ChakraMenu.Content ref={ref} {...rest} />
</ChakraMenu.Positioner>
</Portal>
)
},
)
export const MenuArrow = React.forwardRef<
HTMLDivElement,
ChakraMenu.ArrowProps
>(function MenuArrow(props, ref) {
return (
<ChakraMenu.Arrow ref={ref} {...props}>
<ChakraMenu.ArrowTip />
</ChakraMenu.Arrow>
)
})
export const MenuCheckboxItem = React.forwardRef<
HTMLDivElement,
ChakraMenu.CheckboxItemProps
>(function MenuCheckboxItem(props, ref) {
return (
<ChakraMenu.CheckboxItem ps="8" ref={ref} {...props}>
<AbsoluteCenter axis="horizontal" insetStart="4" asChild>
<ChakraMenu.ItemIndicator>
<LuCheck />
</ChakraMenu.ItemIndicator>
</AbsoluteCenter>
{props.children}
</ChakraMenu.CheckboxItem>
)
})
export const MenuRadioItem = React.forwardRef<
HTMLDivElement,
ChakraMenu.RadioItemProps
>(function MenuRadioItem(props, ref) {
const { children, ...rest } = props
return (
<ChakraMenu.RadioItem ps="8" ref={ref} {...rest}>
<AbsoluteCenter axis="horizontal" insetStart="4" asChild>
<ChakraMenu.ItemIndicator>
<LuCheck />
</ChakraMenu.ItemIndicator>
</AbsoluteCenter>
<ChakraMenu.ItemText>{children}</ChakraMenu.ItemText>
</ChakraMenu.RadioItem>
)
})
export const MenuItemGroup = React.forwardRef<
HTMLDivElement,
ChakraMenu.ItemGroupProps
>(function MenuItemGroup(props, ref) {
const { title, children, ...rest } = props
return (
<ChakraMenu.ItemGroup ref={ref} {...rest}>
{title && (
<ChakraMenu.ItemGroupLabel userSelect="none">
{title}
</ChakraMenu.ItemGroupLabel>
)}
{children}
</ChakraMenu.ItemGroup>
)
})
export interface MenuTriggerItemProps extends ChakraMenu.ItemProps {
startIcon?: React.ReactNode
}
export const MenuTriggerItem = React.forwardRef<
HTMLDivElement,
MenuTriggerItemProps
>(function MenuTriggerItem(props, ref) {
const { startIcon, children, ...rest } = props
return (
<ChakraMenu.TriggerItem ref={ref} {...rest}>
{startIcon}
{children}
<LuChevronRight />
</ChakraMenu.TriggerItem>
)
})
export const MenuRadioItemGroup = ChakraMenu.RadioItemGroup
export const MenuContextTrigger = ChakraMenu.ContextTrigger
export const MenuRoot = ChakraMenu.Root
export const MenuSeparator = ChakraMenu.Separator
export const MenuItem = ChakraMenu.Item
export const MenuItemText = ChakraMenu.ItemText
export const MenuItemCommand = ChakraMenu.ItemCommand
export const MenuTrigger = ChakraMenu.Trigger