feat: UI toast component (#160)

* chore: install radix toast

* feat: add toast component

* chore: display toast column

* chore: remove commented lines

* chore: fix animation
This commit is contained in:
Camila Sosa Morales 2023-03-10 09:04:30 -05:00 committed by GitHub
parent e28c7c6e96
commit 13a9a1e992
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 465 additions and 47 deletions

View File

@ -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",

View File

@ -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 */}
<ConnectKitButton />
</div>
<ToastProvider />
<HashRouter>
<Routes>
<Route path="/home" element={<Home />} />

View File

@ -29,7 +29,7 @@ export interface IconButtonProps extends BaseButtonProps {
'aria-label': string;
}
export const IconButton = forwardRef<IconButtonProps, 'button'>(
export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
function IconButton(props, ref) {
const {
icon,

View File

@ -0,0 +1,15 @@
import { IconStyles as IS } from '../icon.styles';
export const ErrorIcon: React.FC<IS.CustomProps> = (props) => (
<IS.Custom
{...props}
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10 0.25C4.62391 0.25 0.25 4.62391 0.25 10C0.25 15.3761 4.62391 19.75 10 19.75C15.3761 19.75 19.75 15.3761 19.75 10C19.75 4.62391 15.3761 0.25 10 0.25ZM10 15.2458C9.81458 15.2458 9.63332 15.1908 9.47915 15.0878C9.32498 14.9848 9.20482 14.8384 9.13386 14.667C9.06291 14.4957 9.04434 14.3072 9.08051 14.1254C9.11669 13.9435 9.20598 13.7765 9.33709 13.6454C9.4682 13.5143 9.63525 13.425 9.8171 13.3888C9.99896 13.3526 10.1875 13.3712 10.3588 13.4421C10.5301 13.5131 10.6765 13.6333 10.7795 13.7874C10.8825 13.9416 10.9375 14.1229 10.9375 14.3083C10.9375 14.5569 10.8387 14.7954 10.6629 14.9712C10.4871 15.147 10.2486 15.2458 10 15.2458ZM11.0181 5.81687L10.7491 11.5356C10.7491 11.7345 10.67 11.9253 10.5294 12.066C10.3887 12.2066 10.198 12.2856 9.99906 12.2856C9.80015 12.2856 9.60938 12.2066 9.46873 12.066C9.32808 11.9253 9.24906 11.7345 9.24906 11.5356L8.98 5.81969V5.81734C8.9741 5.67997 8.99607 5.54282 9.04458 5.41415C9.09308 5.28549 9.16713 5.16797 9.26225 5.06868C9.35737 4.96938 9.47161 4.89037 9.59807 4.83639C9.72454 4.78241 9.86062 4.75458 9.99813 4.75458C10.1356 4.75458 10.2717 4.78241 10.3982 4.83639C10.5246 4.89037 10.6389 4.96938 10.734 5.06868C10.8291 5.16797 10.9032 5.28549 10.9517 5.41415C11.0002 5.54282 11.0221 5.67997 11.0162 5.81734L11.0181 5.81687Z"
fill="currentColor"
/>
</IS.Custom>
);

View File

@ -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,
});

View File

@ -3,3 +3,4 @@ export * from './layout';
export * from './form';
export * from './card';
export * from './spinner';
export * from './toast';

View File

@ -0,0 +1 @@
export * from './toast';

View File

@ -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, {});
}

View File

@ -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<ToastProps> = ({
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 (
<ToastStyles.Root
open={open}
duration={duration}
variant={type}
onOpenChange={handleOpenChange}
>
<ToastStyles.Layout>
<ToastStyles.Content>
<ToastStyles.Icon name={type} />
<ToastStyles.Body>{message}</ToastStyles.Body>
</ToastStyles.Content>
<ToastStyles.Close asChild>
<ToastStyles.CloseButton
aria-label="close"
colorScheme={type}
variant="link"
icon={<Icon name="close" />}
onClick={onDismiss}
/>
</ToastStyles.Close>
</ToastStyles.Layout>
</ToastStyles.Root>
);
};
export const ToastProvider: React.FC = () => {
const { toasts } = useToastsState();
return (
<ToastStyles.Provider duration={3000} swipeDirection="down">
{toasts.map((toast) => (
<Toast key={toast.id} {...toast} />
))}
<ToastStyles.Viewport />
</ToastStyles.Provider>
);
};

View File

@ -1,2 +1,3 @@
export * from './github';
export * from './ens';
export * from './github';
export * from './toasts';

View File

@ -0,0 +1 @@
export * from './toasts-slice';

View File

@ -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<Omit<ToastsState.Toast, 'id'>>) => {
state.toasts = [...state.toasts, { ...action.payload, id: Date.now() }];
},
dismiss: (state, action: PayloadAction<number>) => {
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;

View File

@ -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({

View File

@ -1,2 +1,3 @@
export * from './themes';
export * from './foundations';
export * from './key-frames';

View File

@ -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)' },
}),
};

View File

@ -2,3 +2,4 @@ export * from './format';
export * from './validation';
export * from './object';
export * from './context';
export * from './toast';

10
ui/src/utils/toast.ts Normal file
View File

@ -0,0 +1,10 @@
import { store, toastsActions, ToastsState } from '@/store';
type PushToast = (
type: ToastsState.Toast['type'],
message: ToastsState.Toast['message'],
extra?: Omit<ToastsState.Toast, 'id' | 'type' | 'message' | 'children'>
) => void;
export const pushToast: PushToast = (type, message, extra = {}) =>
store.dispatch(toastsActions.push({ type, message, ...extra }));

View File

@ -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 (
<Flex
css={{
flexDirection: 'column',
margin: '100px',
justifyContent: 'center',
gap: '10px',
}}
>
<h1>Components Test</h1>
<Flex css={{ width: '400px', gap: '$2' }}>
<Combobox
items={itemsCombobox}
selectedValue={selectedValue}
onChange={handleComboboxChange}
/>
<Combobox
items={itemsCombobox}
selectedValue={selectedValueAutocomplete}
onChange={handleComboboxChangeAutocomplete}
withAutocomplete
/>
</Flex>
</Flex>
);
};

View File

@ -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 (
<Flex
css={{
flexDirection: 'column',
margin: '100px',
justifyContent: 'center',
gap: '10px',
}}
>
<h1>Components Test</h1>
<Flex css={{ width: '400px', gap: '$2' }}>
<Combobox
items={itemsCombobox}
selectedValue={selectedValue}
onChange={handleComboboxChange}
/>
<Combobox
items={itemsCombobox}
selectedValue={selectedValueAutocomplete}
onChange={handleComboboxChangeAutocomplete}
withAutocomplete
/>
</Flex>
<Flex css={{ flexDirection: 'column' }}>
<ToastTest />
<ComboboxTest />
</Flex>
);
};

View File

@ -0,0 +1,24 @@
import { Button, Flex } from '@/components';
import { pushToast } from '@/utils';
export const ToastTest = () => {
return (
<Flex css={{ margin: '$22', gap: '$5' }}>
<h1>ToastTest</h1>
<Button
onClick={() => {
pushToast('error', 'Issue connecting Wallet, please try again.');
}}
>
Toggle Error Toast
</Button>
<Button
onClick={() => {
pushToast('success', 'Message sent successfully!');
}}
>
Toggle Succes Toast
</Button>
</Flex>
);
};

View File

@ -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"