@nationaldesignstudio/react 0.0.17 → 0.1.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.
Files changed (41) hide show
  1. package/dist/component-registry.md +181 -29
  2. package/dist/components/atoms/accordion/accordion.d.ts +2 -2
  3. package/dist/components/atoms/background/background.d.ts +158 -0
  4. package/dist/components/atoms/button/button.d.ts +64 -82
  5. package/dist/components/atoms/button/icon-button.d.ts +128 -66
  6. package/dist/components/organisms/card/card.d.ts +130 -4
  7. package/dist/components/organisms/us-gov-banner/us-gov-banner.d.ts +120 -2
  8. package/dist/components/sections/hero/hero.d.ts +166 -150
  9. package/dist/components/sections/quote-block/quote-block.d.ts +152 -0
  10. package/dist/index.d.ts +6 -2
  11. package/dist/index.js +4068 -6052
  12. package/dist/index.js.map +1 -1
  13. package/dist/lib/utils.d.ts +1 -2
  14. package/dist/tokens.css +207 -16
  15. package/package.json +2 -4
  16. package/src/components/atoms/accordion/accordion.test.tsx +233 -0
  17. package/src/components/atoms/accordion/accordion.tsx +8 -8
  18. package/src/components/atoms/background/background.test.tsx +213 -0
  19. package/src/components/atoms/background/background.tsx +435 -0
  20. package/src/components/atoms/background/index.ts +22 -0
  21. package/src/components/atoms/button/button.stories.tsx +81 -32
  22. package/src/components/atoms/button/button.tsx +101 -49
  23. package/src/components/atoms/button/icon-button.stories.tsx +179 -28
  24. package/src/components/atoms/button/icon-button.test.tsx +254 -0
  25. package/src/components/atoms/button/icon-button.tsx +178 -59
  26. package/src/components/atoms/pager-control/pager-control.tsx +32 -3
  27. package/src/components/dev-tools/dev-toolbar/dev-toolbar.tsx +2 -0
  28. package/src/components/organisms/card/card.tsx +82 -24
  29. package/src/components/organisms/card/index.ts +7 -0
  30. package/src/components/organisms/navbar/navbar.tsx +2 -0
  31. package/src/components/organisms/us-gov-banner/index.ts +5 -1
  32. package/src/components/organisms/us-gov-banner/us-gov-banner.tsx +72 -16
  33. package/src/components/sections/hero/hero.stories.tsx +124 -1
  34. package/src/components/sections/hero/hero.test.tsx +21 -18
  35. package/src/components/sections/hero/hero.tsx +188 -301
  36. package/src/components/sections/hero/index.ts +13 -0
  37. package/src/components/sections/quote-block/index.ts +5 -0
  38. package/src/components/sections/quote-block/quote-block.tsx +216 -0
  39. package/src/index.ts +40 -0
  40. package/src/lib/utils.ts +1 -6
  41. package/src/stories/ThemeProvider.stories.tsx +11 -5
@@ -1,2 +1 @@
1
- import { ClassValue } from 'clsx';
2
- export declare function cn(...inputs: ClassValue[]): string;
1
+ export { cnBase as cn } from 'tailwind-variants';
package/dist/tokens.css CHANGED
@@ -294,7 +294,12 @@
294
294
  --color-yellow-v200: color(srgb 1 1 0.3294);
295
295
  --color-yellow-v300: color(srgb 0.9882 0.9216 0.3059);
296
296
  --color-yellow-v400: color(srgb 0.9765 0.8431 0.2863);
297
+ --font-cormorant: Cormorant, serif;
298
+ --font-gloock: Gloock, serif;
297
299
  --font-pp-neue-montreal: "PP Neue Montreal";
300
+ --font-sans: "PP Neue Montreal";
301
+ --font-serif-alt: Cormorant, serif;
302
+ --font-serif: Gloock, serif;
298
303
  --font-weight-medium: 500;
299
304
  --font-weight-regular: 400;
300
305
  --font-weight-semibold: 600;
@@ -601,6 +606,18 @@
601
606
  --spatial-grid-small-columns: 4;
602
607
  --spatial-grid-small-gutter: 12px;
603
608
  --spatial-grid-small-margin: 24px;
609
+ --spatial-layout-medium-large-span: 8;
610
+ --spatial-layout-medium-large-start: 3;
611
+ --spatial-layout-medium-medium-span: 10;
612
+ --spatial-layout-medium-medium-start: 2;
613
+ --spatial-layout-narrow-large-span: 8;
614
+ --spatial-layout-narrow-large-start: 3;
615
+ --spatial-layout-narrow-medium-span: 8;
616
+ --spatial-layout-narrow-medium-start: 3;
617
+ --spatial-layout-wide-large-span: 10;
618
+ --spatial-layout-wide-large-start: 2;
619
+ --spatial-layout-wide-medium-span: 12;
620
+ --spatial-layout-wide-medium-start: 1;
604
621
  --spatial-section-large-gap: 64px;
605
622
  --spatial-section-large-padding: 128px;
606
623
  --spatial-section-medium-gap: 56px;
@@ -957,7 +974,12 @@
957
974
  --color-yellow-v200: var(--color-yellow-v200);
958
975
  --color-yellow-v300: var(--color-yellow-v300);
959
976
  --color-yellow-v400: var(--color-yellow-v400);
977
+ --font-cormorant: var(--font-cormorant);
978
+ --font-gloock: var(--font-gloock);
960
979
  --font-pp-neue-montreal: var(--font-pp-neue-montreal);
980
+ --font-sans: var(--font-sans);
981
+ --font-serif-alt: var(--font-serif-alt);
982
+ --font-serif: var(--font-serif);
961
983
  --font-weight-medium: var(--font-weight-medium);
962
984
  --font-weight-regular: var(--font-weight-regular);
963
985
  --font-weight-semibold: var(--font-weight-semibold);
@@ -995,6 +1017,9 @@
995
1017
  --leading-88: var(--leading-88);
996
1018
  --leading-96: var(--leading-96);
997
1019
  --leading-9: var(--leading-9);
1020
+ --max-width-desktop: 1440px;
1021
+ --max-width-mobile: 320px;
1022
+ --max-width-tablet: 768px;
998
1023
  --radius-0: var(--radius-0);
999
1024
  --radius-10: var(--radius-10);
1000
1025
  --radius-12: var(--radius-12);
@@ -1264,6 +1289,18 @@
1264
1289
  --spatial-grid-small-columns: var(--spatial-grid-small-columns);
1265
1290
  --spatial-grid-small-gutter: var(--spatial-grid-small-gutter);
1266
1291
  --spatial-grid-small-margin: var(--spatial-grid-small-margin);
1292
+ --spatial-layout-medium-large-span: var(--spatial-layout-medium-large-span);
1293
+ --spatial-layout-medium-large-start: var(--spatial-layout-medium-large-start);
1294
+ --spatial-layout-medium-medium-span: var(--spatial-layout-medium-medium-span);
1295
+ --spatial-layout-medium-medium-start: var(--spatial-layout-medium-medium-start);
1296
+ --spatial-layout-narrow-large-span: var(--spatial-layout-narrow-large-span);
1297
+ --spatial-layout-narrow-large-start: var(--spatial-layout-narrow-large-start);
1298
+ --spatial-layout-narrow-medium-span: var(--spatial-layout-narrow-medium-span);
1299
+ --spatial-layout-narrow-medium-start: var(--spatial-layout-narrow-medium-start);
1300
+ --spatial-layout-wide-large-span: var(--spatial-layout-wide-large-span);
1301
+ --spatial-layout-wide-large-start: var(--spatial-layout-wide-large-start);
1302
+ --spatial-layout-wide-medium-span: var(--spatial-layout-wide-medium-span);
1303
+ --spatial-layout-wide-medium-start: var(--spatial-layout-wide-medium-start);
1267
1304
  --spatial-section-large-gap: var(--spatial-section-large-gap);
1268
1305
  --spatial-section-large-padding: var(--spatial-section-large-padding);
1269
1306
  --spatial-section-medium-gap: var(--spatial-section-medium-gap);
@@ -1411,26 +1448,26 @@
1411
1448
 
1412
1449
  :root {
1413
1450
  /* Semantic Color Tokens */
1414
- --color-accent-brand-soft: color(srgb 0.9686 0.8078 0.749);
1415
- --color-accent-brand: color(srgb 0.9216 0.3098 0.1529);
1416
- --color-bg-muted: color(srgb 1 1 1);
1417
- --color-bg-page: color(srgb 0.9804 0.9804 0.9804);
1418
- --color-bg-section: color(srgb 0.9608 0.9608 0.9608);
1419
- --color-border-divider: color(srgb 0 0 0 / 0.1);
1420
- --color-border-focus: color(srgb 0.9216 0.3098 0.1529);
1421
- --color-border-strong: color(srgb 0 0 0 / 0.2);
1422
- --color-border-subtle: color(srgb 0 0 0 / 0.1);
1423
- --color-button-primary-bg-hover: color(srgb 0.4588 0.4588 0.4588);
1424
- --color-button-primary-bg: color(srgb 0.0784 0.0784 0.0784);
1451
+ --color-accent-brand-soft: color(srgb 0.7686 0.6588 0.4392);
1452
+ --color-accent-brand: color(srgb 0.651 0.5451 0.3686);
1453
+ --color-bg-muted: color(srgb 0.9961 0.9922 0.9765);
1454
+ --color-bg-page: color(srgb 0.9961 0.9922 0.9765);
1455
+ --color-bg-section: color(srgb 0.9608 0.9569 0.9373);
1456
+ --color-border-divider: color(srgb 0.149 0.1569 0.2941 / 0.1);
1457
+ --color-border-focus: color(srgb 0.651 0.5451 0.3686);
1458
+ --color-border-strong: color(srgb 0.149 0.1569 0.2941 / 0.2);
1459
+ --color-border-subtle: color(srgb 0.149 0.1569 0.2941 / 0.1);
1460
+ --color-button-primary-bg-hover: color(srgb 0.149 0.1569 0.2941);
1461
+ --color-button-primary-bg: color(srgb 0.0667 0.0745 0.149);
1425
1462
  --color-button-secondary-bg-hover: color(srgb 1 1 1);
1426
1463
  --color-button-secondary-bg: color(srgb 1 1 1);
1427
- --color-card-background: color(srgb 1 1 1);
1428
- --color-text-inverted: color(srgb 0.9608 0.9608 0.9608);
1464
+ --color-card-background: color(srgb 0.5412 0.4353 0.2588);
1465
+ --color-text-inverted: color(srgb 0.9961 0.9922 0.9765);
1429
1466
  --color-text-link-hover: color(srgb 0.3804 0.3804 0.3804);
1430
1467
  --color-text-link: color(srgb 0.0784 0.0784 0.0784);
1431
- --color-text-muted: color(srgb 0.4588 0.4588 0.4588);
1432
- --color-text-primary: color(srgb 0.0784 0.0784 0.0784);
1433
- --color-text-secondary: color(srgb 0.2588 0.2588 0.2588);
1468
+ --color-text-muted: color(srgb 0.651 0.5451 0.3686);
1469
+ --color-text-primary: color(srgb 0.0667 0.0745 0.149);
1470
+ --color-text-secondary: color(srgb 0.0667 0.0745 0.149);
1434
1471
  --radius-surface-button: var(--radius-6);
1435
1472
  --radius-surface-card: var(--radius-4);
1436
1473
  --surface-button-stroke: 1px;
@@ -1466,6 +1503,102 @@
1466
1503
  }
1467
1504
 
1468
1505
 
1506
+ @utility typography-bop-body-large {
1507
+ font-family: var(--font-cormorant);
1508
+ font-size: 28px;
1509
+ font-weight: var(--font-weight-medium);
1510
+ line-height: 1.4;
1511
+ letter-spacing: 0;
1512
+ }
1513
+
1514
+ @utility typography-bop-body-medium {
1515
+ font-family: var(--font-cormorant);
1516
+ font-size: 18px;
1517
+ font-weight: var(--font-weight-regular);
1518
+ line-height: 1.5;
1519
+ letter-spacing: 0;
1520
+ }
1521
+
1522
+ @utility typography-bop-body-small {
1523
+ font-family: var(--font-cormorant);
1524
+ font-size: 16px;
1525
+ font-weight: var(--font-weight-regular);
1526
+ line-height: 1.5;
1527
+ letter-spacing: 0;
1528
+ }
1529
+
1530
+ @utility typography-bop-display-hero {
1531
+ font-family: var(--font-gloock);
1532
+ font-size: 12.5vw;
1533
+ font-weight: var(--font-weight-regular);
1534
+ line-height: 1.1;
1535
+ letter-spacing: -0.03em;
1536
+ }
1537
+
1538
+ @utility typography-bop-display-large {
1539
+ font-family: var(--font-gloock);
1540
+ font-size: 8vw;
1541
+ font-weight: var(--font-weight-regular);
1542
+ line-height: 1.1;
1543
+ letter-spacing: -0.025em;
1544
+ }
1545
+
1546
+ @utility typography-bop-display-medium {
1547
+ font-family: var(--font-gloock);
1548
+ font-size: 5vw;
1549
+ font-weight: var(--font-weight-regular);
1550
+ line-height: 1.2;
1551
+ letter-spacing: -0.02em;
1552
+ }
1553
+
1554
+ @utility typography-bop-headline-large {
1555
+ font-family: var(--font-cormorant);
1556
+ font-size: 48px;
1557
+ font-weight: var(--font-weight-medium);
1558
+ line-height: 1.2;
1559
+ letter-spacing: -1px;
1560
+ }
1561
+
1562
+ @utility typography-bop-headline-medium {
1563
+ font-family: var(--font-cormorant);
1564
+ font-size: 32px;
1565
+ font-weight: var(--font-weight-medium);
1566
+ line-height: 0.95;
1567
+ letter-spacing: -1px;
1568
+ }
1569
+
1570
+ @utility typography-bop-headline-small {
1571
+ font-family: var(--font-cormorant);
1572
+ font-size: 24px;
1573
+ font-weight: var(--font-weight-medium);
1574
+ line-height: 1.2;
1575
+ letter-spacing: -0.5px;
1576
+ }
1577
+
1578
+ @utility typography-bop-ui-button {
1579
+ font-family: var(--font-pp-neue-montreal);
1580
+ font-size: 16px;
1581
+ font-weight: var(--font-weight-medium);
1582
+ line-height: 1;
1583
+ letter-spacing: 0.5px;
1584
+ }
1585
+
1586
+ @utility typography-bop-ui-caption {
1587
+ font-family: var(--font-pp-neue-montreal);
1588
+ font-size: 14px;
1589
+ font-weight: var(--font-weight-regular);
1590
+ line-height: 1.4;
1591
+ letter-spacing: 0;
1592
+ }
1593
+
1594
+ @utility typography-bop-ui-nav {
1595
+ font-family: var(--font-pp-neue-montreal);
1596
+ font-size: 13px;
1597
+ font-weight: var(--font-weight-medium);
1598
+ line-height: 0.95;
1599
+ letter-spacing: 0;
1600
+ }
1601
+
1469
1602
  @utility typography-large-body-large {
1470
1603
  font-family: var(--font-pp-neue-montreal);
1471
1604
  font-size: var(--text-21);
@@ -24051,6 +24184,32 @@
24051
24184
  }
24052
24185
 
24053
24186
 
24187
+ /* Font Family Utilities */
24188
+ @utility font-cormorant {
24189
+ font-family: var(--font-cormorant);
24190
+ }
24191
+
24192
+ @utility font-gloock {
24193
+ font-family: var(--font-gloock);
24194
+ }
24195
+
24196
+ @utility font-pp-neue-montreal {
24197
+ font-family: var(--font-pp-neue-montreal);
24198
+ }
24199
+
24200
+ @utility font-sans {
24201
+ font-family: var(--font-sans);
24202
+ }
24203
+
24204
+ @utility font-serif {
24205
+ font-family: var(--font-serif);
24206
+ }
24207
+
24208
+ @utility font-serif-alt {
24209
+ font-family: var(--font-serif-alt);
24210
+ }
24211
+
24212
+
24054
24213
  /* Surface Utilities */
24055
24214
  @utility rounded-surface-button {
24056
24215
  border-radius: var(--radius-surface-button);
@@ -24158,4 +24317,36 @@
24158
24317
  @utility stroke-y-surface-card {
24159
24318
  border-top-width: var(--surface-card-stroke);
24160
24319
  border-bottom-width: var(--surface-card-stroke);
24320
+ }
24321
+
24322
+
24323
+ /* Grid Content Layout Utilities */
24324
+ @utility grid-content-medium {
24325
+ grid-column: 1 / -1;
24326
+ @media (width >= 48rem) {
24327
+ grid-column: 2 / span 10;
24328
+ }
24329
+ @media (width >= 90rem) {
24330
+ grid-column: 3 / span 8;
24331
+ }
24332
+ }
24333
+
24334
+ @utility grid-content-narrow {
24335
+ grid-column: 1 / -1;
24336
+ @media (width >= 48rem) {
24337
+ grid-column: 3 / span 8;
24338
+ }
24339
+ @media (width >= 90rem) {
24340
+ grid-column: 3 / span 8;
24341
+ }
24342
+ }
24343
+
24344
+ @utility grid-content-wide {
24345
+ grid-column: 1 / -1;
24346
+ @media (width >= 48rem) {
24347
+ grid-column: 1 / span 12;
24348
+ }
24349
+ @media (width >= 90rem) {
24350
+ grid-column: 2 / span 10;
24351
+ }
24161
24352
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nationaldesignstudio/react",
3
- "version": "0.0.17",
3
+ "version": "0.1.0",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "*.css"
@@ -47,9 +47,7 @@
47
47
  "dependencies": {
48
48
  "@base-ui-components/react": "^1.0.0-rc.0",
49
49
  "@radix-ui/react-slot": "^1.2.4",
50
- "tailwind-variants": "^0.3.1",
51
- "clsx": "^2.1.1",
52
- "tailwind-merge": "^3.4.0"
50
+ "tailwind-variants": "^0.3.1"
53
51
  },
54
52
  "devDependencies": {
55
53
  "@chromatic-com/storybook": "catalog:",
@@ -0,0 +1,233 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { page, userEvent } from "vitest/browser";
3
+ import { render } from "vitest-browser-react";
4
+ import { Accordion, AccordionItem } from "./accordion";
5
+
6
+ describe("Accordion", () => {
7
+ describe("Rendering", () => {
8
+ test("renders accordion with items", async () => {
9
+ render(
10
+ <Accordion>
11
+ <AccordionItem id="item-1" title="Question 1">
12
+ Answer 1
13
+ </AccordionItem>
14
+ <AccordionItem id="item-2" title="Question 2">
15
+ Answer 2
16
+ </AccordionItem>
17
+ </Accordion>,
18
+ );
19
+ await expect
20
+ .element(page.getByRole("button", { name: "Question 1" }))
21
+ .toBeInTheDocument();
22
+ await expect
23
+ .element(page.getByRole("button", { name: "Question 2" }))
24
+ .toBeInTheDocument();
25
+ });
26
+
27
+ test("renders with default expanded item", async () => {
28
+ render(
29
+ <Accordion defaultExpanded="item-1">
30
+ <AccordionItem id="item-1" title="Question 1">
31
+ Answer 1
32
+ </AccordionItem>
33
+ <AccordionItem id="item-2" title="Question 2">
34
+ Answer 2
35
+ </AccordionItem>
36
+ </Accordion>,
37
+ );
38
+ // The first item should be expanded (has data-open attribute)
39
+ await expect
40
+ .element(page.getByRole("button", { name: "Question 1" }))
41
+ .toHaveAttribute("data-open");
42
+ });
43
+
44
+ test("renders with multiple default expanded items", async () => {
45
+ render(
46
+ <Accordion allowMultiple defaultExpanded={["item-1", "item-2"]}>
47
+ <AccordionItem id="item-1" title="Question 1">
48
+ Answer 1
49
+ </AccordionItem>
50
+ <AccordionItem id="item-2" title="Question 2">
51
+ Answer 2
52
+ </AccordionItem>
53
+ </Accordion>,
54
+ );
55
+ await expect
56
+ .element(page.getByRole("button", { name: "Question 1" }))
57
+ .toHaveAttribute("data-open");
58
+ await expect
59
+ .element(page.getByRole("button", { name: "Question 2" }))
60
+ .toHaveAttribute("data-open");
61
+ });
62
+ });
63
+
64
+ describe("Keyboard Navigation", () => {
65
+ test("items are focusable via Tab", async () => {
66
+ render(
67
+ <Accordion>
68
+ <AccordionItem id="item-1" title="Question 1">
69
+ Answer 1
70
+ </AccordionItem>
71
+ <AccordionItem id="item-2" title="Question 2">
72
+ Answer 2
73
+ </AccordionItem>
74
+ </Accordion>,
75
+ );
76
+ await userEvent.keyboard("{Tab}");
77
+ await expect
78
+ .element(page.getByRole("button", { name: "Question 1" }))
79
+ .toHaveFocus();
80
+ });
81
+
82
+ test("Enter key expands/collapses item", async () => {
83
+ render(
84
+ <Accordion>
85
+ <AccordionItem id="item-1" title="Question 1">
86
+ Answer 1
87
+ </AccordionItem>
88
+ </Accordion>,
89
+ );
90
+ const trigger = page.getByRole("button", { name: "Question 1" });
91
+ trigger.element().focus();
92
+ await userEvent.keyboard("{Enter}");
93
+ await expect.element(trigger).toHaveAttribute("data-open");
94
+ });
95
+
96
+ test("Space key expands/collapses item", async () => {
97
+ render(
98
+ <Accordion>
99
+ <AccordionItem id="item-1" title="Question 1">
100
+ Answer 1
101
+ </AccordionItem>
102
+ </Accordion>,
103
+ );
104
+ const trigger = page.getByRole("button", { name: "Question 1" });
105
+ trigger.element().focus();
106
+ await userEvent.keyboard(" ");
107
+ await expect.element(trigger).toHaveAttribute("data-open");
108
+ });
109
+ });
110
+
111
+ describe("Click Interactions", () => {
112
+ test("clicking trigger expands item", async () => {
113
+ render(
114
+ <Accordion>
115
+ <AccordionItem id="item-1" title="Question 1">
116
+ Answer 1
117
+ </AccordionItem>
118
+ </Accordion>,
119
+ );
120
+ const trigger = page.getByRole("button", { name: "Question 1" });
121
+ await trigger.click();
122
+ await expect.element(trigger).toHaveAttribute("data-open");
123
+ });
124
+
125
+ test("clicking expanded trigger collapses item", async () => {
126
+ render(
127
+ <Accordion defaultExpanded="item-1">
128
+ <AccordionItem id="item-1" title="Question 1">
129
+ Answer 1
130
+ </AccordionItem>
131
+ </Accordion>,
132
+ );
133
+ const trigger = page.getByRole("button", { name: "Question 1" });
134
+ await expect.element(trigger).toHaveAttribute("data-open");
135
+ await trigger.click();
136
+ await expect.element(trigger).not.toHaveAttribute("data-open");
137
+ });
138
+
139
+ test("single mode collapses other items when opening new one", async () => {
140
+ render(
141
+ <Accordion defaultExpanded="item-1">
142
+ <AccordionItem id="item-1" title="Question 1">
143
+ Answer 1
144
+ </AccordionItem>
145
+ <AccordionItem id="item-2" title="Question 2">
146
+ Answer 2
147
+ </AccordionItem>
148
+ </Accordion>,
149
+ );
150
+ const trigger1 = page.getByRole("button", { name: "Question 1" });
151
+ const trigger2 = page.getByRole("button", { name: "Question 2" });
152
+
153
+ await expect.element(trigger1).toHaveAttribute("data-open");
154
+ await trigger2.click();
155
+ await expect.element(trigger2).toHaveAttribute("data-open");
156
+ await expect.element(trigger1).not.toHaveAttribute("data-open");
157
+ });
158
+
159
+ test("multiple mode allows multiple items open", async () => {
160
+ render(
161
+ <Accordion allowMultiple defaultExpanded="item-1">
162
+ <AccordionItem id="item-1" title="Question 1">
163
+ Answer 1
164
+ </AccordionItem>
165
+ <AccordionItem id="item-2" title="Question 2">
166
+ Answer 2
167
+ </AccordionItem>
168
+ </Accordion>,
169
+ );
170
+ const trigger1 = page.getByRole("button", { name: "Question 1" });
171
+ const trigger2 = page.getByRole("button", { name: "Question 2" });
172
+
173
+ await expect.element(trigger1).toHaveAttribute("data-open");
174
+ await trigger2.click();
175
+ await expect.element(trigger1).toHaveAttribute("data-open");
176
+ await expect.element(trigger2).toHaveAttribute("data-open");
177
+ });
178
+ });
179
+
180
+ describe("Variants", () => {
181
+ test("applies light variant by default", async () => {
182
+ render(
183
+ <Accordion>
184
+ <AccordionItem id="item-1" title="Question 1">
185
+ Answer 1
186
+ </AccordionItem>
187
+ </Accordion>,
188
+ );
189
+ const trigger = page.getByRole("button", { name: "Question 1" });
190
+ // Light variant has gray-800 text
191
+ await expect.element(trigger).toHaveClass(/text-gray-800/);
192
+ });
193
+
194
+ test("applies dark variant classes", async () => {
195
+ render(
196
+ <Accordion variant="dark">
197
+ <AccordionItem id="item-1" title="Question 1">
198
+ Answer 1
199
+ </AccordionItem>
200
+ </Accordion>,
201
+ );
202
+ const trigger = page.getByRole("button", { name: "Question 1" });
203
+ // Dark variant has gray-100 text
204
+ await expect.element(trigger).toHaveClass(/text-gray-100/);
205
+ });
206
+ });
207
+
208
+ describe("Content", () => {
209
+ test("displays title text in trigger", async () => {
210
+ render(
211
+ <Accordion>
212
+ <AccordionItem id="item-1" title="Custom Title">
213
+ Content here
214
+ </AccordionItem>
215
+ </Accordion>,
216
+ );
217
+ await expect.element(page.getByText("Custom Title")).toBeInTheDocument();
218
+ });
219
+
220
+ test("displays content when expanded", async () => {
221
+ render(
222
+ <Accordion defaultExpanded="item-1">
223
+ <AccordionItem id="item-1" title="Question 1">
224
+ Answer content here
225
+ </AccordionItem>
226
+ </Accordion>,
227
+ );
228
+ await expect
229
+ .element(page.getByText("Answer content here"))
230
+ .toBeInTheDocument();
231
+ });
232
+ });
233
+ });
@@ -18,7 +18,7 @@ const accordionVariants = tv({
18
18
  },
19
19
  },
20
20
  defaultVariants: {
21
- variant: "dark",
21
+ variant: "light",
22
22
  },
23
23
  });
24
24
 
@@ -31,7 +31,7 @@ const accordionItemVariants = tv({
31
31
  },
32
32
  },
33
33
  defaultVariants: {
34
- variant: "dark",
34
+ variant: "light",
35
35
  },
36
36
  });
37
37
 
@@ -48,7 +48,7 @@ const accordionTriggerVariants = tv({
48
48
  },
49
49
  },
50
50
  defaultVariants: {
51
- variant: "dark",
51
+ variant: "light",
52
52
  },
53
53
  });
54
54
 
@@ -62,7 +62,7 @@ const accordionPanelVariants = tv({
62
62
  },
63
63
  },
64
64
  defaultVariants: {
65
- variant: "dark",
65
+ variant: "light",
66
66
  },
67
67
  });
68
68
 
@@ -73,7 +73,7 @@ const accordionPanelVariants = tv({
73
73
  const AccordionContext = React.createContext<{
74
74
  variant: "dark" | "light";
75
75
  }>({
76
- variant: "dark",
76
+ variant: "light",
77
77
  });
78
78
 
79
79
  // =============================================================================
@@ -100,8 +100,8 @@ export interface AccordionProps
100
100
  * Built on Base UI's Accordion primitive.
101
101
  *
102
102
  * Variants:
103
- * - dark: Dark theme styling (default)
104
- * - light: Light theme styling
103
+ * - light: Light theme styling (default)
104
+ * - dark: Dark theme styling
105
105
  *
106
106
  * @example
107
107
  * ```tsx
@@ -134,7 +134,7 @@ const Accordion = React.forwardRef<HTMLDivElement, AccordionProps>(
134
134
  }, [defaultExpanded]);
135
135
 
136
136
  return (
137
- <AccordionContext.Provider value={{ variant: variant ?? "dark" }}>
137
+ <AccordionContext.Provider value={{ variant }}>
138
138
  <BaseAccordion.Root
139
139
  ref={ref}
140
140
  className={accordionVariants({ variant, class: className })}