work-in-progress atproto PDS
typescript atproto pds atcute

feat: accordion components

mary.my.id 5481d484 2b86afc1

verified
+150
+86
packages/danaus/src/web/primitives/accordion-header.tsx
··· 1 + import { cva } from 'cva'; 2 + import type { Child } from 'hono/jsx'; 3 + 4 + import ChevronDownSmallOutlined from '../icons/central/chevron-down-small-outlined.tsx'; 5 + 6 + const root = cva({ 7 + base: [ 8 + 'flex w-full cursor-pointer list-none items-center', 9 + 'm-0 rounded-md border-0', 10 + 'bg-transparent text-neutral-foreground-1', 11 + 'outline-2 -outline-offset-2 outline-transparent', 12 + 'focus-visible:outline-stroke-focus-2', 13 + // hide default marker 14 + '[&::-webkit-details-marker]:hidden', 15 + ], 16 + variants: { 17 + size: { 18 + small: 'min-h-8 text-base-200', 19 + medium: 'min-h-11 text-base-300', 20 + large: 'min-h-11 text-base-400', 21 + 'extra-large': 'min-h-11 text-base-500', 22 + }, 23 + expandIconPosition: { 24 + // padding: 0 12px 0 10px 25 + start: 'pr-3 pl-2.5', 26 + // padding: 0 10px 0 12px (reversed) 27 + end: 'pr-2.5 pl-3', 28 + }, 29 + }, 30 + defaultVariants: { 31 + size: 'medium', 32 + expandIconPosition: 'start', 33 + }, 34 + }); 35 + 36 + const expandIconStyle = cva({ 37 + base: ['flex shrink-0 items-center', 'text-base-500 leading-base-500'], 38 + variants: { 39 + position: { 40 + start: 'pr-2', 41 + end: 'grow shrink basis-0 justify-end pl-2', 42 + }, 43 + }, 44 + }); 45 + 46 + const iconStyle = cva({ 47 + base: 'flex shrink-0 items-center pr-2 text-base-500 leading-base-500', 48 + }); 49 + 50 + export interface AccordionHeaderProps { 51 + size?: 'small' | 'medium' | 'large' | 'extra-large'; 52 + expandIconPosition?: 'start' | 'end'; 53 + /** slot for custom icon before the text */ 54 + icon?: Child; 55 + class?: string; 56 + children?: Child; 57 + } 58 + 59 + /** 60 + * accordion header component using native `<summary>` element 61 + */ 62 + const AccordionHeader = (props: AccordionHeaderProps) => { 63 + const { size = 'medium', expandIconPosition = 'start', icon, class: className, children } = props; 64 + 65 + return ( 66 + <summary class={root({ size, expandIconPosition, className })}> 67 + {expandIconPosition === 'start' && ( 68 + <span class={expandIconStyle({ position: 'start' })}> 69 + <ChevronDownSmallOutlined size={20} /> 70 + </span> 71 + )} 72 + 73 + {icon && <span class={iconStyle()}>{icon}</span>} 74 + 75 + {children} 76 + 77 + {expandIconPosition === 'end' && ( 78 + <span class={expandIconStyle({ position: 'end' })}> 79 + <ChevronDownSmallOutlined size={20} /> 80 + </span> 81 + )} 82 + </summary> 83 + ); 84 + }; 85 + 86 + export default AccordionHeader;
+25
packages/danaus/src/web/primitives/accordion-item.tsx
··· 1 + import type { Child } from 'hono/jsx'; 2 + 3 + export interface AccordionItemProps { 4 + /** whether the accordion item is open by default */ 5 + open?: boolean; 6 + /** group name for exclusive accordion behavior (only one open at a time) */ 7 + name?: string; 8 + class?: string; 9 + children?: Child; 10 + } 11 + 12 + /** 13 + * accordion item component using native `<details>` element 14 + */ 15 + const AccordionItem = (props: AccordionItemProps) => { 16 + const { open = false, name, class: className, children } = props; 17 + 18 + return ( 19 + <details open={open} name={name} class={`group/accordion-item${className ? ` ${className}` : ''}`}> 20 + {children} 21 + </details> 22 + ); 23 + }; 24 + 25 + export default AccordionItem;
+22
packages/danaus/src/web/primitives/accordion-panel.tsx
··· 1 + import { cva } from 'cva'; 2 + import type { Child } from 'hono/jsx'; 3 + 4 + const root = cva({ 5 + base: 'px-3 pb-3', 6 + }); 7 + 8 + export interface AccordionPanelProps { 9 + class?: string; 10 + children?: Child; 11 + } 12 + 13 + /** 14 + * accordion panel component for content within accordion item 15 + */ 16 + const AccordionPanel = (props: AccordionPanelProps) => { 17 + const { class: className, children } = props; 18 + 19 + return <div class={root({ className })}>{children}</div>; 20 + }; 21 + 22 + export default AccordionPanel;
+17
packages/danaus/src/web/primitives/accordion.tsx
··· 1 + import type { Child } from 'hono/jsx'; 2 + 3 + export interface AccordionProps { 4 + class?: string; 5 + children?: Child; 6 + } 7 + 8 + /** 9 + * accordion container component 10 + */ 11 + const Accordion = (props: AccordionProps) => { 12 + const { class: className, children } = props; 13 + 14 + return <div class={className}>{children}</div>; 15 + }; 16 + 17 + export default Accordion;