@roadlittledawn/docs-design-system-react 0.11.2 → 0.12.1

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/USAGE.md CHANGED
@@ -132,32 +132,65 @@ import { Card } from "@roadlittledawn/docs-design-system-react";
132
132
  | `titleColor` | `"blue" \| "green" \| "purple" \| "red" \| "yellow" \| "gray"` | `"gray"` | Color of the title text |
133
133
  | `backgroundColor` | `"blue" \| "green" \| "purple" \| "red" \| "yellow" \| "gray" \| "white"` | `"white"` | Background color of the card |
134
134
  | `href` | `string` | — | Optional link URL. When provided, the entire card becomes clickable |
135
+ | `icon` | `ReactNode` | — | Optional icon to display. Pass a rendered icon component. In MDX, the consuming site's component map resolves string names to rendered components before passing here. |
136
+ | `iconPlacement` | `"left" \| "top-left" \| "top-center"` | `"top-left"` | Where to place the icon: vertically centered on the left, above content flush left, or above content centered |
137
+ | `iconSize` | `string` | — | Override the icon container size (width and height). Accepts any valid CSS length (e.g. `"2rem"`, `"48px"`). Defaults to `--dds-card-icon-size` (`1.5rem`). |
138
+ | `showArrow` | `boolean` | `false` | Show an animated arrow in the lower-right corner to signal the card is navigable. Best used with `href`. |
135
139
  | `children` | `ReactNode` | — | Card content |
136
140
  | `className` | `string` | `""` | Additional CSS classes |
137
141
 
138
142
  ### Examples
139
143
 
140
144
  ```tsx
141
- {
142
- /* Basic card */
143
- }
145
+ {/* Basic card */}
144
146
  <Card title="Getting Started">
145
147
  Learn the basics of using this documentation system.
146
- </Card>;
148
+ </Card>
147
149
 
148
- {
149
- /* Clickable card */
150
- }
151
- <Card title="API Reference" href="/docs/api">
152
- Complete reference for all available components.
153
- </Card>;
150
+ {/* Clickable card with animated arrow */}
151
+ <Card title="Get Started" href="/docs/quickstart" showArrow>
152
+ Follow the quickstart guide to set up in minutes.
153
+ </Card>
154
154
 
155
- {
156
- /* Colored background */
157
- }
155
+ {/* Card with icon left (vertically centered beside content) */}
156
+ <Card title="Documentation" icon={<YourIcon />} iconPlacement="left">
157
+ Read guides, tutorials, and API references.
158
+ </Card>
159
+
160
+ {/* Card with icon top-center */}
161
+ <Card title="Documentation" icon={<YourIcon />} iconPlacement="top-center">
162
+ Read guides, tutorials, and API references.
163
+ </Card>
164
+
165
+ {/* Card with custom icon size (48px container) */}
166
+ <Card title="Documentation" icon={<YourIcon />} iconPlacement="top-left" iconSize="3rem">
167
+ Icon container overridden to 48px × 48px.
168
+ </Card>
169
+
170
+ {/* Colored background */}
158
171
  <Card title="New Feature" titleColor="blue" backgroundColor="blue">
159
172
  Check out our latest component additions.
160
- </Card>;
173
+ </Card>
174
+ ```
175
+
176
+ ### Icon usage in MDX
177
+
178
+ In MDX files the `icon` prop is typically a string name (`icon="book"`). The consuming site's MDX component map is responsible for resolving strings to rendered icon components:
179
+
180
+ ```tsx
181
+ // In your MDX components config:
182
+ import { YourBookIcon, YourRocketIcon } from 'your-icon-library';
183
+
184
+ const iconMap: Record<string, React.ComponentType> = {
185
+ book: YourBookIcon,
186
+ rocket: YourRocketIcon,
187
+ };
188
+
189
+ // Wrap Card in your MDX components map:
190
+ Card: ({ icon, ...props }) => {
191
+ const IconComp = typeof icon === 'string' ? iconMap[icon] : null;
192
+ return <DdsCard icon={IconComp ? <IconComp /> : icon} {...props} />;
193
+ }
161
194
  ```
162
195
 
163
196
  ---
@@ -14,9 +14,34 @@ export interface CardProps {
14
14
  backgroundColor?: "blue" | "green" | "purple" | "red" | "yellow" | "gray" | "white";
15
15
  /** Optional link URL. When provided, the entire card becomes clickable */
16
16
  href?: string;
17
+ /**
18
+ * Optional icon to display. Pass a rendered icon component (e.g. `<YourIcon />`).
19
+ * In MDX, the consuming site's component map resolves icon name strings to rendered
20
+ * components before passing them here.
21
+ */
22
+ icon?: ReactNode;
23
+ /**
24
+ * Placement of the icon within the card.
25
+ * - `"left"` — icon centered vertically on the left, title + content on the right
26
+ * - `"top-left"` — icon above title and content, flush left
27
+ * - `"top-center"` — icon above title and content, horizontally centered
28
+ * @default 'top-left'
29
+ */
30
+ iconPlacement?: "left" | "top-left" | "top-center";
31
+ /**
32
+ * Override the icon container size (width and height). Accepts any valid CSS length value (e.g. `"2rem"`, `"48px"`).
33
+ * Defaults to the `--dds-card-icon-size` token (`1.5rem`).
34
+ */
35
+ iconSize?: string;
36
+ /**
37
+ * Show an animated arrow in the lower-right corner to signal the card is navigable.
38
+ * Best used together with `href`. The arrow animates with a springy motion on hover.
39
+ * @default false
40
+ */
41
+ showArrow?: boolean;
17
42
  /** Card content */
18
43
  children: ReactNode;
19
44
  /** Additional CSS classes */
20
45
  className?: string;
21
46
  }
22
- export declare function Card({ title, titleColor, backgroundColor, href, children, className, }: CardProps): import("react/jsx-runtime").JSX.Element;
47
+ export declare function Card({ title, titleColor, backgroundColor, href, icon, iconPlacement, iconSize, showArrow, children, className, }: CardProps): import("react/jsx-runtime").JSX.Element;
@@ -1,10 +1,22 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
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, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
13
  export function Card(_a) {
3
- var title = _a.title, _b = _a.titleColor, titleColor = _b === void 0 ? "gray" : _b, _c = _a.backgroundColor, backgroundColor = _c === void 0 ? "white" : _c, href = _a.href, children = _a.children, _d = _a.className, className = _d === void 0 ? "" : _d;
14
+ var title = _a.title, _b = _a.titleColor, titleColor = _b === void 0 ? "gray" : _b, _c = _a.backgroundColor, backgroundColor = _c === void 0 ? "white" : _c, href = _a.href, icon = _a.icon, _d = _a.iconPlacement, iconPlacement = _d === void 0 ? "top-left" : _d, iconSize = _a.iconSize, _e = _a.showArrow, showArrow = _e === void 0 ? false : _e, children = _a.children, _f = _a.className, className = _f === void 0 ? "" : _f;
4
15
  var cardClasses = [
5
16
  "dds-card",
6
17
  "dds-card-bg-".concat(backgroundColor),
7
18
  href ? "dds-card-clickable" : "",
19
+ showArrow ? "dds-card-has-arrow" : "",
8
20
  className,
9
21
  ]
10
22
  .filter(Boolean)
@@ -13,7 +25,15 @@ export function Card(_a) {
13
25
  var textClasses = backgroundColor !== "white"
14
26
  ? "dds-card-text-".concat(backgroundColor)
15
27
  : "dds-card-text-gray";
16
- var content = (_jsxs("div", { className: cardClasses, children: [title && _jsx("h3", { className: titleClasses, children: title }), _jsx("div", { className: textClasses, children: children })] }));
28
+ var iconEl = icon ? (_jsx("span", { className: [
29
+ "dds-card-icon",
30
+ iconPlacement === "top-center" ? "dds-card-icon-top-center" : "",
31
+ ]
32
+ .filter(Boolean)
33
+ .join(" "), style: __assign({}, (iconSize && { width: iconSize, height: iconSize })), "aria-hidden": "true", children: icon })) : null;
34
+ var arrowEl = showArrow ? (_jsx("span", { className: "dds-card-arrow", "aria-hidden": "true", children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M2 8H14M10 4L14 8L10 12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })) : null;
35
+ var bodyContent = icon && iconPlacement === "left" ? (_jsxs("div", { className: "dds-card-icon-row", children: [iconEl, _jsxs("div", { className: "dds-card-icon-content", children: [title && _jsx("h3", { className: titleClasses, children: title }), _jsx("div", { className: textClasses, children: children })] })] })) : (_jsxs(_Fragment, { children: [iconEl, title && _jsx("h3", { className: titleClasses, children: title }), _jsx("div", { className: textClasses, children: children })] }));
36
+ var content = (_jsxs("div", { className: cardClasses, children: [bodyContent, arrowEl] }));
17
37
  if (href) {
18
38
  return (_jsx("a", { href: href, className: "no-text-decoration", children: content }));
19
39
  }
@@ -14,6 +14,26 @@ export declare const Basic: Story;
14
14
  * Clickable card that links to another page.
15
15
  */
16
16
  export declare const Clickable: Story;
17
+ /**
18
+ * Clickable card with an animated arrow in the lower-right corner. Hover to see the animation.
19
+ */
20
+ export declare const WithArrow: Story;
21
+ /**
22
+ * Card with an icon placed to the left, vertically centered next to the title and content.
23
+ */
24
+ export declare const WithIconLeft: Story;
25
+ /**
26
+ * Card with an icon placed above the title, flush left (the default top placement).
27
+ */
28
+ export declare const WithIconTopLeft: Story;
29
+ /**
30
+ * Card with an icon centered horizontally above the title and content.
31
+ */
32
+ export declare const WithIconTopCenter: Story;
33
+ /**
34
+ * Clickable card combining a left icon and the animated arrow. Hover to see the arrow animate.
35
+ */
36
+ export declare const WithIconAndArrow: Story;
17
37
  /**
18
38
  * Card with colored background.
19
39
  */
@@ -22,6 +42,15 @@ export declare const ColoredBackground: Story;
22
42
  * Card without a title.
23
43
  */
24
44
  export declare const NoTitle: Story;
45
+ /**
46
+ * All icon placement variants side by side.
47
+ */
48
+ export declare const IconPlacements: Story;
49
+ /**
50
+ * Cards with a custom icon size using the `iconSize` prop.
51
+ * Use any valid CSS length value (e.g. `"2rem"`, `"48px"`).
52
+ */
53
+ export declare const WithCustomIconSize: Story;
25
54
  /**
26
55
  * All title color variants.
27
56
  */
@@ -28,6 +28,25 @@ var meta = {
28
28
  control: 'text',
29
29
  description: 'Optional link URL. When provided, the entire card becomes clickable.',
30
30
  },
31
+ icon: {
32
+ control: false,
33
+ description: 'Optional icon to display. Pass a rendered icon component.',
34
+ },
35
+ iconPlacement: {
36
+ control: { type: 'select' },
37
+ options: ['left', 'top-left', 'top-center'],
38
+ description: 'Placement of the icon within the card.',
39
+ table: { defaultValue: { summary: "'top-left'" } },
40
+ },
41
+ iconSize: {
42
+ control: 'text',
43
+ description: 'Override the icon container size (width and height, e.g. "2rem", "48px"). Defaults to the --dds-card-icon-size token (1.5rem).',
44
+ },
45
+ showArrow: {
46
+ control: 'boolean',
47
+ description: 'Show an animated arrow in the lower-right corner to signal the card is navigable.',
48
+ table: { defaultValue: { summary: 'false' } },
49
+ },
31
50
  children: {
32
51
  control: 'text',
33
52
  description: 'Card content.',
@@ -41,12 +60,14 @@ var meta = {
41
60
  parameters: {
42
61
  docs: {
43
62
  description: {
44
- component: "\nThe Card component provides a flexible container for displaying content with visual hierarchy.\n\n## When to Use\n\n- To group related content together\n- To create clickable navigation elements\n- To display feature highlights or key information\n- To organize content in grid layouts\n\n## When Not to Use\n\n- For plain text content (use typography components)\n- For alerts or notifications (use Callout)\n- For extensive content (consider using sections or pages)\n\n## Accessibility\n\n- Clickable cards use proper link semantics\n- Color is not the only means of conveying information\n ",
63
+ component: "\nThe Card component provides a flexible container for displaying content with visual hierarchy.\n\n## When to Use\n\n- To group related content together\n- To create clickable navigation elements (use `href` + `showArrow`)\n- To display feature highlights with icons\n- To organize content in grid layouts\n\n## When Not to Use\n\n- For plain text content (use typography components)\n- For alerts or notifications (use Callout)\n- For extensive content (consider using sections or pages)\n\n## Icon Usage in MDX\n\nIn MDX files, `icon` is typically a string name (e.g. `icon=\"book\"`). The consuming site's\nMDX component map resolves the string to a rendered icon before passing it to Card:\n\n```tsx\n// In your MDX components config:\nCard: ({ icon, ...props }) => {\n const IconComp = typeof icon === 'string' ? iconMap[icon] : null;\n return <DdsCard icon={IconComp ? <IconComp /> : icon} {...props} />;\n}\n```\n\n## Accessibility\n\n- Clickable cards use proper link semantics\n- The arrow and icon are decorative (`aria-hidden`) and do not affect screen reader output\n- Color is not the only means of conveying information\n ",
45
64
  },
46
65
  },
47
66
  },
48
67
  };
49
68
  export default meta;
69
+ /** A simple inline SVG used in stories to simulate a real icon component. */
70
+ var DemoIcon = function () { return (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("path", { d: "M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25" }) })); };
50
71
  /**
51
72
  * Basic card with title and content.
52
73
  */
@@ -80,6 +101,98 @@ export var Clickable = {
80
101
  },
81
102
  },
82
103
  };
104
+ /**
105
+ * Clickable card with an animated arrow in the lower-right corner. Hover to see the animation.
106
+ */
107
+ export var WithArrow = {
108
+ args: {
109
+ title: 'Get Started',
110
+ href: '/docs/quickstart',
111
+ showArrow: true,
112
+ children: 'Follow the quickstart guide to set up in minutes.',
113
+ },
114
+ parameters: {
115
+ docs: {
116
+ source: {
117
+ code: "<Card title=\"Get Started\" href=\"/docs/quickstart\" showArrow>\n Follow the quickstart guide to set up in minutes.\n</Card>",
118
+ },
119
+ },
120
+ },
121
+ };
122
+ /**
123
+ * Card with an icon placed to the left, vertically centered next to the title and content.
124
+ */
125
+ export var WithIconLeft = {
126
+ args: {
127
+ title: 'Documentation',
128
+ icon: _jsx(DemoIcon, {}),
129
+ iconPlacement: 'left',
130
+ children: 'Read guides, tutorials, and API references.',
131
+ },
132
+ parameters: {
133
+ docs: {
134
+ source: {
135
+ code: "// In MDX the consuming site resolves the icon string to a component:\n<Card title=\"Documentation\" icon={<DemoIcon />} iconPlacement=\"left\">\n Read guides, tutorials, and API references.\n</Card>",
136
+ },
137
+ },
138
+ },
139
+ };
140
+ /**
141
+ * Card with an icon placed above the title, flush left (the default top placement).
142
+ */
143
+ export var WithIconTopLeft = {
144
+ args: {
145
+ title: 'Documentation',
146
+ icon: _jsx(DemoIcon, {}),
147
+ iconPlacement: 'top-left',
148
+ children: 'Read guides, tutorials, and API references.',
149
+ },
150
+ parameters: {
151
+ docs: {
152
+ source: {
153
+ code: "<Card title=\"Documentation\" icon={<DemoIcon />} iconPlacement=\"top-left\">\n Read guides, tutorials, and API references.\n</Card>",
154
+ },
155
+ },
156
+ },
157
+ };
158
+ /**
159
+ * Card with an icon centered horizontally above the title and content.
160
+ */
161
+ export var WithIconTopCenter = {
162
+ args: {
163
+ title: 'Documentation',
164
+ icon: _jsx(DemoIcon, {}),
165
+ iconPlacement: 'top-center',
166
+ children: 'Read guides, tutorials, and API references.',
167
+ },
168
+ parameters: {
169
+ docs: {
170
+ source: {
171
+ code: "<Card title=\"Documentation\" icon={<DemoIcon />} iconPlacement=\"top-center\">\n Read guides, tutorials, and API references.\n</Card>",
172
+ },
173
+ },
174
+ },
175
+ };
176
+ /**
177
+ * Clickable card combining a left icon and the animated arrow. Hover to see the arrow animate.
178
+ */
179
+ export var WithIconAndArrow = {
180
+ args: {
181
+ title: 'Get Started',
182
+ href: '/docs/quickstart',
183
+ icon: _jsx(DemoIcon, {}),
184
+ iconPlacement: 'left',
185
+ showArrow: true,
186
+ children: 'Follow the quickstart guide to set up in minutes.',
187
+ },
188
+ parameters: {
189
+ docs: {
190
+ source: {
191
+ code: "<Card title=\"Get Started\" href=\"/docs/quickstart\" icon={<DemoIcon />} iconPlacement=\"left\" showArrow>\n Follow the quickstart guide to set up in minutes.\n</Card>",
192
+ },
193
+ },
194
+ },
195
+ };
83
196
  /**
84
197
  * Card with colored background.
85
198
  */
@@ -113,6 +226,33 @@ export var NoTitle = {
113
226
  },
114
227
  },
115
228
  };
229
+ /**
230
+ * All icon placement variants side by side.
231
+ */
232
+ export var IconPlacements = {
233
+ parameters: {
234
+ docs: {
235
+ source: {
236
+ code: "<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>\n <Card title=\"Icon Left\" icon={<DemoIcon />} iconPlacement=\"left\">\n Icon is centered vertically beside the content.\n </Card>\n <Card title=\"Icon Top Left\" icon={<DemoIcon />} iconPlacement=\"top-left\">\n Icon sits above the title, flush left.\n </Card>\n <Card title=\"Icon Top Center\" icon={<DemoIcon />} iconPlacement=\"top-center\">\n Icon sits above the title, horizontally centered.\n </Card>\n</div>",
237
+ },
238
+ },
239
+ },
240
+ render: function () { return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '1rem' }, children: [_jsx(Card, { title: "Icon Left", icon: _jsx(DemoIcon, {}), iconPlacement: "left", children: _jsx("span", { style: { color: 'var(--dds-card-text-gray)' }, children: "Icon is centered vertically beside the content." }) }), _jsx(Card, { title: "Icon Top Left", icon: _jsx(DemoIcon, {}), iconPlacement: "top-left", children: _jsx("span", { style: { color: 'var(--dds-card-text-gray)' }, children: "Icon sits above the title, flush left." }) }), _jsx(Card, { title: "Icon Top Center", icon: _jsx(DemoIcon, {}), iconPlacement: "top-center", children: _jsx("span", { style: { color: 'var(--dds-card-text-gray)' }, children: "Icon sits above the title, horizontally centered." }) })] })); },
241
+ };
242
+ /**
243
+ * Cards with a custom icon size using the `iconSize` prop.
244
+ * Use any valid CSS length value (e.g. `"2rem"`, `"48px"`).
245
+ */
246
+ export var WithCustomIconSize = {
247
+ parameters: {
248
+ docs: {
249
+ source: {
250
+ code: "{/* 48px icon container */}\n<Card title=\"Large Icon\" icon={<YourIcon />} iconPlacement=\"top-left\" iconSize=\"3rem\">\n Icon container is 48px \u00D7 48px (3rem).\n</Card>\n\n{/* 16px icon container */}\n<Card title=\"Small Icon\" icon={<YourIcon />} iconPlacement=\"left\" iconSize=\"1rem\">\n Icon container is 16px \u00D7 16px (1rem).\n</Card>",
251
+ },
252
+ },
253
+ },
254
+ render: function () { return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '1rem' }, children: [_jsx(Card, { title: "Large Icon", icon: _jsx(DemoIcon, {}), iconPlacement: "top-left", iconSize: "3rem", children: _jsx("span", { style: { color: 'var(--dds-card-text-gray)' }, children: "Icon container is 48px \u00D7 48px (3rem)." }) }), _jsx(Card, { title: "Small Icon", icon: _jsx(DemoIcon, {}), iconPlacement: "left", iconSize: "1rem", children: _jsx("span", { style: { color: 'var(--dds-card-text-gray)' }, children: "Icon container is 16px \u00D7 16px (1rem)." }) })] })); },
255
+ };
116
256
  /**
117
257
  * All title color variants.
118
258
  */
package/dist/styles.css CHANGED
@@ -45,6 +45,13 @@
45
45
  --dds-card-text-yellow: #854d0e; /* yellow-800 */
46
46
  --dds-card-text-gray: #374151; /* gray-700 */
47
47
 
48
+ --dds-card-icon-size: 1.5rem; /* 24px */
49
+ --dds-card-icon-color: #6b7280; /* gray-500 */
50
+ --dds-card-icon-margin-bottom: 0.75rem;
51
+ --dds-card-icon-gap: 1rem;
52
+ --dds-card-arrow-color: #9ca3af; /* gray-400 */
53
+ --dds-card-arrow-inset: 0.75rem;
54
+
48
55
  /* Typography - Font Sizes */
49
56
  --dds-heading-1-size: 2.25rem; /* text-4xl */
50
57
  --dds-heading-2-size: 1.875rem; /* text-3xl */
@@ -359,6 +366,9 @@
359
366
  --dds-card-text-yellow: #fef08a; /* yellow-200 */
360
367
  --dds-card-text-gray: #d1d5db; /* gray-300 */
361
368
 
369
+ --dds-card-icon-color: #9ca3af; /* gray-400 */
370
+ --dds-card-arrow-color: #6b7280; /* gray-500 */
371
+
362
372
  /* Link */
363
373
  --dds-link-color: #60a5fa; /* blue-400 */
364
374
  --dds-link-color-hover: #93c5fd; /* blue-300 */
@@ -541,6 +551,9 @@
541
551
  --dds-card-text-yellow: #fef08a;
542
552
  --dds-card-text-gray: #d1d5db;
543
553
 
554
+ --dds-card-icon-color: #9ca3af; /* gray-400 */
555
+ --dds-card-arrow-color: #6b7280; /* gray-500 */
556
+
544
557
  /* Link */
545
558
  --dds-link-color: #60a5fa;
546
559
  --dds-link-color-hover: #93c5fd;
@@ -723,6 +736,9 @@
723
736
  --dds-card-text-yellow: #fef08a;
724
737
  --dds-card-text-gray: #d1d5db;
725
738
 
739
+ --dds-card-icon-color: #9ca3af; /* gray-400 */
740
+ --dds-card-arrow-color: #6b7280; /* gray-500 */
741
+
726
742
  /* Link */
727
743
  --dds-link-color: #60a5fa;
728
744
  --dds-link-color-hover: #93c5fd;
@@ -1085,6 +1101,7 @@ a.no-text-decoration {
1085
1101
  padding: var(--dds-card-padding);
1086
1102
  border-radius: var(--dds-card-radius);
1087
1103
  border: 1px solid var(--dds-card-border);
1104
+ position: relative;
1088
1105
  }
1089
1106
  .dds-card-clickable {
1090
1107
  cursor: pointer;
@@ -1143,6 +1160,77 @@ a.no-text-decoration {
1143
1160
  .dds-card-title-gray {
1144
1161
  color: var(--dds-card-title-gray);
1145
1162
  }
1163
+ /* Icon */
1164
+ .dds-card-icon {
1165
+ display: block;
1166
+ width: var(--dds-card-icon-size);
1167
+ height: var(--dds-card-icon-size);
1168
+ color: var(--dds-card-icon-color);
1169
+ flex-shrink: 0;
1170
+ margin-bottom: var(--dds-card-icon-margin-bottom);
1171
+ }
1172
+ .dds-card-icon > * {
1173
+ width: 100%;
1174
+ height: 100%;
1175
+ }
1176
+ .dds-card-icon-top-center {
1177
+ margin-left: auto;
1178
+ margin-right: auto;
1179
+ }
1180
+ /* Icon-left layout */
1181
+ .dds-card-icon-row {
1182
+ display: flex;
1183
+ align-items: center;
1184
+ gap: var(--dds-card-icon-gap);
1185
+ }
1186
+ .dds-card-icon-row .dds-card-icon {
1187
+ margin-bottom: 0;
1188
+ }
1189
+ .dds-card-icon-content {
1190
+ flex: 1;
1191
+ min-width: 0;
1192
+ }
1193
+ /* Arrow */
1194
+ .dds-card-has-arrow {
1195
+ padding-right: calc(var(--dds-card-padding) + 1.25rem);
1196
+ }
1197
+ [dir="rtl"] .dds-card-has-arrow {
1198
+ padding-right: var(--dds-card-padding);
1199
+ padding-left: calc(var(--dds-card-padding) + 1.25rem);
1200
+ }
1201
+ .dds-card-arrow {
1202
+ position: absolute;
1203
+ bottom: var(--dds-card-arrow-inset);
1204
+ right: var(--dds-card-arrow-inset);
1205
+ color: var(--dds-card-arrow-color);
1206
+ display: flex;
1207
+ align-items: center;
1208
+ justify-content: center;
1209
+ pointer-events: none;
1210
+ }
1211
+ [dir="rtl"] .dds-card-arrow {
1212
+ right: auto;
1213
+ left: var(--dds-card-arrow-inset);
1214
+ transform: scaleX(-1);
1215
+ }
1216
+ @keyframes dds-arrow-nudge {
1217
+ 0% { transform: translateX(0); }
1218
+ 40% { transform: translateX(5px); }
1219
+ 70% { transform: translateX(-2px); }
1220
+ 100% { transform: translateX(0); }
1221
+ }
1222
+ @keyframes dds-arrow-nudge-rtl {
1223
+ 0% { transform: scaleX(-1) translateX(0); }
1224
+ 40% { transform: scaleX(-1) translateX(5px); }
1225
+ 70% { transform: scaleX(-1) translateX(-2px); }
1226
+ 100% { transform: scaleX(-1) translateX(0); }
1227
+ }
1228
+ .dds-card-clickable:hover .dds-card-arrow {
1229
+ animation: dds-arrow-nudge 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
1230
+ }
1231
+ [dir="rtl"] .dds-card-clickable:hover .dds-card-arrow {
1232
+ animation: dds-arrow-nudge-rtl 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
1233
+ }
1146
1234
  /* Text color variants */
1147
1235
  .dds-card-text-blue {
1148
1236
  color: var(--dds-card-text-blue);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@roadlittledawn/docs-design-system-react",
3
- "version": "0.11.2",
3
+ "version": "0.12.1",
4
4
  "license": "MIT",
5
5
  "description": "React components for documentation design system",
6
6
  "repository": {