@pure-ds/storybook 0.1.6 → 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.
@@ -1,195 +1,305 @@
1
1
  import { html } from 'lit';
2
+ import { presets } from '../../../../src/js/pds-core/pds-config.js';
3
+
4
+ const iconStoryStyles = html`
5
+ <style>
6
+ .icon-story-section {
7
+ padding: var(--spacing-4);
8
+ display: grid;
9
+ gap: var(--spacing-4);
10
+ }
11
+
12
+ .icon-story-description {
13
+ margin-bottom: var(--spacing-4);
14
+ opacity: 0.8;
15
+ max-width: 60ch;
16
+ }
17
+
18
+ .icon-story-grid {
19
+ display: flex;
20
+ gap: var(--spacing-3);
21
+ flex-wrap: wrap;
22
+ align-items: center;
23
+ }
24
+
25
+ .icon-story-size-grid {
26
+ display: grid;
27
+ gap: var(--spacing-4);
28
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
29
+ }
30
+
31
+ .icon-story-size-item {
32
+ display: grid;
33
+ gap: var(--spacing-2);
34
+ text-align: center;
35
+ justify-items: center;
36
+ }
37
+
38
+ .icon-story-filter {
39
+ display: grid;
40
+ justify-items: center;
41
+ gap: var(--spacing-2);
42
+ margin-bottom: var(--spacing-6);
43
+ }
44
+
45
+ .icon-story-filter__label {
46
+ font-weight: 600;
47
+ }
48
+
49
+ .icon-story-filter__input {
50
+ width: 100%;
51
+ max-width: 400px;
52
+ padding: var(--spacing-3);
53
+ border: 1px solid var(--color-border);
54
+ border-radius: var(--radius-md);
55
+ font-size: 1rem;
56
+ text-align: center;
57
+ background: var(--color-surface);
58
+ }
59
+
60
+ .icon-category {
61
+ display: grid;
62
+ gap: var(--spacing-4);
63
+ }
64
+
65
+ .icon-category__title {
66
+ text-transform: capitalize;
67
+ display: flex;
68
+ align-items: baseline;
69
+ gap: var(--spacing-2);
70
+ flex-wrap: wrap;
71
+ }
72
+
73
+ .icon-category__count {
74
+ font-size: 0.85rem;
75
+ font-weight: normal;
76
+ opacity: 0.6;
77
+ }
78
+
79
+ .icon-category__grid {
80
+ display: grid;
81
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
82
+ gap: var(--spacing-3);
83
+ }
84
+
85
+ .icon-item {
86
+ display: flex;
87
+ flex-direction: column;
88
+ align-items: center;
89
+ gap: var(--spacing-2);
90
+ padding: var(--spacing-3);
91
+ border-radius: var(--radius-sm);
92
+ cursor: pointer;
93
+ transition: background-color 0.2s ease, color 0.2s ease;
94
+ }
95
+
96
+ .icon-item:hover {
97
+ background: var(--surface-elevated);
98
+ }
99
+
100
+ .icon-item--copied {
101
+ animation: iconItemCopied 0.4s ease;
102
+ background: var(--color-primary);
103
+ color: var(--color-surface);
104
+ }
105
+
106
+ .icon-item__label {
107
+ font-size: 0.75rem;
108
+ text-align: center;
109
+ word-break: break-word;
110
+ opacity: 0.8;
111
+ }
112
+
113
+ .icon-story-usage {
114
+ margin-top: var(--spacing-6);
115
+ display: grid;
116
+ gap: var(--spacing-3);
117
+ }
118
+
119
+ .icon-story-usage__code {
120
+ margin: 0;
121
+ padding: var(--spacing-3);
122
+ background: var(--surface-bg);
123
+ border-radius: var(--radius-sm);
124
+ overflow-x: auto;
125
+ }
126
+
127
+ @keyframes iconItemCopied {
128
+ 0% {
129
+ transform: scale(1);
130
+ }
131
+ 50% {
132
+ transform: scale(0.98);
133
+ }
134
+ 100% {
135
+ transform: scale(1);
136
+ }
137
+ }
138
+ </style>
139
+ `;
2
140
 
3
141
  export default {
4
142
  title: 'Foundations/Icons',
5
143
  parameters: {
6
144
  docs: {
7
145
  description: {
8
- component: 'Design tokens - colors, typography, spacing, icons'
146
+ component: 'Icon system using Phosphor icons with configurable sets per category'
9
147
  }
10
148
  }
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
149
  }
27
150
  };
28
151
 
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
- });
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
-
52
-
53
-
54
- return html`
55
- <div class="story-container" style="padding: 2rem;">
56
- <h2>
57
- <pds-icon icon="star" size="lg" class="icon-accent"></pds-icon>
58
- Icon System
59
- </h2>
60
-
61
- <h3>Sizes</h3>
62
- <div class="icon-sizes surface-translucent">
63
- <pds-icon icon="heart" size="xs"></pds-icon>
64
- <pds-icon icon="heart" size="sm"></pds-icon>
65
- <pds-icon icon="heart" size="md"></pds-icon>
66
- <pds-icon icon="heart" size="lg"></pds-icon>
67
- <pds-icon icon="heart" size="xl"></pds-icon>
68
- <pds-icon icon="heart" size="2xl"></pds-icon>
69
- </div>
152
+ export const CommonIcons = () => html`
153
+ ${iconStoryStyles}
154
+ <section class="icon-story-section">
155
+ <div>
156
+ <h3>Common Icons</h3>
157
+ <p class="icon-story-description">
158
+ Frequently used icons for everyday UI needs
159
+ </p>
160
+ </div>
161
+ <div class="icon-story-grid">
162
+ <pds-icon icon="heart" size="lg"></pds-icon>
163
+ <pds-icon icon="star" size="lg"></pds-icon>
164
+ <pds-icon icon="user" size="lg"></pds-icon>
165
+ <pds-icon icon="bell" size="lg"></pds-icon>
166
+ <pds-icon icon="magnifying-glass" size="lg"></pds-icon>
167
+ <pds-icon icon="list" size="lg"></pds-icon>
168
+ <pds-icon icon="x" size="lg"></pds-icon>
169
+ <pds-icon icon="check" size="lg"></pds-icon>
170
+ <pds-icon icon="gear" size="lg"></pds-icon>
171
+ <pds-icon icon="download" size="lg"></pds-icon>
172
+ </div>
173
+ </section>
174
+ `;
70
175
 
71
- <h3>Semantic Colors</h3>
72
- <div class="icon-colors surface-translucent">
73
- <pds-icon
74
- icon="check-circle"
75
- class="icon-primary"
76
- size="lg"
77
- ></pds-icon>
78
- <pds-icon
79
- icon="check-circle"
80
- class="icon-secondary"
81
- size="lg"
82
- ></pds-icon>
83
- <pds-icon
84
- icon="check-circle"
85
- class="icon-accent"
86
- size="lg"
87
- ></pds-icon>
88
- <pds-icon
89
- icon="check-circle"
90
- class="icon-success"
91
- size="lg"
92
- ></pds-icon>
93
- <pds-icon
94
- icon="warning"
95
- class="icon-warning"
96
- size="lg"
97
- ></pds-icon>
98
- <pds-icon
99
- icon="x-circle"
100
- class="icon-danger"
101
- size="lg"
102
- ></pds-icon>
103
- <pds-icon icon="info" class="icon-info" size="lg"></pds-icon>
104
- </div>
176
+ CommonIcons.storyName = 'Common Icons';
105
177
 
106
- <h3>Icon with Text</h3>
107
- <div class="icon-text-demo">
108
- <div class="icon-text">
109
- <pds-icon icon="envelope"></pds-icon>
110
- <span>Email</span>
111
- </div>
112
- <div class="icon-text">
113
- <pds-icon icon="phone"></pds-icon>
114
- <span>Phone</span>
115
- </div>
116
- <div class="icon-text">
117
- <pds-icon icon="user"></pds-icon>
118
- <span>Profile</span>
119
- </div>
120
- <div class="icon-text">
121
- <pds-icon icon="calendar"></pds-icon>
122
- <span>Schedule</span>
123
- </div>
124
- </div>
178
+ export const IconSizes = () => html`
179
+ ${iconStoryStyles}
180
+ <section class="icon-story-section">
181
+ <div>
182
+ <h3>Icon Sizes</h3>
183
+ <p class="icon-story-description">
184
+ Built-in sizing scale keeps visual hierarchy consistent across the UI.
185
+ </p>
186
+ </div>
187
+ <div class="icon-story-size-grid">
188
+ <div class="icon-story-size-item">
189
+ <pds-icon icon="heart" size="xs"></pds-icon>
190
+ <small class="text-muted">xs (16px)</small>
191
+ </div>
192
+ <div class="icon-story-size-item">
193
+ <pds-icon icon="heart" size="sm"></pds-icon>
194
+ <small class="text-muted">sm (20px)</small>
195
+ </div>
196
+ <div class="icon-story-size-item">
197
+ <pds-icon icon="heart" size="md"></pds-icon>
198
+ <small class="text-muted">md (24px)</small>
199
+ </div>
200
+ <div class="icon-story-size-item">
201
+ <pds-icon icon="heart" size="lg"></pds-icon>
202
+ <small class="text-muted">lg (32px)</small>
203
+ </div>
204
+ <div class="icon-story-size-item">
205
+ <pds-icon icon="heart" size="xl"></pds-icon>
206
+ <small class="text-muted">xl (48px)</small>
207
+ </div>
208
+ <div class="icon-story-size-item">
209
+ <pds-icon icon="heart" size="2xl"></pds-icon>
210
+ <small class="text-muted">2xl (64px)</small>
211
+ </div>
212
+ </div>
213
+ </section>
214
+ `;
125
215
 
126
- <h3>Inputs with Icons</h3>
127
- <div class="input-icon-demo">
128
- <div class="input-icon">
129
- <pds-icon icon="magnifying-glass"></pds-icon>
130
- <input type="search" placeholder="Search..." />
131
- </div>
132
- <div class="input-icon input-icon-end">
133
- <input type="text" placeholder="Username" />
134
- <pds-icon icon="user"></pds-icon>
135
- </div>
136
- </div>
216
+ IconSizes.storyName = 'Icon Sizes';
137
217
 
138
- <h3>Common Icons</h3>
139
- <div class="icon-grid surface-translucent">
140
- <div class="icon-grid-item">
141
- <pds-icon icon="house" size="lg"></pds-icon>
142
- <span class="icon-grid-label">house</span>
143
- </div>
144
- <div class="icon-grid-item">
145
- <pds-icon icon="gear" size="lg"></pds-icon>
146
- <span class="icon-grid-label">gear</span>
147
- </div>
148
- <div class="icon-grid-item">
149
- <pds-icon icon="bell" size="lg"></pds-icon>
150
- <span class="icon-grid-label">bell</span>
151
- </div>
152
- <div class="icon-grid-item">
153
- <pds-icon icon="heart" size="lg"></pds-icon>
154
- <span class="icon-grid-label">heart</span>
155
- </div>
156
- <div class="icon-grid-item">
157
- <pds-icon icon="star" size="lg"></pds-icon>
158
- <span class="icon-grid-label">star</span>
159
- </div>
160
- <div class="icon-grid-item">
161
- <pds-icon icon="trash" size="lg"></pds-icon>
162
- <span class="icon-grid-label">trash</span>
163
- </div>
164
- <div class="icon-grid-item">
165
- <pds-icon icon="pencil" size="lg"></pds-icon>
166
- <span class="icon-grid-label">pencil</span>
167
- </div>
168
- <div class="icon-grid-item">
169
- <pds-icon icon="check" size="lg"></pds-icon>
170
- <span class="icon-grid-label">check</span>
171
- </div>
172
- <div class="icon-grid-item">
173
- <pds-icon icon="x" size="lg"></pds-icon>
174
- <span class="icon-grid-label">x</span>
175
- </div>
176
- <div class="icon-grid-item">
177
- <pds-icon icon="plus" size="lg"></pds-icon>
178
- <span class="icon-grid-label">plus</span>
179
- </div>
180
- <div class="icon-grid-item">
181
- <pds-icon icon="minus" size="lg"></pds-icon>
182
- <span class="icon-grid-label">minus</span>
183
- </div>
184
- <div class="icon-grid-item">
185
- <pds-icon icon="download" size="lg"></pds-icon>
186
- <span class="icon-grid-label">download</span>
187
- </div>
188
- </div>
218
+ export const AllIcons = () => {
219
+ const iconConfig = presets.default.icons.include;
220
+
221
+ return html`
222
+ ${iconStoryStyles}
223
+ <section class="icon-story-section">
224
+ <div>
225
+ <h2>All Available Icons</h2>
226
+ <p class="icon-story-description">
227
+ Complete icon set from Phosphor Icons, organized by category. Click any icon name to copy it to clipboard.
228
+ </p>
189
229
  </div>
190
- `;
191
- },
192
- args: {
193
- preset: 'default'
194
- }
230
+
231
+ <div class="icon-story-filter">
232
+ <span class="icon-story-filter__label" data-label>Filter icons</span>
233
+ <input
234
+ class="icon-story-filter__input"
235
+ type="search"
236
+ placeholder="Type to filter..."
237
+ @input="${(event) => {
238
+ const searchTerm = event.target.value.toLowerCase();
239
+ const storyRoot = event.target.closest('.icon-story-section');
240
+ const categories = storyRoot?.querySelectorAll('.icon-category');
241
+
242
+ categories?.forEach((category) => {
243
+ const items = category.querySelectorAll('.icon-item');
244
+ let visibleCount = 0;
245
+
246
+ items.forEach((item) => {
247
+ const iconName = item.dataset.iconName ?? '';
248
+ if (iconName.includes(searchTerm)) {
249
+ item.style.display = 'flex';
250
+ visibleCount += 1;
251
+ } else {
252
+ item.style.display = 'none';
253
+ }
254
+ });
255
+
256
+ category.style.display = visibleCount > 0 ? 'grid' : 'none';
257
+ });
258
+ }}"
259
+ />
260
+ </div>
261
+
262
+ ${Object.entries(iconConfig).map(
263
+ ([category, icons]) => html`
264
+ <article class="card icon-category">
265
+ <h3 class="icon-category__title">
266
+ ${category.replace(/([A-Z])/g, ' $1').trim()}
267
+ <span class="icon-category__count">(${icons.length} icons)</span>
268
+ </h3>
269
+
270
+ <div class="icon-category__grid">
271
+ ${icons.map(
272
+ (icon) => html`
273
+ <div
274
+ class="icon-item"
275
+ data-icon-name="${icon}"
276
+ @click="${(event) => {
277
+ navigator.clipboard.writeText(icon);
278
+ const target = event.currentTarget;
279
+ target.classList.add('icon-item--copied');
280
+ setTimeout(() => {
281
+ target.classList.remove('icon-item--copied');
282
+ }, 200);
283
+ }}"
284
+ >
285
+ <pds-icon icon="${icon}" size="lg"></pds-icon>
286
+ <span class="icon-item__label">${icon}</span>
287
+ </div>
288
+ `
289
+ )}
290
+ </div>
291
+ </article>
292
+ `
293
+ )}
294
+
295
+ <article class="card surface-elevated icon-story-usage">
296
+ <h4>Usage</h4>
297
+ <pre class="icon-story-usage__code"><code>&lt;pds-icon icon="heart" size="lg"&gt;&lt;/pds-icon&gt;
298
+ &lt;pds-icon icon="star" size="md"&gt;&lt;/pds-icon&gt;
299
+ &lt;pds-icon icon="user" size="sm"&gt;&lt;/pds-icon&gt;</code></pre>
300
+ </article>
301
+ </section>
302
+ `;
195
303
  };
304
+
305
+ AllIcons.storyName = 'All Icons';