@roadlittledawn/docs-design-system-react 0.4.0 → 0.5.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.
@@ -0,0 +1,183 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { Popover } from "./Popover";
14
+ var meta = {
15
+ title: "Components/Popover",
16
+ component: Popover,
17
+ tags: ["autodocs"],
18
+ parameters: {
19
+ layout: "centered",
20
+ docs: {
21
+ description: {
22
+ component: "\nA hover/tap-activated popover for enriching inline content in documentation.\nBuilt on the native [Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API) for reliable top-layer rendering \u2014 no z-index wars, no overflow clipping.\n\nCommon use cases include glossary term definitions and Wikipedia-style content previews.\n\n## Content modes\n\nThe `Popover` supports three mutually exclusive content modes, checked in this order:\n\n1. **`content`** \u2014 arbitrary `ReactNode`; you control everything\n2. **`glossary`** \u2014 structured `{ term, title, definition }` template\n3. **`preview`** \u2014 structured `{ title, excerpt, imageUrl, href }` template\n\n## When to Use\n\n- Inline term definitions that would interrupt reading flow if expanded in-place\n- Link previews that let users get context without navigating away\n- Any contextual content that benefits from being on-demand rather than always visible\n\n## When Not to Use\n\n- For critical information users must read \u2014 use a `Callout` instead\n- As a primary navigation mechanism\n- For content that needs persistent visibility\n\n## Mobile behavior\n\nOn screens \u2264 640 px the popover renders as a bottom sheet instead of a floating panel.\nHover events don't apply; the popover toggles on tap.\n\n## Accessibility\n\n- Trigger has `tabIndex={0}` and shows the popover on focus (keyboard accessible)\n- Popover panel has `role=\"tooltip\"` and is linked via `aria-describedby`\n- The native Popover API handles Escape-key dismissal automatically\n- Light-dismiss (click outside) is provided by `popover=\"auto\"`\n ",
23
+ },
24
+ },
25
+ },
26
+ };
27
+ export default meta;
28
+ /**
29
+ * The glossary template renders a structured definition popover.
30
+ * The `definition` field accepts `ReactNode` — pre-render any markdown
31
+ * using your preferred renderer before passing it in.
32
+ */
33
+ export var GlossaryDefinition = {
34
+ args: {
35
+ glossary: {
36
+ term: "observability",
37
+ title: "Observability",
38
+ definition: (_jsxs(_Fragment, { children: ["The ability to understand the internal state of a system by examining its external outputs \u2014 primarily", " ", _jsx("a", { href: "https://example.com/metrics", children: "metrics" }), ", logs, and traces."] })),
39
+ },
40
+ },
41
+ parameters: {
42
+ docs: {
43
+ source: {
44
+ code: "<Popover\n glossary={{\n term: \"observability\",\n title: \"Observability\",\n definition: (\n <>\n The ability to understand the internal state of a system by examining\n its external outputs \u2014 primarily{\" \"}\n <a href=\"https://example.com/metrics\">metrics</a>, logs, and traces.\n </>\n ),\n }}\n>\n observability\n</Popover>",
45
+ },
46
+ },
47
+ },
48
+ render: function (args) { return (_jsxs("p", { style: { fontFamily: "sans-serif", fontSize: "1rem", color: "var(--dds-tabs-panel-text)" }, children: ["Modern software reliability depends on", " ", _jsx(Popover, __assign({}, args, { children: "observability" })), " to diagnose production issues quickly."] })); },
49
+ };
50
+ /**
51
+ * The preview template renders a Wikipedia-style content preview with an
52
+ * optional featured image, excerpt, and "Read more" link.
53
+ */
54
+ export var ContentPreview = {
55
+ args: {
56
+ preview: {
57
+ title: "New Relic",
58
+ excerpt: "New Relic is an observability platform that helps engineers plan, build, deploy, and run software. Over 17,000 customers use New Relic to improve uptime, performance, and operational efficiency.",
59
+ imageUrl: "https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=640&q=80",
60
+ href: "https://newrelic.com",
61
+ linkText: "Read more",
62
+ },
63
+ size: "lg",
64
+ },
65
+ parameters: {
66
+ docs: {
67
+ source: {
68
+ code: "<Popover\n size=\"lg\"\n preview={{\n title: \"New Relic\",\n excerpt: \"New Relic is an observability platform that helps engineers plan, build, deploy, and run software.\",\n imageUrl: \"/images/newrelic.jpg\",\n href: \"https://newrelic.com\",\n linkText: \"Read more\",\n }}\n>\n New Relic\n</Popover>",
69
+ },
70
+ },
71
+ },
72
+ render: function (args) { return (_jsxs("p", { style: { fontFamily: "sans-serif", fontSize: "1rem", color: "var(--dds-tabs-panel-text)" }, children: ["The monitoring data is sent to ", _jsx(Popover, __assign({}, args, { children: "New Relic" })), " ", "where you can build dashboards and alerts."] })); },
73
+ };
74
+ /**
75
+ * Pass any React element as the `content` prop when the built-in templates
76
+ * don't fit your use case.
77
+ */
78
+ export var CustomContent = {
79
+ args: {
80
+ content: (_jsxs("div", { style: { padding: "1rem" }, children: [_jsx("strong", { style: { display: "block", marginBottom: "0.5rem" }, children: "API Rate Limits" }), _jsxs("table", { style: { fontSize: "0.8125rem", borderCollapse: "collapse", width: "100%" }, children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { style: { textAlign: "left", paddingBottom: "0.25rem", borderBottom: "1px solid #e5e7eb" }, children: "Plan" }), _jsx("th", { style: { textAlign: "right", paddingBottom: "0.25rem", borderBottom: "1px solid #e5e7eb" }, children: "Req/min" })] }) }), _jsxs("tbody", { children: [_jsxs("tr", { children: [_jsx("td", { children: "Free" }), _jsx("td", { style: { textAlign: "right" }, children: "60" })] }), _jsxs("tr", { children: [_jsx("td", { children: "Pro" }), _jsx("td", { style: { textAlign: "right" }, children: "1,000" })] }), _jsxs("tr", { children: [_jsx("td", { children: "Enterprise" }), _jsx("td", { style: { textAlign: "right" }, children: "Unlimited" })] })] })] })] })),
81
+ size: "md",
82
+ },
83
+ parameters: {
84
+ docs: {
85
+ source: {
86
+ code: "<Popover\n content={\n <div style={{ padding: \"1rem\" }}>\n <strong>API Rate Limits</strong>\n {/* custom table or any JSX */}\n </div>\n }\n>\n rate limits\n</Popover>",
87
+ },
88
+ },
89
+ },
90
+ render: function (args) { return (_jsxs("p", { style: { fontFamily: "sans-serif", fontSize: "1rem", color: "var(--dds-tabs-panel-text)" }, children: ["Each API key is subject to ", _jsx(Popover, __assign({}, args, { children: "rate limits" })), " based on your subscription plan."] })); },
91
+ };
92
+ /**
93
+ * Size variants — sm (240px), md (320px), lg (480px).
94
+ */
95
+ export var Sizes = {
96
+ parameters: {
97
+ docs: {
98
+ source: {
99
+ code: "<Popover size=\"sm\" glossary={{ term: \"sm\", title: \"Small (240px)\", definition: \"A compact popover for brief definitions.\" }}>\n small\n</Popover>\n\n<Popover size=\"md\" glossary={{ term: \"md\", title: \"Medium (320px)\", definition: \"The default size, suitable for most glossary and preview use cases.\" }}>\n medium\n</Popover>\n\n<Popover size=\"lg\" glossary={{ term: \"lg\", title: \"Large (480px)\", definition: \"A wider panel for rich content previews with images or tables.\" }}>\n large\n</Popover>",
100
+ },
101
+ },
102
+ },
103
+ render: function () { return (_jsxs("div", { style: {
104
+ fontFamily: "sans-serif",
105
+ fontSize: "1rem",
106
+ display: "flex",
107
+ gap: "2rem",
108
+ alignItems: "center",
109
+ color: "var(--dds-tabs-panel-text)",
110
+ }, children: [_jsx(Popover, { size: "sm", glossary: {
111
+ term: "sm",
112
+ title: "Small (240px)",
113
+ definition: "A compact popover for brief definitions.",
114
+ }, children: "small" }), _jsx(Popover, { size: "md", glossary: {
115
+ term: "md",
116
+ title: "Medium (320px)",
117
+ definition: "The default size, suitable for most glossary and preview use cases.",
118
+ }, children: "medium" }), _jsx(Popover, { size: "lg", glossary: {
119
+ term: "lg",
120
+ title: "Large (480px)",
121
+ definition: "A wider panel for rich content previews with images or tables.",
122
+ }, children: "large" })] })); },
123
+ };
124
+ /**
125
+ * Placement variants control which side of the trigger the popover appears on.
126
+ * "auto" (default) detects available viewport space.
127
+ */
128
+ export var Placement = {
129
+ parameters: {
130
+ docs: {
131
+ source: {
132
+ code: "<Popover placement=\"top\" glossary={...}>shows above</Popover>\n<Popover placement=\"bottom\" glossary={...}>shows below</Popover>\n<Popover placement=\"top-start\" glossary={...}>top-start</Popover>\n<Popover placement=\"bottom-end\" glossary={...}>bottom-end</Popover>",
133
+ },
134
+ },
135
+ },
136
+ render: function () { return (_jsx("div", { style: {
137
+ fontFamily: "sans-serif",
138
+ fontSize: "1rem",
139
+ display: "flex",
140
+ flexWrap: "wrap",
141
+ gap: "2rem",
142
+ justifyContent: "center",
143
+ padding: "6rem 2rem",
144
+ color: "var(--dds-tabs-panel-text)",
145
+ }, children: [
146
+ "top",
147
+ "top-start",
148
+ "top-end",
149
+ "bottom",
150
+ "bottom-start",
151
+ "bottom-end",
152
+ ].map(function (p) { return (_jsx(Popover, { placement: p, glossary: {
153
+ term: p,
154
+ title: "placement=\"".concat(p, "\""),
155
+ definition: "The popover opens ".concat(p.replace("-", " "), " relative to its trigger."),
156
+ }, children: p }, p)); }) })); },
157
+ };
158
+ /**
159
+ * Multiple popovers in a paragraph — only one can be open at a time
160
+ * (native Popover API `popover="auto"` behaviour).
161
+ */
162
+ export var InlineParagraph = {
163
+ parameters: {
164
+ docs: {
165
+ source: {
166
+ code: "<p>\n <Popover glossary={{ term: \"apm\", title: \"APM\", definition: \"Application Performance Monitoring...\" }}>APM</Popover>\n {\" \"}data flows into{\" \"}\n <Popover preview={{ title: \"New Relic\", excerpt: \"...\", href: \"https://newrelic.com\" }}>New Relic</Popover>\n {\" \"}where you can configure{\" \"}\n <Popover glossary={{ term: \"alert\", title: \"Alert\", definition: \"A notification triggered when a signal crosses a threshold.\" }}>alerts</Popover>.\n</p>",
167
+ },
168
+ },
169
+ },
170
+ render: function () { return (_jsxs("p", { style: { fontFamily: "sans-serif", fontSize: "1rem", maxWidth: "480px", lineHeight: 1.7, color: "var(--dds-tabs-panel-text)", margin: 0 }, children: [_jsx(Popover, { glossary: {
171
+ term: "apm",
172
+ title: "APM",
173
+ definition: "Application Performance Monitoring — tracks the performance of software applications and their underlying infrastructure.",
174
+ }, children: "APM" }), " ", "data flows into", " ", _jsx(Popover, { preview: {
175
+ title: "New Relic",
176
+ excerpt: "New Relic is an observability platform used by over 17,000 customers.",
177
+ href: "https://newrelic.com",
178
+ }, children: "New Relic" }), " ", "where you can configure", " ", _jsx(Popover, { glossary: {
179
+ term: "alert",
180
+ title: "Alert",
181
+ definition: "A notification triggered when a metric or signal crosses a defined threshold.",
182
+ }, children: "alerts" }), " ", "to notify your on-call team."] })); },
183
+ };
@@ -24,6 +24,13 @@ export var H1 = {
24
24
  variant: 'h1',
25
25
  children: 'Heading 1 Style',
26
26
  },
27
+ parameters: {
28
+ docs: {
29
+ source: {
30
+ code: "<Typography variant=\"h1\">Heading 1 Style</Typography>",
31
+ },
32
+ },
33
+ },
27
34
  };
28
35
  /**
29
36
  * H2 heading style.
@@ -33,6 +40,13 @@ export var H2 = {
33
40
  variant: 'h2',
34
41
  children: 'Heading 2 Style',
35
42
  },
43
+ parameters: {
44
+ docs: {
45
+ source: {
46
+ code: "<Typography variant=\"h2\">Heading 2 Style</Typography>",
47
+ },
48
+ },
49
+ },
36
50
  };
37
51
  /**
38
52
  * H3 heading style.
@@ -42,6 +56,13 @@ export var H3 = {
42
56
  variant: 'h3',
43
57
  children: 'Heading 3 Style',
44
58
  },
59
+ parameters: {
60
+ docs: {
61
+ source: {
62
+ code: "<Typography variant=\"h3\">Heading 3 Style</Typography>",
63
+ },
64
+ },
65
+ },
45
66
  };
46
67
  /**
47
68
  * H4 heading style.
@@ -51,6 +72,13 @@ export var H4 = {
51
72
  variant: 'h4',
52
73
  children: 'Heading 4 Style',
53
74
  },
75
+ parameters: {
76
+ docs: {
77
+ source: {
78
+ code: "<Typography variant=\"h4\">Heading 4 Style</Typography>",
79
+ },
80
+ },
81
+ },
54
82
  };
55
83
  /**
56
84
  * Paragraph style (default).
@@ -60,6 +88,13 @@ export var Paragraph = {
60
88
  variant: 'p',
61
89
  children: 'This is a paragraph with the default typography style. It provides readable text for body content.',
62
90
  },
91
+ parameters: {
92
+ docs: {
93
+ source: {
94
+ code: "<Typography variant=\"p\">\n This is a paragraph with the default typography style. It provides readable text for body content.\n</Typography>",
95
+ },
96
+ },
97
+ },
63
98
  };
64
99
  /**
65
100
  * Caption style for small text.
@@ -69,10 +104,24 @@ export var Caption = {
69
104
  variant: 'caption',
70
105
  children: 'This is caption text, typically used for figure captions or footnotes.',
71
106
  },
107
+ parameters: {
108
+ docs: {
109
+ source: {
110
+ code: "<Typography variant=\"caption\">\n This is caption text, typically used for figure captions or footnotes.\n</Typography>",
111
+ },
112
+ },
113
+ },
72
114
  };
73
115
  /**
74
116
  * All typography variants displayed together.
75
117
  */
76
118
  export var AllVariants = {
119
+ parameters: {
120
+ docs: {
121
+ source: {
122
+ code: "<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>\n <Typography variant=\"h1\">Heading 1 Style</Typography>\n <Typography variant=\"h2\">Heading 2 Style</Typography>\n <Typography variant=\"h3\">Heading 3 Style</Typography>\n <Typography variant=\"h4\">Heading 4 Style</Typography>\n <Typography variant=\"p\">\n This is paragraph text. It's the default variant and is suitable for\n body content and general text throughout your documentation.\n </Typography>\n <Typography variant=\"caption\">\n This is caption text, used for smaller annotations or supplementary information.\n </Typography>\n</div>",
123
+ },
124
+ },
125
+ },
77
126
  render: function () { return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '1rem' }, children: [_jsx(Typography, { variant: "h1", children: "Heading 1 Style" }), _jsx(Typography, { variant: "h2", children: "Heading 2 Style" }), _jsx(Typography, { variant: "h3", children: "Heading 3 Style" }), _jsx(Typography, { variant: "h4", children: "Heading 4 Style" }), _jsx(Typography, { variant: "p", children: "This is paragraph text. It's the default variant and is suitable for body content and general text throughout your documentation." }), _jsx(Typography, { variant: "caption", children: "This is caption text, used for smaller annotations or supplementary information." })] })); },
78
127
  };
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ export * from './components/Collapser';
6
6
  export * from './components/CollapserGroup';
7
7
  export * from './components/CodeBlock';
8
8
  export * from './components/Tabs';
9
+ export * from './components/Popover';
9
10
  export * from './components/Typography';
10
11
  export * from './components/Heading';
11
12
  export * from './components/Link';
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ export * from './components/Collapser';
7
7
  export * from './components/CollapserGroup';
8
8
  export * from './components/CodeBlock';
9
9
  export * from './components/Tabs';
10
+ export * from './components/Popover';
10
11
  export * from './components/Typography';
11
12
  export * from './components/Heading';
12
13
  export * from './components/Link';
package/dist/styles.css CHANGED
@@ -224,6 +224,27 @@
224
224
  --dds-tabs-tab-border-active: #3b82f6; /* blue-500 */
225
225
  --dds-tabs-panel-padding: 1.25rem 0;
226
226
  --dds-tabs-panel-text: #111827; /* gray-900 */
227
+
228
+ /* Popover */
229
+ --dds-popover-bg: #ffffff;
230
+ --dds-popover-border: #e5e7eb; /* gray-200 */
231
+ --dds-popover-radius: 0.5rem; /* rounded-lg */
232
+ --dds-popover-shadow:
233
+ 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 10px 15px -3px rgba(0, 0, 0, 0.1),
234
+ 0 2px 4px -1px rgba(0, 0, 0, 0.06);
235
+ --dds-popover-text: #374151; /* gray-700 */
236
+ --dds-popover-title-color: #111827; /* gray-900 */
237
+ --dds-popover-eyebrow-color: #6b7280; /* gray-500 */
238
+ --dds-popover-link-color: #2563eb; /* blue-600 */
239
+ --dds-popover-link-color-hover: #1e40af; /* blue-800 */
240
+ --dds-popover-width-sm: 240px;
241
+ --dds-popover-width-md: 320px;
242
+ --dds-popover-width-lg: 480px;
243
+ --dds-popover-padding: 1rem;
244
+ --dds-popover-image-height: 120px;
245
+ --dds-popover-title-size: 0.9375rem; /* ~15px */
246
+ --dds-popover-text-size: 0.875rem; /* text-sm */
247
+ --dds-popover-eyebrow-size: 0.6875rem; /* ~11px */
227
248
  }
228
249
  /* ==========================================================================
229
250
  Dark Mode Tokens
@@ -365,6 +386,18 @@
365
386
  --dds-prism-keyword: #60a5fa; /* blue-400 */
366
387
  --dds-prism-function: #a78bfa; /* violet-400 */
367
388
  --dds-prism-regex: #fb923c; /* orange-400 */
389
+
390
+ /* Popover */
391
+ --dds-popover-bg: #1f2937; /* gray-800 */
392
+ --dds-popover-border: #4b5563; /* gray-600 */
393
+ --dds-popover-shadow:
394
+ 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 10px 15px -3px rgba(0, 0, 0, 0.4),
395
+ 0 2px 4px -1px rgba(0, 0, 0, 0.2);
396
+ --dds-popover-text: #e5e7eb; /* gray-200 */
397
+ --dds-popover-title-color: #f9fafb; /* gray-50 */
398
+ --dds-popover-eyebrow-color: #9ca3af; /* gray-400 */
399
+ --dds-popover-link-color: #60a5fa; /* blue-400 */
400
+ --dds-popover-link-color-hover: #93c5fd; /* blue-300 */
368
401
  }
369
402
  /* Auto dark mode — follows OS preference, opt-out with .dds-light */
370
403
  @media (prefers-color-scheme: dark) {
@@ -501,6 +534,18 @@
501
534
  --dds-prism-keyword: #60a5fa;
502
535
  --dds-prism-function: #a78bfa;
503
536
  --dds-prism-regex: #fb923c;
537
+
538
+ /* Popover */
539
+ --dds-popover-bg: #1f2937;
540
+ --dds-popover-border: #4b5563;
541
+ --dds-popover-shadow:
542
+ 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 10px 15px -3px rgba(0, 0, 0, 0.4),
543
+ 0 2px 4px -1px rgba(0, 0, 0, 0.2);
544
+ --dds-popover-text: #e5e7eb;
545
+ --dds-popover-title-color: #f9fafb;
546
+ --dds-popover-eyebrow-color: #9ca3af;
547
+ --dds-popover-link-color: #60a5fa;
548
+ --dds-popover-link-color-hover: #93c5fd;
504
549
  }
505
550
  }
506
551
  /* Explicit dark mode via data attribute (overrides OS preference) */
@@ -626,6 +671,18 @@
626
671
  --dds-prism-keyword: #60a5fa;
627
672
  --dds-prism-function: #a78bfa;
628
673
  --dds-prism-regex: #fb923c;
674
+
675
+ /* Popover */
676
+ --dds-popover-bg: #1f2937;
677
+ --dds-popover-border: #4b5563;
678
+ --dds-popover-shadow:
679
+ 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 10px 15px -3px rgba(0, 0, 0, 0.4),
680
+ 0 2px 4px -1px rgba(0, 0, 0, 0.2);
681
+ --dds-popover-text: #e5e7eb;
682
+ --dds-popover-title-color: #f9fafb;
683
+ --dds-popover-eyebrow-color: #9ca3af;
684
+ --dds-popover-link-color: #60a5fa;
685
+ --dds-popover-link-color-hover: #93c5fd;
629
686
  }
630
687
  /* Import PrismJS theme */
631
688
  /**
@@ -1409,4 +1466,226 @@ a.no-text-decoration {
1409
1466
  margin-bottom: 0.25rem; /* mb-1 */
1410
1467
  vertical-align: middle;
1411
1468
  }
1469
+ /* ==========================================================================
1470
+ Popover Component
1471
+ Uses the native Popover API for top-layer rendering.
1472
+ Positioning is handled via inline styles set by JS (getBoundingClientRect).
1473
+ ========================================================================== */
1474
+ /* Trigger */
1475
+ .dds-popover-trigger {
1476
+ display: inline;
1477
+ cursor: default;
1478
+ text-decoration-line: underline;
1479
+ text-decoration-style: dotted;
1480
+ text-decoration-color: currentColor;
1481
+ text-underline-offset: 3px;
1482
+ border-radius: 2px;
1483
+ outline-offset: 2px;
1484
+ }
1485
+ .dds-popover-trigger:focus-visible {
1486
+ outline: 2px solid var(--dds-link-color);
1487
+ }
1488
+ /* ==========================================================================
1489
+ Popover panel — rendered in the top layer via Popover API
1490
+ ========================================================================== */
1491
+ .dds-popover {
1492
+ /* Reset browser popover defaults */
1493
+ margin: 0;
1494
+ padding: 0;
1495
+ border: none;
1496
+ overflow: visible;
1497
+ inset: unset; /* we set top/left via JS */
1498
+
1499
+ /* Layout */
1500
+ position: fixed;
1501
+ width: var(--dds-popover-width-md);
1502
+ max-width: calc(100vw - 16px);
1503
+
1504
+ /* Appearance */
1505
+ background: var(--dds-popover-bg);
1506
+ border: 1px solid var(--dds-popover-border);
1507
+ border-radius: var(--dds-popover-radius);
1508
+ box-shadow: var(--dds-popover-shadow);
1509
+ color: var(--dds-popover-text);
1510
+ font-size: var(--dds-popover-text-size);
1511
+ line-height: var(--dds-line-height-relaxed);
1512
+
1513
+ /* Hidden by default (Popover API manages this, but we set it for fallback) */
1514
+ display: none;
1515
+ }
1516
+ /* Popover API open state */
1517
+ .dds-popover:popover-open {
1518
+ display: block;
1519
+ }
1520
+ /* ==========================================================================
1521
+ Entry / exit animations
1522
+ ========================================================================== */
1523
+ @keyframes dds-popover-in-bottom {
1524
+ from {
1525
+ opacity: 0;
1526
+ transform: translateY(-6px);
1527
+ }
1528
+ to {
1529
+ opacity: 1;
1530
+ transform: translateY(0);
1531
+ }
1532
+ }
1533
+ @keyframes dds-popover-in-top {
1534
+ from {
1535
+ opacity: 0;
1536
+ transform: translateY(6px);
1537
+ }
1538
+ to {
1539
+ opacity: 1;
1540
+ transform: translateY(0);
1541
+ }
1542
+ }
1543
+ .dds-popover:popover-open {
1544
+ animation: dds-popover-in-bottom 150ms ease forwards;
1545
+ }
1546
+ .dds-popover:popover-open[data-placement="top"] {
1547
+ animation: dds-popover-in-top 150ms ease forwards;
1548
+ }
1549
+ /* @starting-style enables the entry animation when the element first enters the top layer */
1550
+ @starting-style {
1551
+ .dds-popover:popover-open {
1552
+ opacity: 0;
1553
+ transform: translateY(-6px);
1554
+ }
1555
+
1556
+ .dds-popover:popover-open[data-placement="top"] {
1557
+ opacity: 0;
1558
+ transform: translateY(6px);
1559
+ }
1560
+ }
1561
+ /* ==========================================================================
1562
+ Size variants
1563
+ ========================================================================== */
1564
+ .dds-popover-sm {
1565
+ width: var(--dds-popover-width-sm);
1566
+ }
1567
+ .dds-popover-md {
1568
+ width: var(--dds-popover-width-md);
1569
+ }
1570
+ .dds-popover-lg {
1571
+ width: var(--dds-popover-width-lg);
1572
+ }
1573
+ /* ==========================================================================
1574
+ Shared inner elements
1575
+ ========================================================================== */
1576
+ .dds-popover-eyebrow {
1577
+ display: block;
1578
+ font-size: var(--dds-popover-eyebrow-size);
1579
+ font-weight: var(--dds-font-semibold);
1580
+ letter-spacing: 0.08em;
1581
+ text-transform: uppercase;
1582
+ color: var(--dds-popover-eyebrow-color);
1583
+ margin-bottom: 0.25rem;
1584
+ }
1585
+ .dds-popover-title {
1586
+ margin: 0 0 0.5rem;
1587
+ font-size: var(--dds-popover-title-size);
1588
+ font-weight: var(--dds-font-semibold);
1589
+ color: var(--dds-popover-title-color);
1590
+ line-height: var(--dds-line-height-tight);
1591
+ }
1592
+ .dds-popover-title dfn {
1593
+ font-style: normal;
1594
+ }
1595
+ .dds-popover-body {
1596
+ color: var(--dds-popover-text);
1597
+ font-size: var(--dds-popover-text-size);
1598
+ line-height: var(--dds-line-height-relaxed);
1599
+ }
1600
+ .dds-popover-body p {
1601
+ margin: 0;
1602
+ }
1603
+ .dds-popover-body a {
1604
+ color: var(--dds-popover-link-color);
1605
+ }
1606
+ .dds-popover-body a:hover {
1607
+ color: var(--dds-popover-link-color-hover);
1608
+ }
1609
+ /* ==========================================================================
1610
+ Glossary template
1611
+ ========================================================================== */
1612
+ .dds-popover-glossary {
1613
+ padding: var(--dds-popover-padding);
1614
+ }
1615
+ /* ==========================================================================
1616
+ Preview template
1617
+ ========================================================================== */
1618
+ .dds-popover-preview {
1619
+ /* no padding at top — image goes edge-to-edge */
1620
+ }
1621
+ .dds-popover-preview-image-wrap {
1622
+ width: 100%;
1623
+ height: var(--dds-popover-image-height);
1624
+ overflow: hidden;
1625
+ border-radius: var(--dds-popover-radius) var(--dds-popover-radius) 0 0;
1626
+ background: var(--dds-popover-border);
1627
+ }
1628
+ .dds-popover-preview-image {
1629
+ width: 100%;
1630
+ height: 100%;
1631
+ object-fit: cover;
1632
+ display: block;
1633
+ }
1634
+ .dds-popover-preview-body {
1635
+ padding: var(--dds-popover-padding);
1636
+ }
1637
+ .dds-popover-preview-link {
1638
+ display: inline-block;
1639
+ margin-top: 0.5rem;
1640
+ font-size: var(--dds-popover-text-size);
1641
+ font-weight: var(--dds-font-medium);
1642
+ color: var(--dds-popover-link-color);
1643
+ text-decoration: none;
1644
+ }
1645
+ .dds-popover-preview-link:hover {
1646
+ color: var(--dds-popover-link-color-hover);
1647
+ text-decoration: underline;
1648
+ }
1649
+ /* ==========================================================================
1650
+ Mobile — bottom sheet on small screens
1651
+ At ≤ 640px the popover slides up from the bottom of the viewport
1652
+ regardless of JS-computed position.
1653
+ ========================================================================== */
1654
+ @media (max-width: 640px) {
1655
+ .dds-popover:popover-open {
1656
+ /* Override JS-set position — anchor to bottom of viewport */
1657
+ top: auto !important;
1658
+ left: 0 !important;
1659
+ bottom: 0;
1660
+ width: 100% !important;
1661
+ max-width: 100%;
1662
+ border-radius: var(--dds-popover-radius) var(--dds-popover-radius) 0 0;
1663
+ border-left: none;
1664
+ border-right: none;
1665
+ border-bottom: none;
1666
+ animation: dds-popover-sheet-in 200ms ease forwards;
1667
+ }
1668
+
1669
+ .dds-popover-preview-image-wrap {
1670
+ border-radius: var(--dds-popover-radius) var(--dds-popover-radius) 0 0;
1671
+ }
1672
+ }
1673
+ @keyframes dds-popover-sheet-in {
1674
+ from {
1675
+ opacity: 0;
1676
+ transform: translateY(100%);
1677
+ }
1678
+ to {
1679
+ opacity: 1;
1680
+ transform: translateY(0);
1681
+ }
1682
+ }
1683
+ @starting-style {
1684
+ @media (max-width: 640px) {
1685
+ .dds-popover:popover-open {
1686
+ opacity: 0;
1687
+ transform: translateY(100%);
1688
+ }
1689
+ }
1690
+ }
1412
1691
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@roadlittledawn/docs-design-system-react",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "license": "MIT",
5
5
  "description": "React components for documentation design system",
6
6
  "repository": {