diff --git a/.changeset/warm-countries-cry.md b/.changeset/warm-countries-cry.md new file mode 100644 index 00000000..93f81a09 --- /dev/null +++ b/.changeset/warm-countries-cry.md @@ -0,0 +1,5 @@ +--- +"@status-im/components": patch +--- + +Add `` and `` diff --git a/packages/components/package.json b/packages/components/package.json index 7ef450a3..0705a662 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -47,6 +47,7 @@ "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-popover": "^1.1.1", + "@radix-ui/react-switch": "^1.1.0", "@radix-ui/react-tabs": "^1.1.0", "@radix-ui/react-toast": "^1.2.1", "@radix-ui/react-tooltip": "^1.1.2", diff --git a/packages/components/src/checkbox/checkbox.tsx b/packages/components/src/checkbox/checkbox.tsx index 4a6eae01..684c6438 100644 --- a/packages/components/src/checkbox/checkbox.tsx +++ b/packages/components/src/checkbox/checkbox.tsx @@ -7,7 +7,7 @@ import { cva } from 'cva' import type { VariantProps } from 'cva' -type Variants = VariantProps +type Variants = VariantProps type Props = Omit & { checked: boolean @@ -23,7 +23,7 @@ const Root = forwardRef, Props>( , Props>( Root.displayName = Checkbox.Root.displayName -const styles = cva({ +const rootStyles = cva({ base: [ - 'group inline-flex size-[18px] shrink-0 items-center justify-center overflow-hidden rounded-6 text-white-100 transition-colors', + 'group inline-flex size-[18px] shrink-0 cursor-default items-center justify-center overflow-hidden rounded-6 text-white-100 transition-colors', 'border border-neutral-20 hover:border-neutral-30', 'aria-checked:border-customisation-50 aria-checked:bg-customisation-50 aria-checked:hover:border-customisation-60 aria-checked:hover:bg-customisation-60', 'focus-visible:ring-2 focus-visible:ring-customisation-50 focus-visible:ring-offset-2', diff --git a/packages/components/src/dropdown-menu/dropdown-menu.stories.tsx b/packages/components/src/dropdown-menu/dropdown-menu.stories.tsx index 7a21f836..407e8902 100644 --- a/packages/components/src/dropdown-menu/dropdown-menu.stories.tsx +++ b/packages/components/src/dropdown-menu/dropdown-menu.stories.tsx @@ -31,9 +31,8 @@ const meta: Meta = { }, render: args => { - // eslint-disable-next-line react-hooks/rules-of-hooks - const [isChecked, setIsChecked] = useState(false) - + const [isChecked, setIsChecked] = useState(false) // eslint-disable-line react-hooks/rules-of-hooks + const [isChecked2, setIsChecked2] = useState(false) // eslint-disable-line react-hooks/rules-of-hooks return ( Open @@ -100,6 +99,13 @@ const meta: Meta = { onCheckedChange={setIsChecked} onSelect={e => e.preventDefault()} /> + } + label="Toggle alerts" + checked={isChecked2} + onCheckedChange={setIsChecked2} + onSelect={e => e.preventDefault()} + /> diff --git a/packages/components/src/dropdown-menu/dropdown-menu.tsx b/packages/components/src/dropdown-menu/dropdown-menu.tsx index a3b5033f..02838b30 100644 --- a/packages/components/src/dropdown-menu/dropdown-menu.tsx +++ b/packages/components/src/dropdown-menu/dropdown-menu.tsx @@ -11,6 +11,7 @@ import { cva } from 'cva' import { Checkbox } from '../checkbox' import { Input } from '../input' +import { Switch } from '../switch' import type { IconElement } from '../types' @@ -111,7 +112,7 @@ type ItemProps = DropdownMenu.DropdownMenuItemProps & { const itemStyles = cva({ base: [ - 'flex h-8 cursor-pointer select-none items-center gap-2 rounded-8 px-2 text-15 transition-colors active:bg-neutral-10', + 'flex h-8 select-none items-center gap-2 rounded-8 px-2 text-15 transition-colors active:bg-neutral-10', 'outline-none data-[highlighted]:bg-neutral-5', 'dark:active:bg-customisation-50/10 dark:hover:bg-customisation-50/5', ], @@ -198,7 +199,7 @@ export const CheckboxItem = forwardRef< variant="outline" checked={itemProps.checked} onCheckedChange={() => { - // handle by parent + // handled by parent }} /> @@ -207,6 +208,49 @@ export const CheckboxItem = forwardRef< CheckboxItem.displayName = DropdownMenu.CheckboxItem.displayName +/** + * SwitchItem + */ + +type SwitchItemProps = DropdownMenu.DropdownMenuCheckboxItemProps & { + icon?: IconElement + label: string + checked: boolean + onCheckedChange: (checked: boolean) => void + danger?: boolean +} + +export const SwitchItem = forwardRef< + React.ElementRef, + SwitchItemProps +>((props, ref) => { + const { label, icon, danger, ...itemProps } = props + + const id = useId() + + return ( + + {icon && ( + {cloneElement(icon)} + )} + {label} + { + // handled by parent + }} + /> + + ) +}) + +SwitchItem.displayName = 'DropdownMenuSwitchItem' + /** * Separator */ diff --git a/packages/components/src/index.tsx b/packages/components/src/index.tsx index 63ace6d7..9f2c5166 100644 --- a/packages/components/src/index.tsx +++ b/packages/components/src/index.tsx @@ -12,6 +12,7 @@ export { StatusProvider } from './provider' export { Shortcut } from './shortcut' export { Skeleton } from './skeleton' export { Step } from './step' +export { Switch } from './switch' export { Tabs } from './tabs' export { Tag } from './tag' export { Text } from './text' diff --git a/packages/components/src/switch/index.tsx b/packages/components/src/switch/index.tsx new file mode 100644 index 00000000..85599dd6 --- /dev/null +++ b/packages/components/src/switch/index.tsx @@ -0,0 +1,2 @@ +export type { SwitchProps } from './switch' +export { Switch } from './switch' diff --git a/packages/components/src/switch/switch.stories.tsx b/packages/components/src/switch/switch.stories.tsx new file mode 100644 index 00000000..c69b520e --- /dev/null +++ b/packages/components/src/switch/switch.stories.tsx @@ -0,0 +1,50 @@ +import { Switch } from './switch' + +import type { Meta, StoryObj } from '@storybook/react' + +const Variant = (props: React.ComponentProps) => { + return ( +
+ + + +
+ ) +} + +const meta: Meta = { + title: 'Components/Switch', + component: Switch, + args: { + // size: 'md', + }, + parameters: { + design: { + type: 'figma', + url: 'https://www.figma.com/design/IBmFKgGL1B4GzqD8LQTw6n/Design-System-for-Desktop%2FWeb?node-id=370-18368&node-type=frame&m=dev', + }, + }, + + render: props => { + return ( +
+ + +
+ ) + }, +} + +type Story = StoryObj + +export const Light: Story = {} + +export const Dark: Story = { + parameters: { + backgrounds: { + default: 'dark', + }, + }, +} + +export default meta diff --git a/packages/components/src/switch/switch.tsx b/packages/components/src/switch/switch.tsx new file mode 100644 index 00000000..dc645030 --- /dev/null +++ b/packages/components/src/switch/switch.tsx @@ -0,0 +1,43 @@ +'use client' + +import { forwardRef } from 'react' + +import * as Switch from '@radix-ui/react-switch' +import { cva } from 'cva' + +type Props = Switch.SwitchProps & { + checked: boolean + onCheckedChange: (checked: boolean) => void +} + +const Root = forwardRef, Props>( + (props, ref) => { + return ( + + + + ) + }, +) + +Root.displayName = Switch.Root.displayName + +const rootStyles = cva({ + base: [ + 'relative h-5 w-[30px] shrink-0 cursor-default rounded-full outline-none transition-colors', + 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-customisation-50 focus-visible:ring-offset-2', + 'bg-neutral-20 data-[state=checked]:bg-customisation-blue-50 hover:bg-neutral-30 data-[state=checked]:hover:bg-customisation-blue-60', + 'dark:bg-neutral-80 dark:data-[state=checked]:bg-customisation-blue-60 dark:hover:bg-neutral-70 dark:data-[state=checked]:hover:bg-customisation-blue-50 dark:focus-visible:ring-offset-neutral-80', + 'data-[disabled]:pointer-events-none data-[disabled]:opacity-[30%]', + ], +}) + +const thumbStyles = cva({ + base: [ + 'block size-4 rounded-full bg-white-100', + 'translate-x-0.5 transition-transform duration-100 data-[state=checked]:translate-x-[12px]', + ], +}) + +export { Root as Switch } +export type { Props as SwitchProps } diff --git a/yarn.lock b/yarn.lock index aa1314e3..b86a24b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2483,6 +2483,19 @@ dependencies: "@radix-ui/react-compose-refs" "1.1.0" +"@radix-ui/react-switch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-switch/-/react-switch-1.1.0.tgz#fcf8e778500f1d60d4b2bec2fc3fad77a7c118e3" + integrity sha512-OBzy5WAj641k0AOSpKQtreDMe+isX0MQJ1IVyF03ucdF3DunOnROVrjWs8zsXUxC3zfZ6JL9HFVCUlMghz9dJw== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-previous" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + "@radix-ui/react-tabs@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.1.0.tgz#0a6db1caed56776a1176aae68532060e301cc1c0"