diff --git a/package.json b/package.json index f39fffc..06c5f6e 100644 --- a/package.json +++ b/package.json @@ -44,9 +44,11 @@ "@dydxprotocol/v4-localization": "^1.0.5", "@ethersproject/providers": "^5.7.2", "@js-joda/core": "^5.5.3", + "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-dropdown-menu": "^2.0.5", + "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-navigation-menu": "^1.1.3", "@radix-ui/react-popover": "^1.0.6", "@radix-ui/react-radio-group": "^1.1.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 470293e..cd5bd27 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,9 +1,5 @@ lockfileVersion: '6.0' -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - dependencies: '@0xsquid/sdk': specifier: ^1.10.0 @@ -41,6 +37,9 @@ dependencies: '@js-joda/core': specifier: ^5.5.3 version: 5.5.3 + '@radix-ui/react-checkbox': + specifier: ^1.0.4 + version: 1.0.4(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-collapsible': specifier: ^1.0.3 version: 1.0.3(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0) @@ -50,6 +49,9 @@ dependencies: '@radix-ui/react-dropdown-menu': specifier: ^2.0.5 version: 2.0.5(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-icons': + specifier: ^1.3.0 + version: 1.3.0(react@18.2.0) '@radix-ui/react-navigation-menu': specifier: ^1.1.3 version: 1.1.3(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0) @@ -2181,6 +2183,34 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-checkbox@1.0.4(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.22.10 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.14)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.14)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.14)(react@18.2.0) + '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.14)(react@18.2.0) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.14)(react@18.2.0) + '@types/react': 18.2.14 + '@types/react-dom': 18.2.6 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==} peerDependencies: @@ -2482,6 +2512,14 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-icons@1.3.0(react@18.2.0): + resolution: {integrity: sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==} + peerDependencies: + react: ^16.x || ^17.x || ^18.x + dependencies: + react: 18.2.0 + dev: false + /@radix-ui/react-id@1.0.0(react@18.2.0): resolution: {integrity: sha512-Q6iAB/U7Tq3NTolBBQbHTgclPmGWE3OlktGGqrClPozSw4vkQ1DfQAOtzgRPecKsMdJINE05iaoDUG8tRzCBjw==} peerDependencies: @@ -14099,3 +14137,7 @@ packages: /zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} dev: true + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false diff --git a/public/wallets/generic-wallet.png b/public/wallets/generic-wallet.png index 2c48616..8492d6e 100644 Binary files a/public/wallets/generic-wallet.png and b/public/wallets/generic-wallet.png differ diff --git a/src/components/Checkbox.stories.tsx b/src/components/Checkbox.stories.tsx index db559f6..248519c 100644 --- a/src/components/Checkbox.stories.tsx +++ b/src/components/Checkbox.stories.tsx @@ -13,7 +13,9 @@ export const Checkboxes: Story = (args) => { setIsChecked((e.target as HTMLInputElement).checked)} + onCheckedChange={setIsChecked} + id="story-checkbox" + label="example label" /> ); diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx index 973a0f2..037f881 100644 --- a/src/components/Checkbox.tsx +++ b/src/components/Checkbox.tsx @@ -1,10 +1,14 @@ import styled, { type AnyStyledComponent } from 'styled-components'; +import { Root, Indicator } from '@radix-ui/react-checkbox'; +import { CheckIcon } from '@radix-ui/react-icons'; -import { breakpoints } from '@/styles'; +import { layoutMixins } from '@/styles/layoutMixins'; type ElementProps = { checked: boolean; - onClick: (e: React.ChangeEvent) => void; + onCheckedChange: (checked: boolean) => void; + id?: string; + label?: React.ReactNode; }; type StyleProps = { @@ -13,85 +17,54 @@ type StyleProps = { export type CheckboxProps = ElementProps & StyleProps; -export const Checkbox: React.FC = ({ checked, className, onClick }) => { - return ( - - - - - ); -}; +export const Checkbox: React.FC = ({ + checked, + className, + onCheckedChange, + id, + label, +}) => ( + + + + + + + {label && } + +); const Styled: Record = {}; -Styled.CustomCheckbox = styled.span` - width: 1.25em; - height: 1.25em; +Styled.Container = styled.div` + ${layoutMixins.row} + gap: 1ch; + font: var(--font-small-book); - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; + label { + cursor: pointer; + } +`; + +Styled.Root = styled(Root)` + --checkbox-backgroundColor: var(--color-layer-0); + + min-width: 1.25rem; + height: 1.25rem; + + border-radius: 0.375rem; + border: var(--border-width) solid var(--color-border); background-color: var(--checkbox-backgroundColor); - &::after { - position: absolute; - content: ''; - top: 0.25em; - left: 0.4375em; - width: 0.3125em; - height: 0.5em; - border: solid var(--checkbox-checkColor); - border-width: 0 0.125em 0.125em 0; - border-radius: 0.0625em; - opacity: 0; - transform: rotate(0deg) scale(0); - transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out; - } - - @media ${breakpoints.tablet} { - width: 1.5em; - height: 1.5em; - - &::after { - top: 0.25em; - left: 0.4375em; - width: 0.4375em; - height: 0.625em; - } + &[data-state='checked'] { + --checkbox-backgroundColor: var(--color-accent); } `; -Styled.CheckboxWrapper = styled.div` - --checkbox-backgroundColor: var(--color-layer-1); - --checkbox-checkColor: var(--color-text-1); - +Styled.Indicator = styled(Indicator)` display: flex; - border-radius: 0.25em; - overflow: hidden; - position: relative; - cursor: pointer; + align-items: center; + justify-content: center; - > input:checked ~ ${Styled.CustomCheckbox}::after { - opacity: 1; - transform: rotate(40deg) scale(1); - } -`; - -Styled.Checkbox = styled.input` - width: 1.25em; - height: 1.25em; - z-index: 1; - cursor: pointer; - opacity: 0; - - @media ${breakpoints.tablet} { - width: 1.5em; - height: 1.5em; - } + color: var(--color-text-2); `; diff --git a/src/components/CopyButton.stories.tsx b/src/components/CopyButton.stories.tsx index 71f4070..f3d0934 100644 --- a/src/components/CopyButton.stories.tsx +++ b/src/components/CopyButton.stories.tsx @@ -15,10 +15,10 @@ CopyButtonStory.args = { }; CopyButtonStory.argTypes = { - shownAsText: { - options: [true, false], + buttonType: { + options: ["text", "icon", "default"], control: { type: 'select' }, - defaultValue: false, + defaultValue: "default", }, children: { options: ['some text to copy'], diff --git a/src/components/CopyButton.tsx b/src/components/CopyButton.tsx index 5da154e..4c0cf53 100644 --- a/src/components/CopyButton.tsx +++ b/src/components/CopyButton.tsx @@ -9,14 +9,20 @@ import { layoutMixins } from '@/styles/layoutMixins'; import { Button, ButtonProps } from './Button'; import { Icon, IconName } from './Icon'; +import { IconButton } from './IconButton'; export type CopyButtonProps = { value?: string; - shownAsText?: boolean; + buttonType?: 'text' | 'icon' | 'default'; children?: React.ReactNode; } & ButtonProps; -export const CopyButton = ({ value, shownAsText, children, ...buttonProps }: CopyButtonProps) => { +export const CopyButton = ({ + value, + buttonType = 'default', + children, + ...buttonProps +}: CopyButtonProps) => { const stringGetter = useStringGetter(); const [copied, setCopied] = useState(false); @@ -28,11 +34,19 @@ export const CopyButton = ({ value, shownAsText, children, ...buttonProps }: Cop setTimeout(() => setCopied(false), 500); }; - return shownAsText ? ( + return buttonType === 'text' ? ( {children} - + + ) : buttonType === 'icon' ? ( + ) : (