From 13a9a1e992315e9aaee7f0431d15389a6794ec7c Mon Sep 17 00:00:00 2001 From: Camila Sosa Morales Date: Fri, 10 Mar 2023 09:04:30 -0500 Subject: [PATCH] feat: UI toast component (#160) * chore: install radix toast * feat: add toast component * chore: display toast column * chore: remove commented lines * chore: fix animation --- ui/package.json | 1 + ui/src/app.tsx | 2 + ui/src/components/core/button/icon-button.tsx | 2 +- ui/src/components/core/icon/custom/error.tsx | 15 +++ ui/src/components/core/icon/icon-library.tsx | 6 ++ ui/src/components/index.ts | 1 + ui/src/components/toast/index.ts | 1 + ui/src/components/toast/toast.styles.tsx | 101 ++++++++++++++++++ ui/src/components/toast/toast.tsx | 73 +++++++++++++ ui/src/store/features/index.ts | 3 +- ui/src/store/features/toasts/index.ts | 1 + ui/src/store/features/toasts/toasts-slice.ts | 46 ++++++++ ui/src/store/store.ts | 4 +- ui/src/theme/index.ts | 1 + ui/src/theme/key-frames.ts | 22 ++++ ui/src/utils/index.ts | 1 + ui/src/utils/toast.ts | 10 ++ .../views/components-test/combobox-test.tsx | 50 +++++++++ .../views/components-test/components-test.tsx | 50 ++------- ui/src/views/components-test/toast-test.tsx | 24 +++++ ui/yarn.lock | 98 +++++++++++++++++ 21 files changed, 465 insertions(+), 47 deletions(-) create mode 100644 ui/src/components/core/icon/custom/error.tsx create mode 100644 ui/src/components/toast/index.ts create mode 100644 ui/src/components/toast/toast.styles.tsx create mode 100644 ui/src/components/toast/toast.tsx create mode 100644 ui/src/store/features/toasts/index.ts create mode 100644 ui/src/store/features/toasts/toasts-slice.ts create mode 100644 ui/src/theme/key-frames.ts create mode 100644 ui/src/utils/toast.ts create mode 100644 ui/src/views/components-test/combobox-test.tsx create mode 100644 ui/src/views/components-test/toast-test.tsx diff --git a/ui/package.json b/ui/package.json index cfc6733..026c80b 100644 --- a/ui/package.json +++ b/ui/package.json @@ -21,6 +21,7 @@ "@headlessui/react": "^1.7.8", "@radix-ui/colors": "^0.1.8", "@radix-ui/react-avatar": "^1.0.1", + "@radix-ui/react-toast": "^1.1.2", "@react-icons/all-files": "^4.1.0", "@reduxjs/toolkit": "^1.9.1", "@stitches/react": "^1.2.8", diff --git a/ui/src/app.tsx b/ui/src/app.tsx index c956c37..a406226 100644 --- a/ui/src/app.tsx +++ b/ui/src/app.tsx @@ -4,6 +4,7 @@ import { ComponentsTest, Home, Mint } from './views'; import { SVGTestScreen } from './views/svg-test'; // TODO: remove when done import { ConnectKitButton } from 'connectkit'; import { MintTest } from './views/mint-test'; +import { ToastProvider } from './components'; import { CreateAP } from './views/access-point'; export const App = () => { @@ -14,6 +15,7 @@ export const App = () => { {/* TODO remove after adding NavBar */} + } /> diff --git a/ui/src/components/core/button/icon-button.tsx b/ui/src/components/core/button/icon-button.tsx index cbb6c08..3061d9a 100644 --- a/ui/src/components/core/button/icon-button.tsx +++ b/ui/src/components/core/button/icon-button.tsx @@ -29,7 +29,7 @@ export interface IconButtonProps extends BaseButtonProps { 'aria-label': string; } -export const IconButton = forwardRef( +export const IconButton = forwardRef( function IconButton(props, ref) { const { icon, diff --git a/ui/src/components/core/icon/custom/error.tsx b/ui/src/components/core/icon/custom/error.tsx new file mode 100644 index 0000000..c82a358 --- /dev/null +++ b/ui/src/components/core/icon/custom/error.tsx @@ -0,0 +1,15 @@ +import { IconStyles as IS } from '../icon.styles'; + +export const ErrorIcon: React.FC = (props) => ( + + + +); diff --git a/ui/src/components/core/icon/icon-library.tsx b/ui/src/components/core/icon/icon-library.tsx index d4a39fe..8ad03c7 100644 --- a/ui/src/components/core/icon/icon-library.tsx +++ b/ui/src/components/core/icon/icon-library.tsx @@ -8,18 +8,24 @@ import { IoCloudUploadSharp } from '@react-icons/all-files/io5/IoCloudUploadShar import { MetamaskIcon, EthereumIcon } from './custom'; import { IoCheckmarkCircleSharp } from '@react-icons/all-files/io5/IoCheckmarkCircleSharp'; import { AiOutlineTwitter } from '@react-icons/all-files/ai/AiOutlineTwitter'; +import { ErrorIcon } from './custom/error'; +import { IoClose } from '@react-icons/all-files/io5/IoClose'; +import { AiFillCheckCircle } from '@react-icons/all-files/ai/AiFillCheckCircle'; export const IconLibrary = Object.freeze({ back: IoArrowBackCircleSharp, check: AiOutlineCheck, 'check-circle': IoCheckmarkCircleSharp, 'chevron-down': AiOutlineDown, + close: IoClose, + error: ErrorIcon, ethereum: EthereumIcon, github: IoLogoGithub, info: IoInformationCircleSharp, upload: IoCloudUploadSharp, metamask: MetamaskIcon, //remove if not used search: BiSearch, + success: AiFillCheckCircle, twitter: AiOutlineTwitter, }); diff --git a/ui/src/components/index.ts b/ui/src/components/index.ts index 5d821dc..c01aa91 100644 --- a/ui/src/components/index.ts +++ b/ui/src/components/index.ts @@ -3,3 +3,4 @@ export * from './layout'; export * from './form'; export * from './card'; export * from './spinner'; +export * from './toast'; diff --git a/ui/src/components/toast/index.ts b/ui/src/components/toast/index.ts new file mode 100644 index 0000000..ddce050 --- /dev/null +++ b/ui/src/components/toast/index.ts @@ -0,0 +1 @@ +export * from './toast'; diff --git a/ui/src/components/toast/toast.styles.tsx b/ui/src/components/toast/toast.styles.tsx new file mode 100644 index 0000000..f4d11e5 --- /dev/null +++ b/ui/src/components/toast/toast.styles.tsx @@ -0,0 +1,101 @@ +import { dripStitches } from '@/theme'; +import * as ToastLib from '@radix-ui/react-toast'; +import { Icon, IconButton } from '../core'; +import { Flex } from '../layout'; + +const { styled, keyframes } = dripStitches; + +export abstract class ToastStyles { + static readonly Provider = ToastLib.Provider; + + static readonly DismissTimeout = 200; + + static readonly ViewportPadding = '$md'; + + static readonly KeyFrames = { + hide: keyframes({ + '0%': { opacity: 1 }, + '100%': { opacity: 0 }, + }), + show: keyframes({ + '0%': { opacity: 0 }, + '100%': { opacity: 1 }, + }), + }; + + static readonly Root = styled(ToastLib.Root, { + padding: '$4 $5', + borderRadius: '$lg', + borderWidth: '$default', + maxWidth: '$128', + + variants: { + variant: { + error: { + backgroundColor: '$red3', + borderColor: '$red6', + color: '$red11', + }, + success: { + backgroundColor: '$green3', + borderColor: '$green6', + color: '$green11', + }, + }, + }, + + '@media (prefers-reduced-motion: no-preference)': { + '&[data-state="open"]': { + animation: `${this.KeyFrames.show} 750ms `, + }, + '&[data-state="closed"]': { + animation: `${this.KeyFrames.hide} ${this.DismissTimeout}ms ease-in`, + }, + }, + }); + + static readonly Body = styled(ToastLib.Description, { + fontSize: '$md', + fontWeight: '$normal', + mr: '$5', + }); + + static readonly Close = styled(ToastLib.Close, {}); + + static readonly CloseButton = styled(IconButton, { + variants: { + colorScheme: { + error: { + color: '$red11 !important', + }, + success: { + color: '$green11 !important', + }, + }, + }, + }); + + static readonly Viewport = styled(ToastLib.Viewport, { + padding: '$14', + + position: 'fixed', + bottom: 0, + left: '50%', + transform: 'translate(-50%)', + display: 'flex', + flexDirection: 'column', + gap: '$4', + }); + + static readonly Layout = styled(Flex, { + flexDirection: 'row', + justifyContent: 'space-between', + }); + + static readonly Icon = styled(Icon, { + fontSize: '$5', + marginRight: '$2h', + }); + + static readonly Content = styled(Flex, {}); +} diff --git a/ui/src/components/toast/toast.tsx b/ui/src/components/toast/toast.tsx new file mode 100644 index 0000000..f11cfb6 --- /dev/null +++ b/ui/src/components/toast/toast.tsx @@ -0,0 +1,73 @@ +import { + toastsActions, + ToastsState, + useAppDispatch, + useToastsState, +} from '@/store'; +import { useCallback, useState } from 'react'; +import { Icon } from '../core'; +import { ToastStyles } from './toast.styles'; + +type ToastProps = ToastsState.Toast; + +const Toast: React.FC = ({ + id, + type, + message, + onDismiss, + duration = 3000, +}) => { + const dispatch = useAppDispatch(); + const [open, setOpen] = useState(true); + + const handleOpenChange = useCallback( + (value: boolean) => { + setOpen(value); + if (!value) { + if (onDismiss) onDismiss(); + setTimeout(() => { + dispatch(toastsActions.dismiss(id)); + }, ToastStyles.DismissTimeout); + } + }, + [onDismiss, dispatch, id] + ); + + return ( + + + + + {message} + + + } + onClick={onDismiss} + /> + + + + ); +}; + +export const ToastProvider: React.FC = () => { + const { toasts } = useToastsState(); + + return ( + + {toasts.map((toast) => ( + + ))} + + + ); +}; diff --git a/ui/src/store/features/index.ts b/ui/src/store/features/index.ts index a587625..22ab4b0 100644 --- a/ui/src/store/features/index.ts +++ b/ui/src/store/features/index.ts @@ -1,2 +1,3 @@ -export * from './github'; export * from './ens'; +export * from './github'; +export * from './toasts'; diff --git a/ui/src/store/features/toasts/index.ts b/ui/src/store/features/toasts/index.ts new file mode 100644 index 0000000..9d96d9a --- /dev/null +++ b/ui/src/store/features/toasts/index.ts @@ -0,0 +1 @@ +export * from './toasts-slice'; diff --git a/ui/src/store/features/toasts/toasts-slice.ts b/ui/src/store/features/toasts/toasts-slice.ts new file mode 100644 index 0000000..3d87514 --- /dev/null +++ b/ui/src/store/features/toasts/toasts-slice.ts @@ -0,0 +1,46 @@ +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; + +import type { RootState } from '@/store'; +import { useAppSelector } from '@/store/hooks'; + +export namespace ToastsState { + export type Toast = { + id: number; + type: 'success' | 'error'; + message: string; + onDismiss?: () => void; + duration?: number; + }; +} + +interface ToastsState { + toasts: ToastsState.Toast[]; +} + +const initialState: ToastsState = { + toasts: [], +}; + +export const toastsSlice = createSlice({ + name: 'toasts', + initialState, + reducers: { + push: (state, action: PayloadAction>) => { + state.toasts = [...state.toasts, { ...action.payload, id: Date.now() }]; + }, + dismiss: (state, action: PayloadAction) => { + state.toasts = state.toasts.filter( + (toast) => toast.id !== action.payload + ); + }, + }, +}); + +export const toastsActions = { ...toastsSlice.actions }; + +const selectToastsState = (state: RootState): ToastsState => state.toasts; + +export const useToastsState = (): ToastsState => + useAppSelector(selectToastsState); + +export default toastsSlice.reducer; diff --git a/ui/src/store/store.ts b/ui/src/store/store.ts index f86bae7..db53f7b 100644 --- a/ui/src/store/store.ts +++ b/ui/src/store/store.ts @@ -1,11 +1,13 @@ import { configureStore } from '@reduxjs/toolkit'; import githubReducer from './features/github/github-slice'; +import toastsReducer from './features/toasts/toasts-slice'; import ensReducer from './features/ens/ens-slice'; export const store = configureStore({ reducer: { - github: githubReducer, ens: ensReducer, + github: githubReducer, + toasts: toastsReducer, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ diff --git a/ui/src/theme/index.ts b/ui/src/theme/index.ts index 8fe1080..bdbfceb 100644 --- a/ui/src/theme/index.ts +++ b/ui/src/theme/index.ts @@ -1,2 +1,3 @@ export * from './themes'; export * from './foundations'; +export * from './key-frames'; diff --git a/ui/src/theme/key-frames.ts b/ui/src/theme/key-frames.ts new file mode 100644 index 0000000..4c09aac --- /dev/null +++ b/ui/src/theme/key-frames.ts @@ -0,0 +1,22 @@ +import { dripStitches } from './themes'; + +const { keyframes } = dripStitches; + +export const KeyFrames = { + slideUpAndFade: keyframes({ + '0%': { opacity: 0, transform: 'translateY(2px)' }, + '100%': { opacity: 1, transform: 'translateY(0)' }, + }), + slideRightAndFade: keyframes({ + '0%': { opacity: 0, transform: 'translateX(-2px)' }, + '100%': { opacity: 1, transform: 'translateX(0)' }, + }), + slideDownAndFade: keyframes({ + '0%': { opacity: 0, transform: 'translateY(-2px)' }, + '100%': { opacity: 1, transform: 'translateY(0)' }, + }), + slideLeftAndFade: keyframes({ + '0%': { opacity: 0, transform: 'translateX(2px)' }, + '100%': { opacity: 1, transform: 'translateX(0)' }, + }), +}; diff --git a/ui/src/utils/index.ts b/ui/src/utils/index.ts index 670741c..aa68340 100644 --- a/ui/src/utils/index.ts +++ b/ui/src/utils/index.ts @@ -2,3 +2,4 @@ export * from './format'; export * from './validation'; export * from './object'; export * from './context'; +export * from './toast'; diff --git a/ui/src/utils/toast.ts b/ui/src/utils/toast.ts new file mode 100644 index 0000000..40d9986 --- /dev/null +++ b/ui/src/utils/toast.ts @@ -0,0 +1,10 @@ +import { store, toastsActions, ToastsState } from '@/store'; + +type PushToast = ( + type: ToastsState.Toast['type'], + message: ToastsState.Toast['message'], + extra?: Omit +) => void; + +export const pushToast: PushToast = (type, message, extra = {}) => + store.dispatch(toastsActions.push({ type, message, ...extra })); diff --git a/ui/src/views/components-test/combobox-test.tsx b/ui/src/views/components-test/combobox-test.tsx new file mode 100644 index 0000000..f381668 --- /dev/null +++ b/ui/src/views/components-test/combobox-test.tsx @@ -0,0 +1,50 @@ +import { Combobox, ComboboxItem, Flex } from '@/components'; +import { useState } from 'react'; + +const itemsCombobox = [ + { label: 'Item 1', value: 'item-1' }, + { label: 'Item 2', value: 'item-2' }, + { label: 'Item 3', value: 'item-3' }, +]; + +export const ComboboxTest = () => { + const [selectedValue, setSelectedValue] = useState({} as ComboboxItem); + const [selectedValueAutocomplete, setSelectedValueAutocomplete] = useState( + {} as ComboboxItem + ); + + const handleComboboxChange = (item: ComboboxItem) => { + setSelectedValue(item); + }; + + const handleComboboxChangeAutocomplete = (item: ComboboxItem) => { + setSelectedValueAutocomplete(item); + }; + + return ( + +

Components Test

+ + + + +
+ ); +}; diff --git a/ui/src/views/components-test/components-test.tsx b/ui/src/views/components-test/components-test.tsx index a3871e1..e703f82 100644 --- a/ui/src/views/components-test/components-test.tsx +++ b/ui/src/views/components-test/components-test.tsx @@ -1,50 +1,12 @@ -import { Combobox, ComboboxItem, Flex } from '@/components'; -import { useState } from 'react'; - -const itemsCombobox = [ - { label: 'Item 1', value: 'item-1' }, - { label: 'Item 2', value: 'item-2' }, - { label: 'Item 3', value: 'item-3' }, -]; +import { Flex } from '@/components'; +import { ComboboxTest } from './combobox-test'; +import { ToastTest } from './toast-test'; export const ComponentsTest = () => { - const [selectedValue, setSelectedValue] = useState({} as ComboboxItem); - const [selectedValueAutocomplete, setSelectedValueAutocomplete] = useState( - {} as ComboboxItem - ); - - const handleComboboxChange = (item: ComboboxItem) => { - setSelectedValue(item); - }; - - const handleComboboxChangeAutocomplete = (item: ComboboxItem) => { - setSelectedValueAutocomplete(item); - }; - return ( - -

Components Test

- - - - + + + ); }; diff --git a/ui/src/views/components-test/toast-test.tsx b/ui/src/views/components-test/toast-test.tsx new file mode 100644 index 0000000..1ba1316 --- /dev/null +++ b/ui/src/views/components-test/toast-test.tsx @@ -0,0 +1,24 @@ +import { Button, Flex } from '@/components'; +import { pushToast } from '@/utils'; + +export const ToastTest = () => { + return ( + +

ToastTest

+ + +
+ ); +}; diff --git a/ui/yarn.lock b/ui/yarn.lock index d17c95f..8173725 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -3710,6 +3710,13 @@ resolved "https://registry.yarnpkg.com/@radix-ui/colors/-/colors-0.1.8.tgz#b08c62536fc462a87632165fb28e9b18f9bd047e" integrity sha512-jwRMXYwC0hUo0mv6wGpuw254Pd9p/R6Td5xsRpOmaWkUHlooNWqVcadgyzlRumMq3xfOTXwJReU0Jv+EIy4Jbw== +"@radix-ui/primitive@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.0.tgz#e1d8ef30b10ea10e69c76e896f608d9276352253" + integrity sha512-3e7rn8FDMin4CgeL7Z/49smCA3rFYY3Ha2rUQ7HRWFadS5iCRw08ZgVT1LaNTCNqgvrUiyczLflrVrF0SRQtNA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-avatar@^1.0.1": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-avatar/-/react-avatar-1.0.2.tgz#c72209882e191db00ac0bfa16a9d9c025f0958f0" @@ -3721,6 +3728,17 @@ "@radix-ui/react-use-callback-ref" "1.0.0" "@radix-ui/react-use-layout-effect" "1.0.0" +"@radix-ui/react-collection@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.1.tgz#259506f97c6703b36291826768d3c1337edd1de5" + integrity sha512-uuiFbs+YCKjn3X1DTSx9G7BHApu4GHbi3kgiwsnFUbOKCrwejAJv4eE4Vc8C0Oaxt9T0aV4ox0WCOdx+39Xo+g== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-slot" "1.0.1" + "@radix-ui/react-compose-refs@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz#37595b1f16ec7f228d698590e78eeed18ff218ae" @@ -3735,6 +3753,43 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-dismissable-layer@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.2.tgz#f04d1061bddf00b1ca304148516b9ddc62e45fb2" + integrity sha512-WjJzMrTWROozDqLB0uRWYvj4UuXsM/2L19EmQ3Au+IJWqwvwq9Bwd+P8ivo0Deg9JDPArR1I6MbWNi1CmXsskg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-escape-keydown" "1.0.2" + +"@radix-ui/react-portal@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.1.tgz#169c5a50719c2bb0079cf4c91a27aa6d37e5dd33" + integrity sha512-NY2vUWI5WENgAT1nfC6JS7RU5xRYBfjZVLq0HmgEN1Ezy3rk/UruMV4+Rd0F40PEaFC5SrLS1ixYvcYIQrb4Ig== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.1" + +"@radix-ui/react-presence@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.0.tgz#814fe46df11f9a468808a6010e3f3ca7e0b2e84a" + integrity sha512-A+6XEvN01NfVWiKu38ybawfHsBjWum42MRPnEuqPsBZ4eV7e/7K321B5VgYMPv3Xx5An6o1/l9ZuDBgmcmWK3w== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.0.0" + +"@radix-ui/react-primitive@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.1.tgz#c1ebcce283dd2f02e4fbefdaa49d1cb13dbc990a" + integrity sha512-fHbmislWVkZaIdeF6GZxF0A/NH/3BjrGIYj+Ae6eTmTCr7EB0RQAAVEiqsXK6p3/JcRqVSBQoceZroj30Jj3XA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-slot" "1.0.1" + "@radix-ui/react-primitive@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.2.tgz#54e22f49ca59ba88d8143090276d50b93f8a7053" @@ -3751,6 +3806,25 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-compose-refs" "1.0.0" +"@radix-ui/react-toast@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-toast/-/react-toast-1.1.2.tgz#53872fbf20c6515040bac54fc0660dbfe983ab90" + integrity sha512-Kpr4BBYoP0O5A1UeDBmao87UnCMNdAKGNioQH5JzEm6OYTUVGhuDRbOwoZxPwOZ6vsjJHeIpdUrwbiHEB65CCw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-collection" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-dismissable-layer" "1.0.2" + "@radix-ui/react-portal" "1.0.1" + "@radix-ui/react-presence" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-controllable-state" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.0.0" + "@radix-ui/react-visually-hidden" "1.0.1" + "@radix-ui/react-use-callback-ref@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.0.tgz#9e7b8b6b4946fe3cbe8f748c82a2cce54e7b6a90" @@ -3758,6 +3832,22 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-controllable-state@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.0.tgz#a64deaafbbc52d5d407afaa22d493d687c538b7f" + integrity sha512-FohDoZvk3mEXh9AWAVyRTYR4Sq7/gavuofglmiXB2g1aKyboUD4YtgWxKj8O5n+Uak52gXQ4wKz5IFST4vtJHg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-callback-ref" "1.0.0" + +"@radix-ui/react-use-escape-keydown@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.2.tgz#09ab6455ab240b4f0a61faf06d4e5132c4d639f6" + integrity sha512-DXGim3x74WgUv+iMNCF+cAo8xUHHeqvjx8zs7trKf+FkQKPQXLk2sX7Gx1ysH7Q76xCpZuxIJE7HLPxRE+Q+GA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-layout-effect@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.0.tgz#2fc19e97223a81de64cd3ba1dc42ceffd82374dc" @@ -3765,6 +3855,14 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-visually-hidden@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.1.tgz#9a4ac4fc97ae8d72a10e727f16b3121b5f0aa469" + integrity sha512-K1hJcCMfWfiYUibRqf3V8r5Drpyf7rh44jnrwAbdvI5iCCijilBBeyQv9SKidYNZIopMdCyR9FnIjkHxHN0FcQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.1" + "@react-icons/all-files@^4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@react-icons/all-files/-/all-files-4.1.0.tgz#477284873a0821928224b6fc84c62d2534d6650b"