Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
lerte committed Nov 14, 2024
1 parent 79fe2d6 commit 4e0d9e7
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 105 deletions.
32 changes: 16 additions & 16 deletions apps/docs/src/usages/menus.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Icon, IconButton, Menu, MenuItem, MenuItems } from 'actify'
import { Icon, IconButton, Item, Menu, Section } from 'actify'

import React from 'react'

Expand All @@ -10,18 +10,18 @@ export default () => {
label="Open with label"
onAction={(key) => alert(key)}
>
<MenuItems>
<MenuItem key="edit">Edit…</MenuItem>
<MenuItem key="duplicate">Duplicate</MenuItem>
</MenuItems>
<MenuItems>
<MenuItem key="move">Move…</MenuItem>
<MenuItem key="rename">Rename…</MenuItem>
</MenuItems>
<MenuItems>
<MenuItem key="archive">Archive</MenuItem>
<MenuItem key="delete">Delete…</MenuItem>
</MenuItems>
<Section>
<Item key="edit">Edit…</Item>
<Item key="duplicate">Duplicate</Item>
</Section>
<Section>
<Item key="move">Move…</Item>
<Item key="rename">Rename…</Item>
</Section>
<Section>
<Item key="archive">Archive</Item>
<Item key="delete">Delete…</Item>
</Section>
</Menu>
<Menu
activator={(ref, menuTriggerProps) => (
Expand All @@ -31,9 +31,9 @@ export default () => {
)}
onAction={(key) => alert(key)}
>
<MenuItem key="copy">Copy</MenuItem>
<MenuItem key="cut">Cut</MenuItem>
<MenuItem key="paste">Paste</MenuItem>
<Item key="copy">Copy</Item>
<Item key="cut">Cut</Item>
<Item key="paste">Paste</Item>
</Menu>
</div>
)
Expand Down
79 changes: 40 additions & 39 deletions packages/actify/src/components/Autocomplete/Autocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ComboBoxStateOptions, useComboBoxState } from 'react-stately'
import { Icon } from '../Icon'
import { ListBox } from '../ListBox'
import { Popover } from '../Popover'
import { PopoverContext } from '../Popover/PopoverContext'
import React from 'react'
import { TextField } from '../TextFields'
import styles from './autocomplete.module.css'
Expand Down Expand Up @@ -39,46 +40,46 @@ const Autocomplete = <T extends object>(props: AutocompleteProps<T>) => {
)

return (
<div className={styles['autocomplete']} ref={ref}>
<TextField
label={props.label}
inputRef={inputRef}
variant={props.variant}
inputProps={inputProps}
onFocus={() => state.setOpen(true)}
trailingIcon={
<Icon
style={{ cursor: 'pointer' }}
onClick={() => {
state.setOpen(!state.isOpen)
// If the input is focused, move the cursor to the end
inputRef.current?.setSelectionRange(
inputRef.current.value.length,
inputRef.current.value.length
)
}}
>
Arrow_Drop_Down
</Icon>
}
/>
<PopoverContext.Provider value={{ state, referenceWidth }}>
<div className={styles['autocomplete']} ref={ref}>
<TextField
label={props.label}
inputRef={inputRef}
variant={props.variant}
inputProps={inputProps}
onFocus={() => state.setOpen(true)}
trailingIcon={
<Icon
style={{ cursor: 'pointer' }}
onClick={() => {
state.setOpen(!state.isOpen)
// If the input is focused, move the cursor to the end
inputRef.current?.setSelectionRange(
inputRef.current.value.length,
inputRef.current.value.length
)
}}
>
Arrow_Drop_Down
</Icon>
}
/>

{state.isOpen && (
<Popover
state={state}
triggerRef={ref}
popoverRef={popoverRef}
placement="bottom start"
referenceWidth={referenceWidth}
>
<ListBox
state={state}
listBoxRef={listBoxRef}
listBoxProps={listBoxProps}
/>
</Popover>
)}
</div>
{state.isOpen && (
<Popover
triggerRef={ref}
popoverRef={popoverRef}
placement="bottom start"
>
<ListBox
state={state}
listBoxRef={listBoxRef}
listBoxProps={listBoxProps}
/>
</Popover>
)}
</div>
</PopoverContext.Provider>
)
}

Expand Down
7 changes: 4 additions & 3 deletions packages/actify/src/components/Menus/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Button } from './../Button'
import { MenuItem } from './MenuItem'
import { MenuItems } from './MenuItems'
import { Popover } from './../Popover'
import { PopoverContext } from '../Popover/PopoverContext'
import React from 'react'
import clsx from 'clsx'
import styles from './menu.module.css'
Expand All @@ -32,15 +33,15 @@ export function Menu<T extends object>(props: MenuButtonProps<T>) {
const { menuTriggerProps, menuProps } = useMenuTrigger<T>({}, state, ref)

return (
<>
<PopoverContext.Provider value={{ state }}>
{props.label && (
<Button {...menuTriggerProps} ref={ref}>
{props.label}
</Button>
)}
{props?.activator?.(ref, menuTriggerProps)}
{state.isOpen && (
<Popover state={state} triggerRef={ref}>
<Popover triggerRef={ref}>
<MenuRoot
{...props}
{...menuProps}
Expand All @@ -49,7 +50,7 @@ export function Menu<T extends object>(props: MenuButtonProps<T>) {
/>
</Popover>
)}
</>
</PopoverContext.Provider>
)
}

Expand Down
4 changes: 2 additions & 2 deletions packages/actify/src/components/Menus/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './Menu'
export { Menu } from './Menu'

export { Item as MenuItem, Section as MenuItems } from 'react-stately'
export { Item, Section } from 'react-stately'
56 changes: 46 additions & 10 deletions packages/actify/src/components/Popover/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,60 @@ import {
type AriaPopoverProps
} from 'react-aria'

import type { OverlayTriggerState } from 'react-stately'
import type {
OverlayTriggerProps,
PlacementAxis,
PositionProps
} from '@react-types/overlays'

import React from 'react'
import { RenderProps, SlotProps } from './../../utils'
import { PopoverContext } from './PopoverContext'

interface PopoverRenderProps {
/**
* The name of the component that triggered the popover, e.g. "DialogTrigger" or "ComboBox".
* @selector [data-trigger="..."]
*/
trigger: string | null
/**
* The placement of the popover relative to the trigger.
* @selector [data-placement="left | right | top | bottom"]
*/
placement: PlacementAxis
/**
* Whether the popover is currently entering. Use this to apply animations.
* @selector [data-entering]
*/
isEntering: boolean
/**
* Whether the popover is currently exiting. Use this to apply animations.
* @selector [data-exiting]
*/
isExiting: boolean
}

interface PopoverProps extends Omit<AriaPopoverProps, 'popoverRef'> {
referenceWidth?: number
children: React.ReactNode
state: OverlayTriggerState
export interface PopoverProps
extends PositionProps,
Omit<AriaPopoverProps, 'triggerRef' | 'popoverRef'>,
OverlayTriggerProps,
RenderProps<PopoverRenderProps>,
SlotProps {
triggerRef?: React.RefObject<Element | null>
popoverRef?: React.RefObject<Element | null>
}

const Popover = ({ children, referenceWidth, ...props }: PopoverProps) => {
const _popoverRef = React.useRef(null)
const { popoverRef = _popoverRef, state } = props
const Popover = (props: PopoverProps & React.RefAttributes<HTMLElement>) => {
const _triggerRef = React.useRef<HTMLDivElement>(null)
const _popoverRef = React.useRef<HTMLDivElement>(null)

const { triggerRef = _triggerRef, popoverRef = _popoverRef, children } = props
const { state, referenceWidth } = React.useContext(PopoverContext)

const { popoverProps, underlayProps } = usePopover(
{
...props,
triggerRef,
popoverRef
},
state
Expand All @@ -43,8 +80,7 @@ const Popover = ({ children, referenceWidth, ...props }: PopoverProps) => {
className={styles['popover']}
ref={popoverRef as React.RefObject<HTMLDivElement>}
>
{children}
<DismissButton onDismiss={state.close} />
<>{children}</>
</div>
</Overlay>
)
Expand Down
7 changes: 4 additions & 3 deletions packages/actify/src/components/Popover/PopoverActivator.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Button } from '../Button'
import { Popover } from './Popover'
import { PopoverContext } from './PopoverContext'
import React from 'react'
import { useOverlayTrigger } from 'react-aria'
import { useOverlayTriggerState } from 'react-stately'
Expand All @@ -22,16 +23,16 @@ const PopoverActivator = ({
)

return (
<>
<PopoverContext.Provider value={{ state }}>
<Button {...triggerProps} ref={ref}>
{label}
</Button>
{state.isOpen && (
<Popover {...props} triggerRef={ref} state={state}>
<Popover {...props} triggerRef={ref}>
{React.cloneElement(children, overlayProps)}
</Popover>
)}
</>
</PopoverContext.Provider>
)
}

Expand Down
12 changes: 12 additions & 0 deletions packages/actify/src/components/Popover/PopoverContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { OverlayTriggerState } from 'react-stately'
import React from 'react'

type PopoverContextType = {
state: OverlayTriggerState
referenceWidth?: number
}

export const PopoverContext: React.Context<PopoverContextType> =
React.createContext<PopoverContextType>({
state: {} as OverlayTriggerState
})
55 changes: 26 additions & 29 deletions packages/actify/src/components/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Label } from '../Label/Label'
import { ListBox } from '../ListBox'
import { OutlinedField } from './OutlinedField'
import { Popover } from '../Popover/Popover'
import { PopoverContext } from '../Popover/PopoverContext'
import React from 'react'
import { TrailingIcon } from './TrailingIcon'
import clsx from 'clsx'
Expand Down Expand Up @@ -39,37 +40,33 @@ const Select = <T extends object>(props: SelectProps<T>) => {
const referenceWidth = useResizeObserver(ref as React.RefObject<HTMLElement>)

return (
<div
style={props.style}
className={clsx(styles['select'], props.className)}
>
<HiddenSelect
state={state}
triggerRef={ref}
name={props.name}
label={props.label}
isDisabled={props.isDisabled}
/>

<Tag ref={ref} {...triggerProps}>
<Label {...valueProps} style={{ lineHeight: '24px' }}>
{state.selectedItem ? state.selectedItem.rendered : props.label}
</Label>
<TrailingIcon isOpen={state.isOpen} />
</Tag>

{state.isOpen && (
<Popover
offset={2}
<PopoverContext.Provider value={{ state, referenceWidth }}>
<div
style={props.style}
className={clsx(styles['select'], props.className)}
>
<HiddenSelect
state={state}
triggerRef={ref}
placement="bottom start"
referenceWidth={referenceWidth}
>
<ListBox {...menuProps} state={state} />
</Popover>
)}
</div>
name={props.name}
label={props.label}
isDisabled={props.isDisabled}
/>

<Tag ref={ref} {...triggerProps}>
<Label {...valueProps} style={{ lineHeight: '24px' }}>
{state.selectedItem ? state.selectedItem.rendered : props.label}
</Label>
<TrailingIcon isOpen={state.isOpen} />
</Tag>

{state.isOpen && (
<Popover offset={2} triggerRef={ref} placement="bottom start">
<ListBox {...menuProps} state={state} />
</Popover>
)}
</div>
</PopoverContext.Provider>
)
}

Expand Down
1 change: 0 additions & 1 deletion packages/actify/src/components/Slot/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ export {
//
Root
} from './Slot'
export type { SlotProps } from './Slot'
2 changes: 1 addition & 1 deletion packages/actify/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ export * from './components/Spacer'
export * from './components/Tooltips'
export * from './components/Terminal'
export * from './components/BeforeAfter'
export * from './components/Text'
export * from './components/Slot'
export * from './components/Text'
export * from './components/Field'
export * from './components/Label'
export * from './components/VisuallyHidden'
Expand Down
2 changes: 1 addition & 1 deletion packages/actify/src/utils/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ export function composeRenderProps<T, U, V extends T>(

export type WithRef<T, E> = T & { ref?: ForwardedRef<E> }

interface SlotProps {
export interface SlotProps {
/**
* A slot name for the component. Slots allow the component to receive props from a parent component.
* An explicit `null` value indicates that the local props completely override all props received from a parent.
Expand Down

0 comments on commit 4e0d9e7

Please sign in to comment.