@pure-ds/storybook 0.1.5 → 0.1.7

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.
@@ -2,75 +2,352 @@ import { html } from 'lit';
2
2
 
3
3
  export default {
4
4
  title: 'Primitives/Cards',
5
+ tags: ['cards', 'layout', 'spacing', 'surface', 'colors'],
5
6
  parameters: {
7
+ pds: {
8
+ tags: ['cards', 'layout', 'spacing', 'surface', 'colors']
9
+ },
6
10
  docs: {
7
11
  description: {
8
- component: 'Basic UI elements - buttons, forms, cards, badges'
12
+ component: 'Versatile content containers with multiple surface variants. Cards automatically adapt to your theme and support nesting for complex layouts.'
9
13
  }
10
14
  }
11
- },
12
- argTypes: {
13
- preset: {
14
- control: 'select',
15
- options: ['default', 'ocean-breeze', 'midnight-steel', 'sunset-vibes', 'forest-calm', 'lavender-dream'],
16
- description: 'Choose a design preset'
17
- },
18
- primaryColor: {
19
- control: 'color',
20
- description: 'Override primary color'
21
- },
22
- secondaryColor: {
23
- control: 'color',
24
- description: 'Override secondary color'
25
- }
26
15
  }
27
16
  };
28
17
 
29
- export const Default = {
30
- render: (args) => {
31
- // Apply preset if changed
32
- if (args.preset) {
33
- import('../../../src/js/pds.js').then(({ PDS }) => {
34
- PDS.applyDesign({ preset: args.preset });
35
- });
18
+ const cardsStoryStyles = html`
19
+ <style>
20
+ .cards-story-section {
21
+ padding: var(--spacing-4);
36
22
  }
37
-
38
- // Apply color overrides
39
- if (args.primaryColor || args.secondaryColor) {
40
- import('../../../src/js/pds.js').then(({ PDS }) => {
41
- PDS.applyDesign({
42
- design: {
43
- colors: {
44
- primary: args.primaryColor,
45
- secondary: args.secondaryColor
46
- }
47
- }
48
- });
49
- });
23
+ .cards-basic-grid {
24
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
50
25
  }
51
-
52
-
26
+ .cards-surface-grid {
27
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
28
+ }
29
+ .cards-helper {
30
+ margin-bottom: var(--spacing-4);
31
+ opacity: 0.8;
32
+ }
33
+ .cards-inline-actions {
34
+ margin-top: var(--spacing-3);
35
+ }
36
+ .cards-nested-shell {
37
+ max-width: 37.5rem;
38
+ }
39
+ .cards-nested-spacing {
40
+ margin-top: var(--spacing-4);
41
+ }
42
+ .cards-nested-deep {
43
+ margin-top: var(--spacing-3);
44
+ }
45
+ .cards-parent-action {
46
+ margin-top: var(--spacing-4);
47
+ }
48
+ .cards-horizontal-card {
49
+ max-width: 37.5rem;
50
+ margin-bottom: var(--spacing-6);
51
+ }
52
+ .cards-horizontal-media {
53
+ flex-shrink: 0;
54
+ width: 7.5rem;
55
+ height: 7.5rem;
56
+ background: var(--color-primary);
57
+ border-radius: var(--radius-md);
58
+ }
59
+ .cards-horizontal-icon {
60
+ color: white;
61
+ opacity: 0.6;
62
+ }
63
+ .cards-horizontal-body {
64
+ flex: 1;
65
+ }
66
+ .cards-grid-visuals {
67
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
68
+ }
69
+ .cards-visual-block {
70
+ height: 100px;
71
+ border-radius: var(--radius-sm);
72
+ margin-bottom: var(--spacing-3);
73
+ }
74
+ .cards-gradient-one {
75
+ background: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
76
+ }
77
+ .cards-gradient-two {
78
+ background: linear-gradient(135deg, var(--color-secondary), var(--color-primary));
79
+ }
80
+ .cards-gradient-three {
81
+ background: linear-gradient(135deg, var(--color-primary), var(--color-accent));
82
+ }
83
+ .cards-small-copy {
84
+ font-size: 0.9rem;
85
+ }
86
+ .cards-complex-grid {
87
+ grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
88
+ }
89
+ .cards-profile-header {
90
+ margin-bottom: var(--spacing-4);
91
+ }
92
+ .cards-profile-avatar {
93
+ width: 48px;
94
+ height: 48px;
95
+ background: var(--color-primary);
96
+ border-radius: 50%;
97
+ }
98
+ .cards-profile-avatar pds-icon {
99
+ color: white;
100
+ }
101
+ .cards-profile-title {
102
+ margin: 0;
103
+ }
104
+ .cards-profile-meta {
105
+ margin: 0;
106
+ font-size: 0.85rem;
107
+ opacity: 0.7;
108
+ }
109
+ .cards-profile-actions {
110
+ margin-top: var(--spacing-4);
111
+ }
112
+ .cards-premium-header {
113
+ margin-bottom: var(--spacing-3);
114
+ }
115
+ .cards-pro-badge {
116
+ padding: var(--spacing-1) var(--spacing-2);
117
+ background: var(--color-primary);
118
+ color: white;
119
+ border-radius: var(--radius-full);
120
+ font-size: 0.75rem;
121
+ font-weight: 600;
122
+ }
123
+ .cards-premium-list {
124
+ margin: var(--spacing-3) 0;
125
+ }
126
+ .cards-stats-grid {
127
+ margin: var(--spacing-4) 0;
128
+ }
129
+ .cards-stat-value {
130
+ font-size: 2rem;
131
+ font-weight: 700;
132
+ }
133
+ .cards-stat-value.primary {
134
+ color: var(--color-primary);
135
+ }
136
+ .cards-stat-value.secondary {
137
+ color: var(--color-secondary);
138
+ }
139
+ .cards-stat-label {
140
+ font-size: 0.85rem;
141
+ opacity: 0.7;
142
+ }
143
+ </style>
144
+ `;
53
145
 
54
- return html`
55
- <div class="story-container" style="padding: 2rem;">
56
-
57
- <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 1rem;">
146
+ export const BasicCards = () => html`
147
+ ${cardsStoryStyles}
148
+ <div class="cards-story-section">
149
+ <h3>Basic Cards</h3>
150
+ <div class="grid gap-md cards-basic-grid">
58
151
  <article class="card">
59
- <h3>Card Title</h3>
60
- <p>Card content goes here. This is a basic card primitive.</p>
152
+ <h3>Default Card</h3>
153
+ <p>Card content goes here. This is a basic card primitive with automatic theming.</p>
61
154
  <button class="btn-primary">Action</button>
62
155
  </article>
156
+
63
157
  <article class="card">
64
- <h3>Another Card</h3>
65
- <p>Cards are versatile containers for content.</p>
158
+ <h3>With Icon</h3>
159
+ <div class="flex items-start gap-sm">
160
+ <pds-icon icon="star" size="lg" class="icon-primary"></pds-icon>
161
+ <div>
162
+ <p>Cards can contain icons, buttons, forms, and any other content.</p>
163
+ </div>
164
+ </div>
66
165
  <button class="btn-outline">Learn More</button>
67
166
  </article>
167
+
168
+ <article class="card">
169
+ <h3>Interactive Card</h3>
170
+ <p>With multiple actions and rich content.</p>
171
+ <div class="flex gap-sm cards-inline-actions">
172
+ <button class="btn-primary btn-sm">
173
+ <pds-icon icon="heart" size="sm"></pds-icon>
174
+ Like
175
+ </button>
176
+ <button class="btn-secondary btn-sm">
177
+ <pds-icon icon="share" size="sm"></pds-icon>
178
+ Share
179
+ </button>
180
+ <button class="icon-only btn-outline btn-sm">
181
+ <pds-icon icon="bookmark" size="sm" label="Bookmark"></pds-icon>
182
+ </button>
183
+ </div>
184
+ </article>
185
+ </div>
186
+ </div>
187
+ `;
188
+
189
+ BasicCards.storyName = 'Basic Cards';
190
+
191
+ export const SurfaceVariants = () => html`
192
+ ${cardsStoryStyles}
193
+ <div class="cards-story-section">
194
+ <h3>Surface Variants</h3>
195
+ <p class="cards-helper">
196
+ Different surface levels create visual hierarchy
197
+ </p>
198
+
199
+ <div class="grid gap-md cards-surface-grid">
200
+ <article class="card">
201
+ <h4>Default Surface</h4>
202
+ <p>Standard card surface level. Use for most content containers.</p>
203
+ <code>.card</code>
204
+ </article>
205
+
206
+ <article class="card surface-elevated">
207
+ <h4>Elevated Surface</h4>
208
+ <p>Appears raised above the default surface. Great for important content or hover states.</p>
209
+ <code>.surface-elevated</code>
210
+ </article>
211
+
212
+ <article class="card surface-overlay">
213
+ <h4>Overlay Surface</h4>
214
+ <p>Highest surface level. Perfect for modal dialogs and floating panels.</p>
215
+ <code>.surface-overlay</code>
216
+ </article>
68
217
  </div>
69
-
218
+ </div>
219
+ `;
220
+
221
+ SurfaceVariants.storyName = 'Surface Variants';
222
+
223
+ export const NestedCards = () => html`
224
+ ${cardsStoryStyles}
225
+ <div class="cards-story-section">
226
+ <h3>Nested Cards</h3>
227
+ <p class="cards-helper">
228
+ Surface variants enable natural nesting without visual confusion
229
+ </p>
230
+
231
+ <article class="card cards-nested-shell">
232
+ <h3>Parent Card (Default Surface)</h3>
233
+ <p>This is the outer container using the default card surface.</p>
234
+
235
+ <div class="cards-nested-spacing">
236
+ <article class="card surface-elevated">
237
+ <h4>Nested Card (Elevated)</h4>
238
+ <p>This card is nested inside the parent and uses the elevated surface for clear visual separation.</p>
239
+
240
+ <div class="cards-nested-deep">
241
+ <article class="card surface-overlay">
242
+ <h5>Deeply Nested (Overlay)</h5>
243
+ <p class="cards-small-copy">Even deeper nesting maintains readability with the overlay surface.</p>
244
+ </article>
245
+ </div>
246
+ </article>
70
247
  </div>
71
- `;
72
- },
73
- args: {
74
- preset: 'default'
75
- }
76
- };
248
+
249
+ <button class="btn-primary cards-parent-action">Parent Action</button>
250
+ </article>
251
+ </div>
252
+ `;
253
+
254
+ NestedCards.storyName = 'Nested Cards';
255
+
256
+ export const CardLayouts = () => html`
257
+ ${cardsStoryStyles}
258
+ <div class="cards-story-section">
259
+ <h3>Horizontal Card</h3>
260
+ <article class="card flex gap-md cards-horizontal-card">
261
+ <div class="flex items-center justify-center cards-horizontal-media">
262
+ <pds-icon icon="image" size="xl" class="cards-horizontal-icon"></pds-icon>
263
+ </div>
264
+ <div class="cards-horizontal-body">
265
+ <h4>Horizontal Layout</h4>
266
+ <p>Cards work great with flexbox for horizontal layouts.</p>
267
+ <button class="btn-outline btn-sm">View Details</button>
268
+ </div>
269
+ </article>
270
+
271
+ <h3>Card Grid</h3>
272
+ <div class="grid gap-sm cards-grid-visuals">
273
+ <article class="card">
274
+ <div class="cards-visual-block cards-gradient-one"></div>
275
+ <h4>Card 1</h4>
276
+ <p class="cards-small-copy">Grid layout with cards.</p>
277
+ </article>
278
+ <article class="card">
279
+ <div class="cards-visual-block cards-gradient-two"></div>
280
+ <h4>Card 2</h4>
281
+ <p class="cards-small-copy">Responsive and flexible.</p>
282
+ </article>
283
+ <article class="card">
284
+ <div class="cards-visual-block cards-gradient-three"></div>
285
+ <h4>Card 3</h4>
286
+ <p class="cards-small-copy">Auto-fits to space.</p>
287
+ </article>
288
+ </div>
289
+ </div>
290
+ `;
291
+
292
+ CardLayouts.storyName = 'Card Layouts';
293
+
294
+ export const ComplexCards = () => html`
295
+ ${cardsStoryStyles}
296
+ <div class="cards-story-section">
297
+ <h3>Complex Card Examples</h3>
298
+ <div class="grid gap-md cards-complex-grid">
299
+
300
+ <article class="card">
301
+ <div class="flex items-center gap-sm cards-profile-header">
302
+ <div class="flex items-center justify-center cards-profile-avatar">
303
+ <pds-icon icon="user"></pds-icon>
304
+ </div>
305
+ <div>
306
+ <h4 class="cards-profile-title">User Profile</h4>
307
+ <p class="cards-profile-meta">@username</p>
308
+ </div>
309
+ </div>
310
+ <p>Profile description goes here with some interesting details about the user.</p>
311
+ <div class="flex gap-sm cards-profile-actions">
312
+ <button class="btn-primary btn-sm">Follow</button>
313
+ <button class="btn-outline btn-sm">Message</button>
314
+ </div>
315
+ </article>
316
+
317
+ <article class="card surface-elevated">
318
+ <div class="flex justify-between items-start cards-premium-header">
319
+ <h4>Premium Feature</h4>
320
+ <span class="cards-pro-badge">PRO</span>
321
+ </div>
322
+ <p>This elevated card highlights a premium feature with a badge and special styling.</p>
323
+ <ul class="cards-premium-list">
324
+ <li>Feature benefit one</li>
325
+ <li>Feature benefit two</li>
326
+ <li>Feature benefit three</li>
327
+ </ul>
328
+ <button class="btn-primary">
329
+ <pds-icon icon="star"></pds-icon>
330
+ Upgrade Now
331
+ </button>
332
+ </article>
333
+
334
+ <article class="card">
335
+ <h4>Stats Card</h4>
336
+ <div class="grid grid-cols-2 gap-md cards-stats-grid">
337
+ <div>
338
+ <div class="cards-stat-value primary">1.2K</div>
339
+ <div class="cards-stat-label">Followers</div>
340
+ </div>
341
+ <div>
342
+ <div class="cards-stat-value secondary">847</div>
343
+ <div class="cards-stat-label">Following</div>
344
+ </div>
345
+ </div>
346
+ <button class="btn-outline btn-sm">View All</button>
347
+ </article>
348
+
349
+ </div>
350
+ </div>
351
+ `;
352
+
353
+ ComplexCards.storyName = 'Complex Cards';
@@ -1,11 +1,20 @@
1
1
  import { html } from 'lit';
2
+ import { toastFormData } from '../utils/toast-utils.js';
2
3
 
3
4
  export default {
4
5
  title: 'Primitives/Forms',
6
+ tags: ['buttons', 'forms'],
5
7
  parameters: {
8
+ pds: {
9
+ tags: ['buttons', 'forms']
10
+ },
6
11
  docs: {
7
12
  description: {
8
- component: 'Basic UI elements - buttons, forms, cards, badges'
13
+ component: `Standard HTML form controls styled by PDS.
14
+
15
+ **💡 For modern apps, consider using [pds-jsonform](/story/components-pds-jsonform--simple-form)** - a powerful web component that automatically generates forms from JSON Schema with built-in validation, conditional logic, and data binding.
16
+
17
+ These primitive form controls provide the foundation for manual form building when you need full control over the markup.`
9
18
  }
10
19
  }
11
20
  },
@@ -28,173 +37,95 @@ export default {
28
37
 
29
38
  export const Default = {
30
39
  render: (args) => {
31
- // Apply preset if changed
32
- if (args.preset) {
33
- import('../../../src/js/pds.js').then(({ PDS }) => {
34
- PDS.applyDesign({ preset: args.preset });
35
- });
36
- }
37
-
38
- // Apply color overrides
39
- if (args.primaryColor || args.secondaryColor) {
40
- import('../../../src/js/pds.js').then(({ PDS }) => {
41
- PDS.applyDesign({
42
- design: {
43
- colors: {
44
- primary: args.primaryColor,
45
- secondary: args.secondaryColor
46
- }
47
- }
48
- });
49
- });
50
- }
51
-
40
+ // Preset changes are handled by toolbar in preview.js
41
+ const handleSubmit = (event) => {
42
+ event.preventDefault();
43
+ toastFormData(new FormData(event.target));
44
+ };
52
45
 
53
-
54
46
  return html`
55
- <div class="story-container" style="padding: 2rem;">
56
- <h2>
57
- <pds-icon
58
- icon="note-pencil"
59
- size="lg"
60
- class="icon-primary"
61
- ></pds-icon>
62
- Form Controls
63
- </h2>
64
-
65
- <form
66
- class="form-demo"
67
- onsubmit="event.preventDefault(); console.log('Form submitted (prevented)'); return false;"
68
- >
69
- <fieldset>
70
- <legend>Personal Information</legend>
71
-
72
- <label>
73
- <span>Full Name</span>
74
- <input type="text" placeholder="Enter your name" required />
75
- </label>
76
-
77
- <label>
78
- <span>Email</span>
79
- <input
80
- type="email"
81
- placeholder="you@example.com"
82
- autocomplete="username"
83
- required
84
- />
85
- </label>
86
-
87
- <label>
88
- <span>Phone</span>
89
- <input type="tel" placeholder="+1 (555) 000-0000" />
90
- </label>
91
-
92
- <label>
93
- <span>Date of Birth</span>
94
- <input type="date" />
95
- </label>
96
-
97
- <label>
98
- <span>Rich Text</span>
99
- <pds-richtext
100
- name="richtext"
101
- placeholder="Enter rich text"
102
- ></pds-richtext>
103
- </label>
104
-
105
- <label>
106
- <span>Password</span>
107
- <input
108
- type="password"
109
- placeholder="Enter password"
110
- autocomplete="current-password"
111
- />
112
- </label>
113
-
114
- <label>
115
- <span>Country</span>
116
- <select>
117
- <option>United States</option>
118
- <option>Canada</option>
119
- <option>United Kingdom</option>
120
- <option>Germany</option>
121
- <option>France</option>
122
- <option>Other</option>
123
- </select>
124
- </label>
125
-
126
- <label>
127
- <span>Number</span>
128
- <input type="number" min="0" max="100" value="50" />
129
- </label>
130
-
131
- <label>
132
- <span>Range</span>
133
- <input type="range" min="0" max="100" value="50" />
134
- </label>
135
-
136
- <label>
137
- <span>URL</span>
138
- <input type="url" placeholder="https://example.com" />
139
- </label>
140
-
141
- <label>
142
- <span>File Upload</span>
143
- <pds-upload name="file"></pds-upload>
144
- </label>
145
-
146
- <label>
147
- <span>Message</span>
148
- <textarea
149
- rows="4"
150
- placeholder="Your message here..."
151
- ></textarea>
152
- </label>
153
- </fieldset>
154
-
155
- <fieldset>
156
- <legend>Preferences</legend>
157
-
158
- <label data-toggle>
159
- <input type="checkbox" checked />
160
- Subscribe to newsletter
161
- </label>
162
-
163
- <label data-toggle>
164
- <input type="checkbox" />
165
- Receive marketing emails
166
- </label>
167
- </fieldset>
168
-
169
- <fieldset>
170
- <legend>Toggle Switches (Progressive Enhancement)</legend>
171
-
172
- <label data-toggle>
173
- <input type="checkbox" checked />
174
- Enable notifications
175
- </label>
176
-
177
- <label data-toggle>
178
- <input type="checkbox" />
179
- Dark mode
180
- </label>
181
-
182
- <label data-toggle>
183
- <input type="checkbox" checked />
184
- Auto-save
185
- </label>
186
- </fieldset>
47
+ <style>
48
+ .forms-default-form {
49
+ max-width: 25rem;
50
+ }
51
+ </style>
52
+ <div class="card">
53
+
54
+ <form class="forms-default-form" @submit=${handleSubmit}>
55
+ <label>
56
+ <span>Text Input</span>
57
+ <input type="text" name="text" placeholder="Enter text...">
58
+ </label>
59
+ <label>
60
+ <span>Email</span>
61
+ <div class="input-icon">
62
+ <pds-icon icon="envelope"></pds-icon>
63
+ <input type="email" name="email" required placeholder="email@example.com">
64
+ </div>
65
+ </label>
66
+ <label>
67
+ <span>Select</span>
68
+ <select name="select">
69
+ <option>Option 1</option>
70
+ <option>Option 2</option>
71
+ <option>Option 3</option>
72
+ </select>
73
+ </label>
74
+ <label>
75
+ <span>Textarea</span>
76
+ <textarea name="textarea" rows="4" placeholder="Enter longer text..."></textarea>
77
+ </label>
78
+ <button type="submit" class="btn-primary">Submit</button>
79
+ </form>
80
+
81
+ </div>
82
+ `;
83
+ },
84
+ args: {
85
+ preset: 'default'
86
+ }
87
+ };
187
88
 
188
- <div class="form-demo-actions">
189
- <button type="submit" class="btn-primary">Submit Form</button>
190
- <button type="reset" class="btn-secondary">Reset</button>
191
- <button type="button" class="btn-outline">Cancel</button>
192
- </div>
193
- </form>
89
+ export const InputsWithIcons = {
90
+ render: (args) => {
91
+ return html`
92
+ <style>
93
+ .forms-inputs-demo {
94
+ max-width: 25rem;
95
+ }
96
+ </style>
97
+ <div class="card">
98
+ <h3>Inputs with Icons</h3>
99
+ <p>Enhance inputs with icons for better UX. Icons can be positioned at the start or end of the input.</p>
100
+
101
+ <div class="flex flex-col gap-lg forms-inputs-demo">
102
+ <label>
103
+ <span>Search (Icon Start)</span>
104
+ <div class="input-icon">
105
+ <pds-icon icon="magnifying-glass"></pds-icon>
106
+ <input type="search" placeholder="Search..." />
107
+ </div>
108
+ </label>
109
+
110
+ <label>
111
+ <span>Username (Icon End)</span>
112
+ <div class="input-icon input-icon-end">
113
+ <input type="text" placeholder="Username" />
114
+ <pds-icon icon="user"></pds-icon>
115
+ </div>
116
+ </label>
117
+ </div>
194
118
  </div>
195
119
  `;
196
120
  },
197
121
  args: {
198
122
  preset: 'default'
123
+ },
124
+ parameters: {
125
+ docs: {
126
+ description: {
127
+ story: 'Input fields can be enhanced with icons to provide visual context. Use the `input-icon` class wrapper and position icons at the start (default) or end (`input-icon-end`) of the input.'
128
+ }
129
+ }
199
130
  }
200
131
  };