Files
dydx-v4-web/src/components/Collapsible.tsx
T
Jared VuandBill He 99e708a984 Notifications Refresh (#135)
* Remove X button from tablet/mobile Notification menu

* Toast styling

* missed in merge

* .env.example

* Update abacus@1.0.9

* Add notif strings, and abaucs notif state

* Update Notification hooks, add Notification Preference controls

* Consolidate Notification into single component

* withLabel -> withTrigger prop

* nits

* OrderStatusChanged -> AbacusGenerated

* Notification OnClick

* Move Notification -> Components

* withAnimation -> $withAnimation

* Notification styling and click handle

* load state, onClick, localStorage

* add error count

* Rez localStorage Notifications

* Update TransferStatus UI

* Use Notification component for other abacusNotifs

* fix uselocalnotif query

* Default to Notification from NotificationMenu

---------

Co-authored-by: Bill He <bill@dydx.exchange>
2023-11-10 20:55:34 -08:00

143 lines
3.3 KiB
TypeScript

import styled, { css, keyframes, type AnyStyledComponent } from 'styled-components';
import { Root, Trigger, Content } from '@radix-ui/react-collapsible';
import { popoverMixins } from '@/styles/popoverMixins';
import { HorizontalSeparatorFiller } from '@/components/Separator';
import { Icon, IconName } from '@/components/Icon';
type ElementProps = {
defaultOpen?: boolean;
disabled?: boolean;
open?: boolean;
onOpenChange?: (open: boolean) => void;
label: React.ReactNode;
triggerIcon?: IconName;
children: React.ReactNode;
withTrigger?: boolean;
};
type StyleProps = {
className?: string;
transitionDuration?: number;
triggerIconSide?: 'left' | 'right';
fullWidth?: boolean;
};
export type CollapsibleProps = ElementProps & StyleProps;
export const Collapsible = ({
defaultOpen = false,
disabled,
open,
onOpenChange,
label,
children,
transitionDuration,
triggerIcon = IconName.Caret,
triggerIconSide = 'left',
fullWidth,
className,
withTrigger = true,
}: CollapsibleProps) => (
<Styled.Root defaultOpen={defaultOpen} open={open} onOpenChange={onOpenChange}>
{withTrigger && (
<Styled.Trigger className={className} disabled={disabled}>
{triggerIconSide === 'right' && (
<>
{label}
{fullWidth && <HorizontalSeparatorFiller />}
</>
)}
<Styled.TriggerIcon>
<Icon iconName={triggerIcon} />
</Styled.TriggerIcon>
{triggerIconSide === 'left' && (
<>
{fullWidth && <HorizontalSeparatorFiller />}
{label}
</>
)}
</Styled.Trigger>
)}
<Styled.Content $transitionDuration={transitionDuration}>{children}</Styled.Content>
</Styled.Root>
);
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Root = styled(Root)`
display: grid;
&[data-state='open'] {
gap: 0.75rem;
}
`;
Styled.Trigger = styled(Trigger)`
${popoverMixins.trigger}
--trigger-textColor: inherit;
--trigger-icon-width: 0.75em;
--trigger-icon-color: inherit;
`;
Styled.TriggerIcon = styled.span`
width: var(--trigger-icon-width);
display: inline-flex;
transition: rotate 0.3s var(--ease-out-expo);
color: var(--trigger-icon-color);
${Styled.Trigger}[data-state='open'] & {
rotate: -0.5turn;
}
`;
Styled.Content = styled(Content)<{ $transitionDuration: number }>`
display: grid;
--transition-duration: 0.25s;
${({ $transitionDuration }) =>
$transitionDuration &&
css`
--transition-duration: ${$transitionDuration}s;
`}
@media (prefers-reduced-motion: no-preference) {
&[data-state='open'] {
animation: ${keyframes`
from {
overflow: hidden;
max-height: 0;
opacity: 0;
scale: 0.8;
filter: blur(2px);
}
to {
overflow: hidden;
max-height: var(--radix-collapsible-content-height);
}
`} var(--transition-duration) var(--ease-out-expo);
}
&[data-state='closed'] {
animation: ${keyframes`
from {
overflow: hidden;
max-height: var(--radix-collapsible-content-height);
}
to {
overflow: hidden;
max-height: 0;
opacity: 0;
scale: 0.8;
filter: blur(2px);
}
`} var(--transition-duration) var(--ease-out-expo);
}
}
`;