lucent-ui 0.14.2 → 0.15.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/dist/index.cjs +76 -54
- package/dist/index.d.ts +26 -6
- package/dist/index.js +2261 -1995
- package/dist-server/src/components/molecules/Card/Card.manifest.js +194 -29
- package/package.json +1 -1
|
@@ -4,21 +4,64 @@ export const COMPONENT_MANIFEST = {
|
|
|
4
4
|
tier: 'molecule',
|
|
5
5
|
domain: 'neutral',
|
|
6
6
|
specVersion: '0.1',
|
|
7
|
-
description: 'A surface container with
|
|
8
|
-
|
|
9
|
-
'
|
|
10
|
-
|
|
11
|
-
'
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
'those
|
|
19
|
-
'
|
|
20
|
-
'
|
|
7
|
+
description: 'A surface container with five elevation variants that form a visual importance hierarchy. ' +
|
|
8
|
+
'Supports optional header, body, and footer slots with configurable padding, shadow, and radius. ' +
|
|
9
|
+
'Includes a CardBleed sub-component for edge-to-edge content.',
|
|
10
|
+
designIntent: 'Card provides a configurable surface with an explicit elevation hierarchy. Each variant maps to ' +
|
|
11
|
+
'a distinct level of visual prominence, giving consumers a single prop to express how much attention ' +
|
|
12
|
+
'a surface should command relative to its surroundings.\n\n' +
|
|
13
|
+
'## Elevation hierarchy (lowest → highest)\n\n' +
|
|
14
|
+
'1. **ghost** — transparent background, no border, no shadow.\n' +
|
|
15
|
+
' The card is invisible as a container — content floats directly against the page or parent surface. ' +
|
|
16
|
+
'Use for logical groupings that shouldn\'t compete visually: sidebar sections, form regions, or ' +
|
|
17
|
+
'layout slots where structure exists conceptually but not visually. Header/footer dividers still ' +
|
|
18
|
+
'render if those slots are used, providing minimal internal structure.\n\n' +
|
|
19
|
+
'2. **outline** (default) — transparent background with `border-default` border, no shadow.\n' +
|
|
20
|
+
' Like ghost, the card inherits its container\'s background — the border alone defines the boundary. ' +
|
|
21
|
+
'This is the workhorse variant for lists of items, form sections, data panels, ' +
|
|
22
|
+
'and any content that needs a visible container without drawing excessive attention. Header and footer ' +
|
|
23
|
+
'slots are separated from the body by matching `border-default` dividers.\n\n' +
|
|
24
|
+
'3. **filled** — semi-transparent tinted background, no border, no shadow.\n' +
|
|
25
|
+
' Differentiates the card from its surroundings by darkening (light mode) or lightening (dark mode) ' +
|
|
26
|
+
'whatever surface it sits on. Uses `color-mix(in srgb, textPrimary 6%, transparent)` so the tint is ' +
|
|
27
|
+
'always relative to the container — never a fixed color. Use for secondary content areas, inset panels, ' +
|
|
28
|
+
'summary blocks, or anywhere a border would feel heavy but the card needs to be visually distinct. ' +
|
|
29
|
+
'Effective for nesting (e.g., a filled card inside an elevated card creates a recessed region).\n\n' +
|
|
30
|
+
'4. **elevated** — `surface` background with medium shadow, no border.\n' +
|
|
31
|
+
' The card lifts off the page through depth. The shadow creates a physical metaphor: this content ' +
|
|
32
|
+
'sits above the surface it rests on. Use for primary content areas, feature highlights, pricing cards, ' +
|
|
33
|
+
'or any surface that should feel physically elevated. The lack of border keeps the silhouette soft — ' +
|
|
34
|
+
'the shadow alone defines the boundary.\n\n' +
|
|
35
|
+
'5. **combo** — transparent wrapper with an elevated body inset.\n' +
|
|
36
|
+
' The header and footer are flat — they blend into the page background as if they were part of it. ' +
|
|
37
|
+
'Only the body section is elevated: it gets `surface` background, border-radius, and shadow, appearing ' +
|
|
38
|
+
'as a raised card sitting between the flat header/footer regions. This draws the eye to the primary ' +
|
|
39
|
+
'content while keeping supporting info (header) and actions (footer) visually subordinate — they frame ' +
|
|
40
|
+
'the elevated body without competing with it. No dividers are rendered — the elevation change IS the ' +
|
|
41
|
+
'visual separator. Use for detail panels, profile cards, or settings forms where the body content is ' +
|
|
42
|
+
'the focal point.\n\n' +
|
|
43
|
+
'## Shadow override\n' +
|
|
44
|
+
'The `shadow` prop overrides whatever shadow the variant implies. This allows fine-tuning without ' +
|
|
45
|
+
'changing the variant. For example, `variant="elevated" shadow="lg"` gives an elevated card with extra ' +
|
|
46
|
+
'depth, while `variant="outline" shadow="none"` gives a flat bordered card.\n\n' +
|
|
47
|
+
'## Token rules\n' +
|
|
48
|
+
'- `elevated` and `combo` body use `surface` (the primary component surface — white in light mode).\n' +
|
|
49
|
+
'- `filled` uses a semi-transparent tint of `textPrimary` — contextually darker/lighter than its container.\n' +
|
|
50
|
+
'- `combo` wrapper is transparent (header/footer blend with page); only the body is elevated with `surface`.\n' +
|
|
51
|
+
'- `ghost` and `outline` use `transparent` — they inherit from whatever they\'re placed on. ' +
|
|
52
|
+
'The border is the only visual differentiator for `outline`.\n' +
|
|
53
|
+
'- Never use `bgBase` or `bgSubtle` on a Card — those tokens are reserved for the page canvas.\n' +
|
|
54
|
+
'- Content nested inside a Card that needs a tinted fill should use `surfaceSecondary`.',
|
|
21
55
|
props: [
|
|
56
|
+
{
|
|
57
|
+
name: 'variant',
|
|
58
|
+
type: 'enum',
|
|
59
|
+
required: false,
|
|
60
|
+
default: 'outline',
|
|
61
|
+
description: 'The elevation variant. Controls background color, border, and default shadow. ' +
|
|
62
|
+
'Ordered from lowest to highest visual prominence: ghost → outline → filled → elevated → combo.',
|
|
63
|
+
enumValues: ['ghost', 'outline', 'filled', 'elevated', 'combo'],
|
|
64
|
+
},
|
|
22
65
|
{
|
|
23
66
|
name: 'children',
|
|
24
67
|
type: 'ReactNode',
|
|
@@ -29,13 +72,15 @@ export const COMPONENT_MANIFEST = {
|
|
|
29
72
|
name: 'header',
|
|
30
73
|
type: 'ReactNode',
|
|
31
74
|
required: false,
|
|
32
|
-
description: 'Content rendered in the header slot
|
|
75
|
+
description: 'Content rendered in the header slot. Separated from the body by a divider in all variants except combo, ' +
|
|
76
|
+
'where the background-color change provides the separation.',
|
|
33
77
|
},
|
|
34
78
|
{
|
|
35
79
|
name: 'footer',
|
|
36
80
|
type: 'ReactNode',
|
|
37
81
|
required: false,
|
|
38
|
-
description: 'Content rendered in the footer slot
|
|
82
|
+
description: 'Content rendered in the footer slot. Separated from the body by a divider in all variants except combo, ' +
|
|
83
|
+
'where the background-color change provides the separation.',
|
|
39
84
|
},
|
|
40
85
|
{
|
|
41
86
|
name: 'padding',
|
|
@@ -49,8 +94,8 @@ export const COMPONENT_MANIFEST = {
|
|
|
49
94
|
name: 'shadow',
|
|
50
95
|
type: 'enum',
|
|
51
96
|
required: false,
|
|
52
|
-
|
|
53
|
-
|
|
97
|
+
description: 'Box shadow elevation. When omitted, uses the variant\'s default: ghost=none, outline=none, filled=none, elevated=md, combo=md. ' +
|
|
98
|
+
'When set explicitly, overrides the variant\'s default.',
|
|
54
99
|
enumValues: ['none', 'sm', 'md', 'lg'],
|
|
55
100
|
},
|
|
56
101
|
{
|
|
@@ -67,27 +112,102 @@ export const COMPONENT_MANIFEST = {
|
|
|
67
112
|
required: false,
|
|
68
113
|
description: 'Inline style overrides for the card wrapper.',
|
|
69
114
|
},
|
|
115
|
+
{
|
|
116
|
+
name: 'onClick',
|
|
117
|
+
type: 'function',
|
|
118
|
+
required: false,
|
|
119
|
+
description: 'Click handler. When provided, the card renders as a <button> with hover lift, focus ring, ' +
|
|
120
|
+
'and active press states matching the Button component.',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: 'href',
|
|
124
|
+
type: 'string',
|
|
125
|
+
required: false,
|
|
126
|
+
description: 'Link URL. When provided, the card renders as an <a>. Takes precedence over onClick for the element type, ' +
|
|
127
|
+
'but onClick is still attached as a handler.',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: 'target',
|
|
131
|
+
type: 'string',
|
|
132
|
+
required: false,
|
|
133
|
+
description: 'Passed to <a> when href is set (e.g. "_blank").',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: 'rel',
|
|
137
|
+
type: 'string',
|
|
138
|
+
required: false,
|
|
139
|
+
description: 'Passed to <a> when href is set (e.g. "noopener noreferrer").',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: 'disabled',
|
|
143
|
+
type: 'boolean',
|
|
144
|
+
required: false,
|
|
145
|
+
description: 'Disables interactive behavior. Reduces opacity, removes hover/focus/active states, ' +
|
|
146
|
+
'and sets cursor to not-allowed. Only applies when onClick or href is set.',
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'status',
|
|
150
|
+
type: 'enum',
|
|
151
|
+
required: false,
|
|
152
|
+
description: 'Adds a 3px colored accent bar on the left edge of the card. Uses the corresponding status ' +
|
|
153
|
+
'token (successDefault, warningDefault, dangerDefault, infoDefault). Works with all variants.',
|
|
154
|
+
enumValues: ['success', 'warning', 'danger', 'info'],
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: 'selected',
|
|
158
|
+
type: 'boolean',
|
|
159
|
+
required: false,
|
|
160
|
+
description: 'Adds an inset accent ring and subtle background tint to indicate selection. Used for card grids ' +
|
|
161
|
+
'where cards act as radio/checkbox options. Pairs with onClick for toggle behavior. ' +
|
|
162
|
+
'Sets aria-pressed on interactive cards. Disabled takes precedence — ring is hidden when disabled.',
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: 'media',
|
|
166
|
+
type: 'ReactNode',
|
|
167
|
+
required: false,
|
|
168
|
+
description: 'Full-bleed content rendered at the top of the card (before header). No padding is applied. ' +
|
|
169
|
+
'Use for hero images, illustrations, or any edge-to-edge top content. The card\'s overflow:hidden ' +
|
|
170
|
+
'clips media to the border-radius.',
|
|
171
|
+
},
|
|
70
172
|
],
|
|
71
173
|
usageExamples: [
|
|
72
174
|
{
|
|
73
|
-
title: '
|
|
74
|
-
code: `<Card>
|
|
75
|
-
<Text>
|
|
175
|
+
title: 'Ghost — invisible container',
|
|
176
|
+
code: `<Card variant="ghost">
|
|
177
|
+
<Text>Content sits directly on the page background.</Text>
|
|
76
178
|
</Card>`,
|
|
77
179
|
},
|
|
78
180
|
{
|
|
79
|
-
title: '
|
|
181
|
+
title: 'Outline — bordered card (default)',
|
|
80
182
|
code: `<Card
|
|
81
183
|
header={<Text weight="semibold">Card title</Text>}
|
|
82
184
|
footer={<Button variant="primary">Save</Button>}
|
|
83
185
|
>
|
|
84
|
-
<Text color="secondary">
|
|
186
|
+
<Text color="secondary">The standard card treatment with dividers.</Text>
|
|
187
|
+
</Card>`,
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
title: 'Filled — color-differentiated region',
|
|
191
|
+
code: `<Card variant="filled" padding="lg">
|
|
192
|
+
<Text weight="semibold">Summary</Text>
|
|
193
|
+
<Text color="secondary" size="sm">A tinted panel that stands out through background color alone.</Text>
|
|
85
194
|
</Card>`,
|
|
86
195
|
},
|
|
87
196
|
{
|
|
88
|
-
title: '
|
|
89
|
-
code: `<Card
|
|
90
|
-
<Text
|
|
197
|
+
title: 'Elevated — shadow-lifted surface',
|
|
198
|
+
code: `<Card variant="elevated">
|
|
199
|
+
<Text weight="semibold">Featured</Text>
|
|
200
|
+
<Text color="secondary">This card floats above the page with shadow depth.</Text>
|
|
201
|
+
</Card>`,
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
title: 'Combo — two-tone card with header and footer',
|
|
205
|
+
code: `<Card
|
|
206
|
+
variant="combo"
|
|
207
|
+
header={<Text weight="semibold">Profile</Text>}
|
|
208
|
+
footer={<Button variant="primary">Update</Button>}
|
|
209
|
+
>
|
|
210
|
+
<Text>The bright body is framed by the muted header and footer.</Text>
|
|
91
211
|
</Card>`,
|
|
92
212
|
},
|
|
93
213
|
{
|
|
@@ -97,13 +217,58 @@ export const COMPONENT_MANIFEST = {
|
|
|
97
217
|
<CardBleed style={{ borderTop: '1px solid var(--lucent-border-default)', marginTop: 'var(--lucent-space-4)' }}>
|
|
98
218
|
<Text color="secondary">This section stretches to the card edges.</Text>
|
|
99
219
|
</CardBleed>
|
|
220
|
+
</Card>`,
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
title: 'Clickable card',
|
|
224
|
+
code: `<Card variant="elevated" onClick={() => navigate('/detail')}>
|
|
225
|
+
<Text weight="semibold">Dashboard tile</Text>
|
|
226
|
+
<Text color="secondary" size="sm">Click to view details</Text>
|
|
227
|
+
</Card>`,
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
title: 'Link card',
|
|
231
|
+
code: `<Card variant="elevated" href="/docs/getting-started" target="_blank" rel="noopener noreferrer">
|
|
232
|
+
<Text weight="semibold">Documentation</Text>
|
|
233
|
+
<Text color="secondary" size="sm">Opens in a new tab</Text>
|
|
234
|
+
</Card>`,
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
title: 'Status accent',
|
|
238
|
+
code: `<Card status="danger">
|
|
239
|
+
<Text weight="semibold">Payment failed</Text>
|
|
240
|
+
<Text color="secondary" size="sm">Check your card details and try again.</Text>
|
|
241
|
+
</Card>`,
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
title: 'Selectable card',
|
|
245
|
+
code: `<Card
|
|
246
|
+
variant="elevated"
|
|
247
|
+
selected={isSelected}
|
|
248
|
+
onClick={() => setIsSelected(!isSelected)}
|
|
249
|
+
>
|
|
250
|
+
<Text weight="semibold">Pro plan</Text>
|
|
251
|
+
<Text color="secondary" size="sm">$29/month</Text>
|
|
252
|
+
</Card>`,
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
title: 'Media card with hero image',
|
|
256
|
+
code: `<Card
|
|
257
|
+
variant="elevated"
|
|
258
|
+
media={<img src="/hero.jpg" alt="Hero" style={{ width: '100%', display: 'block' }} />}
|
|
259
|
+
>
|
|
260
|
+
<Text weight="semibold">Article title</Text>
|
|
261
|
+
<Text color="secondary" size="sm">A card with a full-bleed hero image.</Text>
|
|
100
262
|
</Card>`,
|
|
101
263
|
},
|
|
102
264
|
],
|
|
103
265
|
compositionGraph: [],
|
|
104
266
|
accessibility: {
|
|
105
|
-
notes: '
|
|
106
|
-
'
|
|
107
|
-
'
|
|
267
|
+
notes: 'Non-interactive cards have no implicit ARIA role — wrap in <section> or <article> if needed. ' +
|
|
268
|
+
'Interactive cards with onClick render as <button> with focus ring. ' +
|
|
269
|
+
'Interactive cards with href render as <a> with focus ring. ' +
|
|
270
|
+
'Selected cards set aria-pressed on the interactive element. ' +
|
|
271
|
+
'The status accent bar is aria-hidden (decorative). ' +
|
|
272
|
+
'Media slot images should include alt text.',
|
|
108
273
|
},
|
|
109
274
|
};
|