Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
9844c50
Add Radix deps
ciampo Mar 30, 2023
0e79741
Re-export radix dropdown with some custom styles
ciampo Mar 30, 2023
9b4c171
Add sample story
ciampo Mar 30, 2023
dc33f98
Start aggregating some components
ciampo Mar 31, 2023
786acc5
Improve storybook config
ciampo Mar 31, 2023
1ccabba
Use better colors
ciampo Apr 4, 2023
d29919a
Fix styles
ciampo Apr 4, 2023
37eb61f
Move types to external file
ciampo Apr 4, 2023
37582a2
Namespace all styled radix components under "DropdownMenuStyled" name…
ciampo Apr 4, 2023
ddda5c1
Use dot icon for radio items instead of check icon
ciampo Apr 4, 2023
4b446db
Pass portal props to portal
ciampo Apr 4, 2023
7a687ef
Add DropdownSubMenu component
ciampo Apr 4, 2023
377c61c
Improve stories to use high-level components
ciampo Apr 4, 2023
c3d36c7
Update notes
ciampo Apr 4, 2023
76ffab2
Comment out unused import
ciampo Apr 4, 2023
0a3acf8
Use menu groups
ciampo Apr 4, 2023
6665504
draft section in contributing guidelines
ciampo Apr 4, 2023
e93beff
Use wordpress icons instead of `@radix-ui/react-icons`
ciampo Apr 4, 2023
6437b35
Add custom `icon` prop to `DropdownMenuItem`
ciampo Apr 4, 2023
557b955
Add missing alignment property for sub trigger
ciampo Apr 4, 2023
76ffa6b
Extract animation variables
ciampo Apr 4, 2023
a1318bf
Align colors more closely to WordPress styles
ciampo Apr 4, 2023
4e32846
Add border to dropdown container
ciampo Apr 4, 2023
4d15f22
Increase spacing, use `space` util
ciampo Apr 4, 2023
76682ec
Use font utils
ciampo Apr 4, 2023
d637c50
Add focus-visible outline
ciampo Apr 4, 2023
7c4769a
Alternative styling for submenu triggers
ciampo Apr 4, 2023
ae83a5e
Pick only selected props for DropdownMenu
ciampo Apr 12, 2023
6dfa27d
Rewrite Storybook example to support controls
ciampo Apr 12, 2023
f376229
DropdownMenuItem: Pick only selected props, support prefix/suffix
ciampo Apr 12, 2023
8f666b1
Remove forwarded refs
ciampo Apr 12, 2023
1574406
Playing around with asChild and ref forwarding
ciampo Apr 12, 2023
b30c4c8
Updated remaining props
ciampo Apr 12, 2023
c41f58a
Add suffix to checkbox / radio items
ciampo Apr 12, 2023
77585cd
Tweak styles (remove arrow, box shadow, center Storybook example)
ciampo Apr 12, 2023
8dedbc1
Try separate submenu trigger component
mirka Apr 26, 2023
a8c66e1
Move layout wrapper to decorator
ciampo May 9, 2023
c6a1c40
Do not use `asChild` for indicator wrappers
ciampo May 9, 2023
d4b9add
Remove solved TODOs
ciampo May 9, 2023
a143f60
RTL support
ciampo May 9, 2023
a6bc304
Add support for reduced motion
ciampo May 9, 2023
a4b27b4
Expose component via lock APIs
ciampo May 9, 2023
d8518c0
Polish styles
ciampo May 10, 2023
c96e449
Generalize storybook
ciampo May 10, 2023
0c6bce7
Focus/hover styles
ciampo May 10, 2023
203b6a9
Refine styles
ciampo May 11, 2023
2bf3379
Tweak storybook example (move separators out of groups, better item t…
ciampo May 12, 2023
6a7ff14
Add unit tests
ciampo May 12, 2023
82b526a
Move legacy implementation to v1 subfolder, move new implementation t…
ciampo May 12, 2023
20552e7
READMEs
ciampo May 12, 2023
ce4d5c5
Tidy up types and JSDocs
ciampo May 12, 2023
f478db2
CHANGELOG
ciampo May 12, 2023
01224d2
Update Storybook example title
ciampo May 12, 2023
b2ffd25
Fix imports
ciampo May 12, 2023
1700cf3
Fix storybook path
ciampo May 12, 2023
1f0b1b8
Fix test import path
ciampo May 16, 2023
1233d26
Fix manifest.json
ciampo May 16, 2023
5768fe7
Move legacy files back to where they were, v2 to separate dropdown-me…
ciampo May 19, 2023
3c31da7
Update CHANGELOG and fix formatting
ciampo May 19, 2023
01e990c
Use WP Button instead of custom button
ciampo May 19, 2023
ce296c2
Remove unnecessary decorator with shared context, using private state…
ciampo May 19, 2023
c9a7826
Remove opinionated wrapper centering styles
ciampo May 19, 2023
ddc1aa8
Update READMEs: remove v1, add experimental callout
ciampo May 19, 2023
da89425
Fix OG DropdownMenu import syntax to be consistent with TypeScript im…
ciampo May 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Start aggregating some components
  • Loading branch information
ciampo committed May 19, 2023
commit dc33f9843a0d7f00ea3665eafd3f1ea174015bd5
115 changes: 106 additions & 9 deletions packages/components/src/ui/radix-dropdown/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
/**
* External dependencies
*/
// Baseline: export all radix components
export * from '@radix-ui/react-dropdown-menu';
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
import { CheckIcon, DividerHorizontalIcon } from '@radix-ui/react-icons';

/**
* WordPress dependencies
*/
import { forwardRef } from '@wordpress/element';

/**
* Internal dependencies
*/
// Overrides some radix components with our styled version
export {
import {
Arrow,
CheckboxItem,
Content,
Expand All @@ -18,10 +22,103 @@ export {
RadioItem,
Root,
Separator,
SubContent,
SubTrigger,
// SubContent,
// SubTrigger,
} from './styles';

// Questions:
// - do we want to have our own JSDocs ?
// - do we want to more explicitly PICK prop types?
type DropdownMenuProps = {
/**
* The props passed to the dropdown's root element
*/
rootProps?: Omit< DropdownMenuPrimitive.DropdownMenuProps, 'children' >;
/**
* The props passed to the dropdown's content
*/
contentProps?: Omit<
DropdownMenuPrimitive.DropdownMenuContentProps,
'children'
>;
/**
* The contents rendered inside the trigger
*/
trigger: React.ReactNode;
/**
* The contents of the dropdown
*/
children: React.ReactNode;
};

// Observations:
// - is it enough to have only one forwarded ref? If we have only one, should it be to the root, or to the content?
// - Should we be consistent in using the same value for the `asChild` prop on both trigger and content?
// - Should we allow customizing the `asChild` prop on trigger and content?
// - Should we explicitly Pick<> every prop ?
export const DropdownMenu = forwardRef(
(
{ children, rootProps, contentProps, trigger }: DropdownMenuProps,
forwardedRef: React.ForwardedRef< any >
) => {
return (
<Root { ...rootProps }>
<DropdownMenuPrimitive.Trigger asChild>
{ trigger }
</DropdownMenuPrimitive.Trigger>
<DropdownMenuPrimitive.Portal>
<Content { ...contentProps } ref={ forwardedRef }>
{ children }
<Arrow />
</Content>
</DropdownMenuPrimitive.Portal>
</Root>
);
}
);

export const DropdownMenuLabel = Label;
export const DropdownMenuItem = Item;
export const DropdownMenuGroup = DropdownMenuPrimitive.Group;

export const DropdownMenuCheckboxItem = forwardRef(
(
{
children,
...props
}: DropdownMenuPrimitive.DropdownMenuCheckboxItemProps,
forwardedRef: React.ForwardedRef< any >
) => {
return (
<CheckboxItem { ...props } ref={ forwardedRef }>
{ children }
<ItemIndicator>
{ props.checked === 'indeterminate' && (
<DividerHorizontalIcon />
) }
{ props.checked === true && <CheckIcon /> }
</ItemIndicator>
</CheckboxItem>
);
}
);

export const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;

export const DropdownMenuRadioItem = forwardRef(
(
{
children,
...props
}: DropdownMenuPrimitive.DropdownMenuRadioItemProps,
forwardedRef: React.ForwardedRef< any >
) => {
return (
<RadioItem { ...props } ref={ forwardedRef }>
{ children }
<ItemIndicator>
<CheckIcon />
</ItemIndicator>
</RadioItem>
);
}
);

export const DropdownMenuSeparator = Separator;
206 changes: 96 additions & 110 deletions packages/components/src/ui/radix-dropdown/stories/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,26 @@ import { css } from '@emotion/react';
/**
* Internal dependencies
*/
import * as DropdownMenu from '../';
import { DropdownMenu, DropdownMenuItem } from '../';
import { useCx } from '../../../utils/hooks/use-cx';

// TODO: replace with wordpress/icons
import {
HamburgerMenuIcon,
DotFilledIcon,
CheckIcon,
ChevronRightIcon,
// DotFilledIcon,
// CheckIcon,
// ChevronRightIcon,
} from '@radix-ui/react-icons';

/**
* WordPress dependencies
*/
import { useState } from '@wordpress/element';
// import { useState } from '@wordpress/element';

const meta: ComponentMeta< typeof DropdownMenu.Root > = {
const meta: ComponentMeta< typeof DropdownMenu > = {
title: 'Components/RadixDropdown',
component: DropdownMenu.Root,
// subcomponents: { DropdownMenu. },
component: DropdownMenu,
subcomponents: { DropdownMenuItem },
argTypes: {
// focusOnMount: {
// options: [ 'firstElement', true, false ],
Expand Down Expand Up @@ -82,120 +82,106 @@ const rightSlot = css`
`;

export const DropdownMenuDemo = () => {
const [ bookmarksChecked, setBookmarksChecked ] = useState( true );
const [ urlsChecked, setUrlsChecked ] = useState( false );
const [ person, setPerson ] = useState( 'pedro' );
// const [ bookmarksChecked, setBookmarksChecked ] = useState( true );
// const [ urlsChecked, setUrlsChecked ] = useState( false );
// const [ person, setPerson ] = useState( 'pedro' );

const cx = useCx();

const rightSlotClassName = cx( rightSlot );

return (
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<DropdownMenu
trigger={
<button
className={ cx( iconButton ) }
aria-label="Customise options"
>
<HamburgerMenuIcon />
</button>
</DropdownMenu.Trigger>

<DropdownMenu.Portal>
<DropdownMenu.Content sideOffset={ 5 }>
<DropdownMenu.Item>
New Tab <div className={ rightSlotClassName }>⌘+T</div>
</DropdownMenu.Item>
<DropdownMenu.Item>
New Window{ ' ' }
<div className={ rightSlotClassName }>⌘+N</div>
</DropdownMenu.Item>
<DropdownMenu.Item disabled>
New Private Window{ ' ' }
<div className={ rightSlotClassName }>⇧+⌘+N</div>
</DropdownMenu.Item>
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger>
More Tools
<div className={ rightSlotClassName }>
<ChevronRightIcon />
</div>
</DropdownMenu.SubTrigger>
<DropdownMenu.Portal>
<DropdownMenu.SubContent
sideOffset={ 2 }
alignOffset={ -5 }
>
<DropdownMenu.Item>
Save Page As…{ ' ' }
<div className={ rightSlotClassName }>
⌘+S
</div>
</DropdownMenu.Item>
<DropdownMenu.Item>
Create Shortcut…
</DropdownMenu.Item>
<DropdownMenu.Item>
Name Window…
</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item>
Developer Tools
</DropdownMenu.Item>
</DropdownMenu.SubContent>
</DropdownMenu.Portal>
</DropdownMenu.Sub>

<DropdownMenu.Separator />

<DropdownMenu.CheckboxItem
checked={ bookmarksChecked }
onCheckedChange={ setBookmarksChecked }
}
contentProps={ { sideOffset: 5 } }
>
<DropdownMenuItem>
New Tab <div className={ rightSlotClassName }>⌘+T</div>
</DropdownMenuItem>
<DropdownMenuItem>
New Window <div className={ rightSlotClassName }>⌘+N</div>
</DropdownMenuItem>
<DropdownMenuItem disabled>
New Private Window{ ' ' }
<div className={ rightSlotClassName }>⇧+⌘+N</div>
</DropdownMenuItem>

{ /* <DropdownMenu.Sub>
<DropdownMenu.SubTrigger>
More Tools
<div className={ rightSlotClassName }>
<ChevronRightIcon />
</div>
</DropdownMenu.SubTrigger>
<DropdownMenu.Portal>
<DropdownMenu.SubContent
sideOffset={ 2 }
alignOffset={ -5 }
>
<DropdownMenu.ItemIndicator>
<CheckIcon />
</DropdownMenu.ItemIndicator>
Show Bookmarks{ ' ' }
<div className={ rightSlotClassName }>⌘+B</div>
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
className="DropdownMenuCheckboxItem"
checked={ urlsChecked }
onCheckedChange={ setUrlsChecked }
>
<DropdownMenu.ItemIndicator>
<CheckIcon />
</DropdownMenu.ItemIndicator>
Show Full URLs
</DropdownMenu.CheckboxItem>

<DropdownMenu.Separator />

<DropdownMenu.Label>People</DropdownMenu.Label>
<DropdownMenu.RadioGroup
value={ person }
onValueChange={ setPerson }
>
<DropdownMenu.RadioItem value="pedro">
<DropdownMenu.ItemIndicator>
<DotFilledIcon />
</DropdownMenu.ItemIndicator>
Pedro Duarte
</DropdownMenu.RadioItem>
<DropdownMenu.RadioItem
className="DropdownMenuRadioItem"
value="colm"
>
<DropdownMenu.ItemIndicator>
<DotFilledIcon />
</DropdownMenu.ItemIndicator>
Colm Tuite
</DropdownMenu.RadioItem>
</DropdownMenu.RadioGroup>

<DropdownMenu.Arrow />
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
<DropdownMenu.Item>
Save Page As…{ ' ' }
<div className={ rightSlotClassName }>⌘+S</div>
</DropdownMenu.Item>
<DropdownMenu.Item>Create Shortcut…</DropdownMenu.Item>
<DropdownMenu.Item>Name Window…</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item>Developer Tools</DropdownMenu.Item>
</DropdownMenu.SubContent>
</DropdownMenu.Portal>
</DropdownMenu.Sub>

<DropdownMenu.Separator />

<DropdownMenu.CheckboxItem
checked={ bookmarksChecked }
onCheckedChange={ setBookmarksChecked }
>
<DropdownMenu.ItemIndicator>
<CheckIcon />
</DropdownMenu.ItemIndicator>
Show Bookmarks <div className={ rightSlotClassName }>⌘+B</div>
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
className="DropdownMenuCheckboxItem"
checked={ urlsChecked }
onCheckedChange={ setUrlsChecked }
>
<DropdownMenu.ItemIndicator>
<CheckIcon />
</DropdownMenu.ItemIndicator>
Show Full URLs
</DropdownMenu.CheckboxItem>

<DropdownMenu.Separator />

<DropdownMenu.Label>People</DropdownMenu.Label>
<DropdownMenu.RadioGroup
value={ person }
onValueChange={ setPerson }
>
<DropdownMenu.RadioItem value="pedro">
<DropdownMenu.ItemIndicator>
<DotFilledIcon />
</DropdownMenu.ItemIndicator>
Pedro Duarte
</DropdownMenu.RadioItem>
<DropdownMenu.RadioItem
className="DropdownMenuRadioItem"
value="colm"
>
<DropdownMenu.ItemIndicator>
<DotFilledIcon />
</DropdownMenu.ItemIndicator>
Colm Tuite
</DropdownMenu.RadioItem>
</DropdownMenu.RadioGroup> */ }
</DropdownMenu>
);
};