@stasho/ds 0.9.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stasho/ds",
3
- "version": "0.9.2",
3
+ "version": "0.11.0",
4
4
  "description": "stasho design system",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -22,6 +22,7 @@
22
22
  "directory": "packages/ds"
23
23
  },
24
24
  "exports": {
25
+ "./accordion": "./src/components/accordion/accordion.tsx",
25
26
  "./alert": "./src/components/alert/alert.tsx",
26
27
  "./button": "./src/components/button/button.tsx",
27
28
  "./icon-button": "./src/components/button/icon-button.tsx",
@@ -0,0 +1,85 @@
1
+ "use client";
2
+
3
+ import { forwardRef, type ComponentPropsWithoutRef } from "react";
4
+ import { Accordion as AccordionPrimitive } from "radix-ui";
5
+ import { CaretDown } from "@phosphor-icons/react";
6
+ import { cn } from "@ac/lib/cn";
7
+
8
+ const Accordion = AccordionPrimitive.Root;
9
+
10
+ const AccordionItem = forwardRef<
11
+ HTMLDivElement,
12
+ ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
13
+ >(({ className, ...rest }, ref) => (
14
+ <AccordionPrimitive.Item
15
+ ref={ref}
16
+ className={cn("border-b border-edge", className)}
17
+ {...rest}
18
+ />
19
+ ));
20
+ AccordionItem.displayName = "AccordionItem";
21
+
22
+ const AccordionTrigger = forwardRef<
23
+ HTMLButtonElement,
24
+ ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
25
+ >(({ className, children, ...rest }, ref) => (
26
+ <AccordionPrimitive.Header className="flex">
27
+ <AccordionPrimitive.Trigger
28
+ ref={ref}
29
+ className={cn(
30
+ "group flex flex-1 items-center justify-between gap-4 py-4",
31
+ "text-left font-sans font-semibold text-foreground",
32
+ "transition-colors duration-200",
33
+ "hover:text-accent-500 dark:hover:text-accent",
34
+ "focus-visible:outline-2 focus-visible:outline-accent-500 dark:focus-visible:outline-accent focus-visible:outline-offset-2",
35
+ "motion-reduce:transition-none",
36
+ className,
37
+ )}
38
+ {...rest}
39
+ >
40
+ {children}
41
+ <CaretDown
42
+ weight="bold"
43
+ aria-hidden="true"
44
+ className={cn(
45
+ "size-4 shrink-0 text-accent-500 dark:text-accent",
46
+ "transition-transform duration-200",
47
+ "group-data-[state=open]:rotate-180",
48
+ "group-data-[state=closed]:group-hover:translate-y-[3px]",
49
+ "motion-reduce:transition-none",
50
+ )}
51
+ />
52
+ </AccordionPrimitive.Trigger>
53
+ </AccordionPrimitive.Header>
54
+ ));
55
+ AccordionTrigger.displayName = "AccordionTrigger";
56
+
57
+ const AccordionContent = forwardRef<
58
+ HTMLDivElement,
59
+ ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
60
+ >(({ className, children, ...rest }, ref) => (
61
+ <AccordionPrimitive.Content
62
+ ref={ref}
63
+ className={cn(
64
+ "group overflow-hidden",
65
+ "motion-safe:data-[state=open]:animate-accordion-down",
66
+ "motion-safe:data-[state=closed]:animate-accordion-up",
67
+ )}
68
+ {...rest}
69
+ >
70
+ <div
71
+ className={cn(
72
+ "pb-4 text-sm leading-relaxed text-muted-foreground",
73
+ "opacity-0 -translate-y-1 transition-[opacity,transform] duration-200 ease-out",
74
+ "group-data-[state=open]:opacity-100 group-data-[state=open]:translate-y-0",
75
+ "motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0",
76
+ className,
77
+ )}
78
+ >
79
+ {children}
80
+ </div>
81
+ </AccordionPrimitive.Content>
82
+ ));
83
+ AccordionContent.displayName = "AccordionContent";
84
+
85
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
@@ -375,4 +375,27 @@
375
375
  animation: none;
376
376
  opacity: 1;
377
377
  }
378
+ }
379
+
380
+ /* ── Accordion open/close (height) ───────────── */
381
+
382
+ /* Registered as real Tailwind utilities so the `data-[state=...]:` variant can
383
+ compose (a plain `.animate-accordion-*` CSS class can't carry a Tailwind
384
+ variant). Applied in the component as `motion-safe:data-[state=open]:…` — the
385
+ `data-[state]` attribute selector out-specifies `motion-reduce:animate-none`,
386
+ so reduced motion is honored by gating the animation INTO motion-safe rather
387
+ than disabling it OUT, which sidesteps the specificity conflict entirely. */
388
+ @theme {
389
+ --animate-accordion-down: accordion-down 200ms ease-out;
390
+ --animate-accordion-up: accordion-up 200ms ease-out;
391
+ }
392
+
393
+ @keyframes accordion-down {
394
+ from { height: 0; }
395
+ to { height: var(--radix-accordion-content-height); }
396
+ }
397
+
398
+ @keyframes accordion-up {
399
+ from { height: var(--radix-accordion-content-height); }
400
+ to { height: 0; }
378
401
  }