-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
211 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
.card-stack-content { | ||
transition: max-height 0.3s ease-in-out !important; | ||
} | ||
|
||
.card-stack-content[data-state="closed"] { | ||
max-height: 6px; | ||
} | ||
|
||
.card-stack-content[data-state="open"] { | ||
max-height: var(--radix-accordion-content-height); | ||
} | ||
|
||
.card-stack-plate { | ||
transition: max-width 0.3s ease-in-out; | ||
} | ||
|
||
.card-stack-content[data-state="closed"] .card-stack-plate { | ||
max-width: calc(100% - 8px); | ||
} | ||
|
||
.card-stack-content[data-state="open"] .card-stack-plate { | ||
max-width: 100%; | ||
} | ||
|
||
.card-stack-content[data-state="closed"] .card-stack-section { | ||
transition: visibility; | ||
transition-delay: 0.3s; | ||
visibility: hidden; | ||
} | ||
|
||
.card-stack-content[data-state="open"] .card-stack-section { | ||
visibility: visible; | ||
} |
68 changes: 68 additions & 0 deletions
68
src/renderer/shared/ui-kit/CardStack/CardStack.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { type Meta, type StoryObj } from '@storybook/react'; | ||
|
||
import { Box } from '../Box/Box'; | ||
|
||
import { CardStack } from './CardStack'; | ||
|
||
const meta: Meta<typeof CardStack> = { | ||
component: CardStack, | ||
title: 'Design System/kit/CardStack', | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof CardStack>; | ||
|
||
export const Default: Story = { | ||
render(args) { | ||
return ( | ||
<div className="flex h-[450px] w-full justify-center bg-gray-100 pt-2"> | ||
<Box width="600px"> | ||
<CardStack {...args}> | ||
<CardStack.Trigger>Hello, open me, please</CardStack.Trigger> | ||
<CardStack.Content> | ||
<ul className="flex flex-col gap-y-4"> | ||
{Array.from({ length: 7 }).map((_, index) => ( | ||
<li key={index} className="flex justify-between rounded p-2"> | ||
<span>My text</span> | ||
<button type="button" className="rounded-md bg-gray-100 p-1"> | ||
Click me | ||
</button> | ||
</li> | ||
))} | ||
</ul> | ||
</CardStack.Content> | ||
</CardStack> | ||
</Box> | ||
</div> | ||
); | ||
}, | ||
}; | ||
|
||
export const StickyTrigger: Story = { | ||
render(args) { | ||
return ( | ||
<div className="flex h-[200px] w-full justify-center overflow-auto"> | ||
<Box width="300px"> | ||
<CardStack {...args}> | ||
<CardStack.Trigger sticky>Hello, I'm sticky button</CardStack.Trigger> | ||
<CardStack.Content> | ||
<ul className="flex flex-col gap-y-4 bg-green-100"> | ||
<ul className="flex flex-col gap-y-4"> | ||
{Array.from({ length: 7 }).map((_, index) => ( | ||
<li key={index} className="flex justify-between rounded p-2"> | ||
<span>My text</span> | ||
<button type="button" className="rounded-md bg-gray-100 p-1"> | ||
Click me | ||
</button> | ||
</li> | ||
))} | ||
</ul> | ||
</ul> | ||
</CardStack.Content> | ||
</CardStack> | ||
</Box> | ||
</div> | ||
); | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import * as RadixAccordion from '@radix-ui/react-accordion'; | ||
import { type PropsWithChildren, createContext, useId, useLayoutEffect, useMemo, useRef, useState } from 'react'; | ||
|
||
import { cnTw } from '@/shared/lib/utils'; | ||
import { Icon } from '@/shared/ui'; | ||
|
||
import './CardStack.css'; | ||
|
||
const Context = createContext<{ open: boolean }>({ open: false }); | ||
|
||
type RootProps = PropsWithChildren<{ | ||
initialOpen?: boolean; | ||
}>; | ||
|
||
const Root = ({ initialOpen = false, children }: RootProps) => { | ||
const id = useId(); | ||
const [open, setOpen] = useState(initialOpen); | ||
|
||
const ctx = useMemo(() => ({ open }), [open]); | ||
|
||
return ( | ||
<Context.Provider value={ctx}> | ||
<RadixAccordion.Root | ||
collapsible | ||
type="single" | ||
value={open ? id : ''} | ||
onValueChange={(value) => setOpen(value === id)} | ||
> | ||
<RadixAccordion.Item value={id}>{children}</RadixAccordion.Item> | ||
</RadixAccordion.Root> | ||
</Context.Provider> | ||
); | ||
}; | ||
|
||
type TriggerProps = PropsWithChildren<{ | ||
sticky?: boolean; | ||
}>; | ||
|
||
const Trigger = ({ sticky, children }: TriggerProps) => { | ||
return ( | ||
<RadixAccordion.Header asChild> | ||
<div className={cnTw('relative z-10 block w-full', sticky && 'sticky top-0 z-10')}> | ||
<RadixAccordion.Trigger | ||
className={cnTw( | ||
'group flex w-full items-center gap-x-2 bg-row-background px-3 py-1', | ||
'shadow-stack hover:shadow-stack-hover focus:shadow-stack-hover data-[state=open]:shadow-none', | ||
'transition-all duration-300 data-[state=closed]:rounded-md data-[state=open]:rounded-t-md', | ||
)} | ||
> | ||
<Icon | ||
className={cnTw( | ||
'transition-all duration-100 group-data-[state=open]:rotate-90', | ||
'shrink-0 text-icon-default group-hover:text-icon-hover group-focus:text-icon-hover', | ||
)} | ||
name="shelfRight" | ||
size={16} | ||
/> | ||
<div className="flex min-w-0 grow">{children}</div> | ||
</RadixAccordion.Trigger> | ||
</div> | ||
</RadixAccordion.Header> | ||
); | ||
}; | ||
|
||
const Content = ({ children }: PropsWithChildren) => { | ||
const ref = useRef<HTMLDivElement>(null); | ||
const contentRef = useRef<HTMLDivElement>(null); | ||
|
||
useLayoutEffect(() => { | ||
if (!ref.current || !contentRef.current) return; | ||
|
||
const resizeObserver = new ResizeObserver(() => { | ||
const { clientHeight } = ref.current!; | ||
|
||
contentRef.current!.style.cssText = `--radix-accordion-content-height: ${clientHeight}px;`; | ||
}); | ||
|
||
resizeObserver.observe(ref.current); | ||
|
||
return () => { | ||
resizeObserver.disconnect(); | ||
}; | ||
}, []); | ||
|
||
return ( | ||
<RadixAccordion.Content forceMount ref={contentRef} className="card-stack-content group relative overflow-hidden"> | ||
<div | ||
className={cnTw( | ||
'card-stack-plate absolute left-1/2 top-0 h-full w-full -translate-x-1/2 rounded-b-md bg-white shadow-stack', | ||
'group-data-[state=open]:border-t group-data-[state=open]:border-divider group-data-[state=open]:shadow-none', | ||
)} | ||
/> | ||
<section ref={ref} className="card-stack-section relative"> | ||
{children} | ||
</section> | ||
</RadixAccordion.Content> | ||
); | ||
}; | ||
|
||
export const CardStack = Object.assign(Root, { | ||
Trigger, | ||
Content, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters