@lumaui/angular 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.
@@ -0,0 +1,452 @@
1
+ ---
2
+ name: Card
3
+ type: component
4
+ selector: luma-card
5
+ category: Layout
6
+ description: Flexible, composable container for grouping related content with multiple visual variants following Neo-Minimal design principles.
7
+ inputs:
8
+ - name: lmVariant
9
+ type: "'default' | 'shadow' | 'nested' | 'preview'"
10
+ default: "'default'"
11
+ description: Card visual style variant
12
+ directives:
13
+ - name: lumaCardHeader
14
+ selector: '[lumaCardHeader]'
15
+ description: Container for card header content (title and description)
16
+ - name: lumaCardTitle
17
+ selector: '[lumaCardTitle]'
18
+ description: Card title with customizable size
19
+ inputs:
20
+ - name: lmSize
21
+ type: "'small' | 'normal' | 'large'"
22
+ default: "'normal'"
23
+ description: Title size variant
24
+ - name: lumaCardDescription
25
+ selector: '[lumaCardDescription]'
26
+ description: Card description text with customizable size
27
+ inputs:
28
+ - name: lmSize
29
+ type: "'small' | 'normal' | 'large'"
30
+ default: "'normal'"
31
+ description: Description size variant
32
+ - name: lumaCardContent
33
+ selector: '[lumaCardContent]'
34
+ description: Container for card main content
35
+ tokens:
36
+ # Legacy (gradient)
37
+ - name: --luma-card-background
38
+ value: oklch(1 0 0)
39
+ description: Legacy card background color
40
+ - name: --luma-card-gradient-from
41
+ value: oklch(0.92 0.005 0 / 0.6)
42
+ description: Gradient border start color
43
+ - name: --luma-card-gradient-to
44
+ value: oklch(0.96 0.003 0 / 0.6)
45
+ description: Gradient border end color
46
+ - name: --luma-card-padding
47
+ value: 1.5rem
48
+ description: Card internal padding
49
+ - name: --luma-card-box-shadow
50
+ value: 0px 2px 0 0px #e4e4e4
51
+ description: Legacy card shadow
52
+ # Shadow variant
53
+ - name: --luma-card-shadow-background
54
+ value: oklch(1 0 0)
55
+ description: Shadow card background
56
+ - name: --luma-card-shadow-border
57
+ value: oklch(0.92 0.008 265)
58
+ description: Shadow card border
59
+ - name: --luma-card-shadow-shadow
60
+ value: 0 8px 24px oklch(0.22 0.01 265 / 0.06)
61
+ description: Shadow card shadow
62
+ - name: --luma-card-shadow-radius
63
+ value: 16px
64
+ description: Shadow card border radius
65
+ # Nested variant
66
+ - name: --luma-card-nested-background
67
+ value: oklch(0.98 0.005 265)
68
+ description: Nested card background
69
+ - name: --luma-card-nested-border
70
+ value: oklch(0.92 0.008 265)
71
+ description: Nested card border
72
+ - name: --luma-card-nested-radius
73
+ value: 12px
74
+ description: Nested card border radius
75
+ # Preview variant
76
+ - name: --luma-card-preview-background
77
+ value: oklch(0.98 0.005 265)
78
+ description: Preview card background
79
+ - name: --luma-card-preview-border
80
+ value: oklch(0.92 0.008 265)
81
+ description: Preview card border
82
+ - name: --luma-card-preview-radius
83
+ value: 12px
84
+ description: Preview card border radius
85
+ ---
86
+
87
+ # Card
88
+
89
+ ## Purpose
90
+
91
+ The Card component provides a flexible, composable container for grouping related content with multiple visual variants that follow Neo-Minimal design principles. Built using a compositional architecture with semantic directives.
92
+
93
+ ## Architecture
94
+
95
+ The Card uses a **compositional design** with a main component and four semantic directives:
96
+
97
+ - `<luma-card>`: Main container with configurable visual variant
98
+ - `[lumaCardHeader]`: Structural directive for header region with spacing
99
+ - `[lumaCardTitle]`: Title with size variants
100
+ - `[lumaCardDescription]`: Subtitle/description with size variants
101
+ - `[lumaCardContent]`: Semantic marker for main content region
102
+
103
+ ## Component API
104
+
105
+ ### CardComponent
106
+
107
+ - `lmVariant`: 'default' | 'shadow' | 'nested' | 'preview' - Card visual style
108
+ - **default**: Gradient border wrapper style (default)
109
+ - **shadow**: Elevated card with subtle shadow for primary content
110
+ - **nested**: Subtle background for sections within cards
111
+ - **preview**: For documentation examples and code previews
112
+
113
+ ### CardTitleDirective
114
+
115
+ - `lmSize`: 'small' | 'normal' | 'large' - Title size variant
116
+ - **small**: `text-sm` - Compact cards or secondary information
117
+ - **normal**: `text-lg` (default) - Standard card titles
118
+ - **large**: `text-2xl` - Hero cards or primary emphasis
119
+
120
+ ### CardDescriptionDirective
121
+
122
+ - `lmSize`: 'small' | 'normal' | 'large' - Description size variant
123
+ - **small**: `text-xs` - Compact cards or tertiary information
124
+ - **normal**: `text-sm` (default) - Standard descriptions
125
+ - **large**: `text-base` - Emphasis or standalone descriptions
126
+
127
+ ### CardHeaderDirective
128
+
129
+ No inputs - provides structural spacing (`mb-4`).
130
+
131
+ ### CardContentDirective
132
+
133
+ No inputs - semantic marker with no styles applied for maximum flexibility.
134
+
135
+ ## Card Variants
136
+
137
+ The Card component supports four visual variants via the `lmVariant` input:
138
+
139
+ ### Default
140
+
141
+ Gradient border wrapper style with distinctive "light as structure" effect (default):
142
+
143
+ ```html
144
+ <luma-card>
145
+ <div lumaCardHeader>
146
+ <h3 lumaCardTitle>Gradient Card</h3>
147
+ <p lumaCardDescription>Default card with gradient border</p>
148
+ </div>
149
+ <div lumaCardContent>
150
+ <p>Content with gradient wrapper styling.</p>
151
+ </div>
152
+ </luma-card>
153
+ ```
154
+
155
+ ### Shadow
156
+
157
+ Elevated card with shadow, ideal for primary content areas and main UI elements:
158
+
159
+ ```html
160
+ <luma-card lmVariant="shadow">
161
+ <div lumaCardHeader>
162
+ <h3 lumaCardTitle>Shadow Card</h3>
163
+ <p lumaCardDescription>Elevated card with subtle shadow</p>
164
+ </div>
165
+ <div lumaCardContent>
166
+ <p>Primary content with clean, elevated appearance.</p>
167
+ </div>
168
+ </luma-card>
169
+ ```
170
+
171
+ ### Nested
172
+
173
+ Subtle background for sections within other containers or cards:
174
+
175
+ ```html
176
+ <luma-card lmVariant="shadow">
177
+ <div lumaCardHeader>
178
+ <h3 lumaCardTitle>Parent Card</h3>
179
+ </div>
180
+ <div lumaCardContent>
181
+ <!-- Nested card inside -->
182
+ <luma-card lmVariant="nested">
183
+ <div lumaCardContent>
184
+ <p>Nested content with subtle differentiation.</p>
185
+ </div>
186
+ </luma-card>
187
+ </div>
188
+ </luma-card>
189
+ ```
190
+
191
+ ### Preview
192
+
193
+ For documentation examples, code showcases, and component previews:
194
+
195
+ ```html
196
+ <luma-card lmVariant="preview">
197
+ <div lumaCardContent>
198
+ <div class="flex items-center justify-center p-8">
199
+ <!-- Component preview -->
200
+ <button lumaButton lmVariant="primary">Preview Button</button>
201
+ </div>
202
+ </div>
203
+ </luma-card>
204
+ ```
205
+
206
+ ## Usage Examples
207
+
208
+ ### Basic Card
209
+
210
+ ```html
211
+ <luma-card>
212
+ <div lumaCardHeader>
213
+ <h3 lumaCardTitle>Card Title</h3>
214
+ <p lumaCardDescription>This is a description of the card content.</p>
215
+ </div>
216
+ <div lumaCardContent>
217
+ <p>Main content goes here.</p>
218
+ </div>
219
+ </luma-card>
220
+ ```
221
+
222
+ ### Stats Card
223
+
224
+ ```html
225
+ <luma-card lmVariant="shadow">
226
+ <div lumaCardHeader>
227
+ <h3 lumaCardTitle lmSize="small">Total Revenue</h3>
228
+ </div>
229
+ <div lumaCardContent>
230
+ <p class="text-3xl font-bold">$45,231.89</p>
231
+ <p class="text-xs lm-text-secondary">+20.1% from last month</p>
232
+ </div>
233
+ </luma-card>
234
+ ```
235
+
236
+ ### Minimal Card (No Header)
237
+
238
+ ```html
239
+ <luma-card lmVariant="nested">
240
+ <div lumaCardContent>
241
+ <p>Simple content without header or title.</p>
242
+ </div>
243
+ </luma-card>
244
+ ```
245
+
246
+ ### Card with Custom Content
247
+
248
+ ```html
249
+ <luma-card lmVariant="shadow">
250
+ <div lumaCardHeader>
251
+ <h3 lumaCardTitle>User Profile</h3>
252
+ <p lumaCardDescription>Manage your account settings</p>
253
+ </div>
254
+ <div lumaCardContent>
255
+ <div class="flex items-center gap-4">
256
+ <img src="avatar.jpg" alt="Avatar" class="w-12 h-12 rounded-full" />
257
+ <div>
258
+ <p class="font-medium">John Doe</p>
259
+ <p class="text-sm lm-text-secondary">john@example.com</p>
260
+ </div>
261
+ </div>
262
+ </div>
263
+ </luma-card>
264
+ ```
265
+
266
+ ### Dashboard Layout with Mixed Variants
267
+
268
+ ```html
269
+ <!-- Main content card -->
270
+ <luma-card lmVariant="shadow">
271
+ <div lumaCardHeader>
272
+ <h2 lumaCardTitle lmSize="large">Dashboard</h2>
273
+ </div>
274
+ <div lumaCardContent>
275
+ <div class="grid grid-cols-3 gap-4">
276
+ <!-- Nested stat cards -->
277
+ <luma-card lmVariant="nested">
278
+ <div lumaCardContent>
279
+ <p class="text-xs lm-text-secondary">Users</p>
280
+ <p class="text-2xl font-bold">1,234</p>
281
+ </div>
282
+ </luma-card>
283
+ <luma-card lmVariant="nested">
284
+ <div lumaCardContent>
285
+ <p class="text-xs lm-text-secondary">Revenue</p>
286
+ <p class="text-2xl font-bold">$12.5k</p>
287
+ </div>
288
+ </luma-card>
289
+ <luma-card lmVariant="nested">
290
+ <div lumaCardContent>
291
+ <p class="text-xs lm-text-secondary">Growth</p>
292
+ <p class="text-2xl font-bold">+15%</p>
293
+ </div>
294
+ </luma-card>
295
+ </div>
296
+ </div>
297
+ </luma-card>
298
+ ```
299
+
300
+ ## Gradient Border Technique
301
+
302
+ The **default** variant uses a distinctive gradient border technique that aligns with Neo-Minimal principles:
303
+
304
+ **How it works:**
305
+
306
+ 1. Outer wrapper has `p-[1px]` padding + `bg-gradient-to-b` gradient
307
+ 2. Inner content has matching border-radius (slightly smaller for visual precision)
308
+ 3. Gradient creates a subtle "light as structure" effect instead of hard borders
309
+
310
+ **Visual effect:**
311
+
312
+ - Light mode: Subtle gradient from light gray to slightly darker gray
313
+ - Dark mode: Inverted gradient for depth perception
314
+ - No hard borders, shadows, or mechanical separators
315
+ - Depth is perceived through luminosity differences
316
+
317
+ This technique exemplifies the Neo-Minimal principle: **"Light as Structure, not decoration"**.
318
+
319
+ ## Customizing
320
+
321
+ The card appearance can be customized using CSS variables defined in `@lumaui/tokens`.
322
+
323
+ ### Override Globally
324
+
325
+ ```css
326
+ /* In your global styles.css */
327
+ :root {
328
+ --luma-card-shadow-background: #ffffff;
329
+ --luma-card-shadow-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
330
+ --luma-card-padding: 24px;
331
+ }
332
+ ```
333
+
334
+ ### Override Per Theme
335
+
336
+ ```css
337
+ /* Light mode */
338
+ :root {
339
+ --luma-card-shadow-background: #fafafa;
340
+ }
341
+
342
+ /* Dark mode */
343
+ .dark {
344
+ --luma-card-shadow-background: oklch(0.18 0.005 265);
345
+ --luma-card-nested-background: oklch(0.2 0.005 265);
346
+ }
347
+ ```
348
+
349
+ ### Override Per Component
350
+
351
+ ```css
352
+ /* Cards in sidebar - more compact */
353
+ .sidebar {
354
+ --luma-card-padding: 16px;
355
+ }
356
+
357
+ /* Cards in hero section - more prominent shadow */
358
+ .hero {
359
+ --luma-card-shadow-shadow: 0 12px 32px oklch(0.22 0.01 265 / 0.1);
360
+ }
361
+ ```
362
+
363
+ ## Neo-Minimal Principles
364
+
365
+ The Card design embodies core Neo-Minimal values:
366
+
367
+ - **Visual Silence**: Subtle borders and shadows, never demands attention
368
+ - **Light as Structure**: Luminosity differences create depth without heavy shadows
369
+ - **Functional Whitespace**: Generous padding (`24px` default) creates hierarchy
370
+ - **Form & Geometry**: Rounded corners (`16px` product, `12px` nested) feel organic
371
+ - **Organic Geometry**: Soft edges flow naturally, avoiding hard mechanical lines
372
+ - **Editorial Color**: No brand colors in structure - neutral tones only
373
+ - **Compositional Architecture**: Directives compose semantically, not through rigid templates
374
+
375
+ ## Accessibility
376
+
377
+ - **Semantic HTML**: Proper heading hierarchy with `<h2>`, `<h3>`, `<h4>` elements
378
+ - **Color contrast**: Background and text meet WCAG AA 4.5:1 minimum
379
+ - **Readable typography**: Generous line-height and spacing for comfortable reading
380
+ - **Theme support**: Both light and dark modes maintain accessibility standards
381
+ - **Flexible structure**: No enforced heading levels - adapt to your document outline
382
+
383
+ **Accessibility Notes:**
384
+
385
+ - Use appropriate heading levels (`<h2>`, `<h3>`, etc.) with `lumaCardTitle` directive
386
+ - Ensure descriptions provide meaningful context for screen reader users
387
+ - Maintain logical heading hierarchy in your document
388
+
389
+ ## Implementation Notes
390
+
391
+ - Uses Angular 20+ signal-based computed values (`computed()`)
392
+ - Styled with Tailwind CSS v4 utilities referencing design tokens with `lm-` prefix
393
+ - Type-safe variant types exported: `CardVariant`, `CardTitleVariants`, `CardDescriptionVariants`
394
+ - OnPush change detection for optimal performance
395
+ - Compositional architecture allows flexible content projection
396
+
397
+ ## When to Use Each Variant
398
+
399
+ | Variant | Use Case |
400
+ | --------- | --------------------------------------------------- |
401
+ | `default` | Default styling, distinctive gradient border effect |
402
+ | `shadow` | Primary content, main UI cards, elevated sections |
403
+ | `nested` | Sections within cards, grouped content, stat blocks |
404
+ | `preview` | Documentation examples, component showcases |
405
+
406
+ **Avoid using Card when:**
407
+
408
+ - Content doesn't need visual separation (use whitespace instead)
409
+ - Creating overly nested card-within-card layouts (violates visual silence)
410
+ - Every element needs a container (over-containerization)
411
+ - A simple list would suffice
412
+
413
+ **Remember:** Per Neo-Minimal principles, "If an element can be removed without functional or semantic loss, it shouldn't exist."
414
+
415
+ ## Design Token Reference
416
+
417
+ ### Legacy Gradient Tokens
418
+
419
+ | Token | Default Value | Purpose |
420
+ | --------------------------- | --------------------------- | --------------------- |
421
+ | `--luma-card-background` | `oklch(1 0 0)` | Inner card background |
422
+ | `--luma-card-gradient-from` | `oklch(0.92 0.005 0 / 0.6)` | Top gradient edge |
423
+ | `--luma-card-gradient-to` | `oklch(0.96 0.003 0 / 0.6)` | Bottom gradient edge |
424
+ | `--luma-card-padding` | `1.5rem` | Inner content padding |
425
+ | `--luma-card-box-shadow` | `0px 2px 0 0px #e4e4e4` | Legacy shadow |
426
+
427
+ ### Shadow Variant Tokens
428
+
429
+ | Token | Default Value | Purpose |
430
+ | ------------------------------- | ---------------------------------------- | --------------- |
431
+ | `--luma-card-shadow-background` | `oklch(1 0 0)` | Card background |
432
+ | `--luma-card-shadow-border` | `oklch(0.92 0.008 265)` | Border color |
433
+ | `--luma-card-shadow-shadow` | `0 8px 24px oklch(0.22 0.01 265 / 0.06)` | Soft elevation |
434
+ | `--luma-card-shadow-radius` | `16px` | Border radius |
435
+
436
+ ### Nested Variant Tokens
437
+
438
+ | Token | Default Value | Purpose |
439
+ | ------------------------------- | ----------------------- | ----------------- |
440
+ | `--luma-card-nested-background` | `oklch(0.98 0.005 265)` | Subtle background |
441
+ | `--luma-card-nested-border` | `oklch(0.92 0.008 265)` | Border color |
442
+ | `--luma-card-nested-radius` | `12px` | Border radius |
443
+
444
+ ### Preview Variant Tokens
445
+
446
+ | Token | Default Value | Purpose |
447
+ | -------------------------------- | ----------------------- | ------------------ |
448
+ | `--luma-card-preview-background` | `oklch(0.98 0.005 265)` | Preview background |
449
+ | `--luma-card-preview-border` | `oklch(0.92 0.008 265)` | Border color |
450
+ | `--luma-card-preview-radius` | `12px` | Border radius |
451
+
452
+ **Note:** Dark theme values are defined in `card.dark.json` and automatically applied via `.dark` selector.
@@ -0,0 +1,19 @@
1
+ // Main Card component
2
+ export * from './card.component';
3
+
4
+ // Card compositional directives
5
+ export * from './card-title.directive';
6
+ export * from './card-description.directive';
7
+ export * from './card-header.directive';
8
+ export * from './card-content.directive';
9
+
10
+ // Re-export types from core for convenience
11
+ export type {
12
+ CardVariants,
13
+ CardContentVariants,
14
+ CardTitleVariants,
15
+ CardDescriptionVariants,
16
+ CardVariant,
17
+ CardTitleSize,
18
+ CardDescriptionSize,
19
+ } from '@lumaui/core';
@@ -0,0 +1,5 @@
1
+ import '@angular/compiler';
2
+ import '@analogjs/vitest-angular/setup-snapshots';
3
+ import { setupTestBed } from '@analogjs/vitest-angular/setup-testbed';
4
+
5
+ setupTestBed();