@ivds/core 0.1.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.
Files changed (154) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +215 -0
  3. package/lib/all.css +6802 -0
  4. package/lib/all.min.css +1 -0
  5. package/lib/base/base.css +215 -0
  6. package/lib/base/base.min.css +1 -0
  7. package/lib/components/_breadcrumb-mixins.scss +173 -0
  8. package/lib/components/_button-mixin.scss +120 -0
  9. package/lib/components/_card-mixin.scss +196 -0
  10. package/lib/components/_checkbox-mixin.scss +208 -0
  11. package/lib/components/_footer-mixin.scss +385 -0
  12. package/lib/components/_header-mixin.scss +275 -0
  13. package/lib/components/_navigation-mixins.scss +270 -0
  14. package/lib/components/_notification-mixin.scss +239 -0
  15. package/lib/components/_pagination-mixins.scss +280 -0
  16. package/lib/components/_radio-button-mixin.scss +207 -0
  17. package/lib/components/_tag-mixin.scss +261 -0
  18. package/lib/components/_text-input-mixin.scss +203 -0
  19. package/lib/components/all.css +3005 -0
  20. package/lib/components/all.min.css +1 -0
  21. package/lib/components/breadcrumb/breadcrumb.css +141 -0
  22. package/lib/components/breadcrumb/breadcrumb.min.css +1 -0
  23. package/lib/components/button/button.css +221 -0
  24. package/lib/components/button/button.min.css +1 -0
  25. package/lib/components/card/card.css +236 -0
  26. package/lib/components/card/card.min.css +1 -0
  27. package/lib/components/checkbox/checkbox.css +305 -0
  28. package/lib/components/checkbox/checkbox.min.css +1 -0
  29. package/lib/components/footer/footer.css +466 -0
  30. package/lib/components/footer/footer.min.css +1 -0
  31. package/lib/components/header/header.css +274 -0
  32. package/lib/components/header/header.min.css +1 -0
  33. package/lib/components/navigation/navigation.css +214 -0
  34. package/lib/components/navigation/navigation.min.css +1 -0
  35. package/lib/components/notification/notification.css +253 -0
  36. package/lib/components/notification/notification.min.css +1 -0
  37. package/lib/components/pagination/pagination.css +221 -0
  38. package/lib/components/pagination/pagination.min.css +1 -0
  39. package/lib/components/radio-button/radio-button.css +326 -0
  40. package/lib/components/radio-button/radio-button.min.css +1 -0
  41. package/lib/components/tag/tag.css +367 -0
  42. package/lib/components/tag/tag.min.css +1 -0
  43. package/lib/components/text-input/text-input.css +243 -0
  44. package/lib/components/text-input/text-input.min.css +1 -0
  45. package/lib/icons/icon-arrow-left.css +139 -0
  46. package/lib/icons/icon-arrow-left.min.css +1 -0
  47. package/lib/icons/icon-arrow-right.css +139 -0
  48. package/lib/icons/icon-arrow-right.min.css +1 -0
  49. package/lib/icons/icon-check.css +139 -0
  50. package/lib/icons/icon-check.min.css +1 -0
  51. package/lib/icons/icon-close.css +140 -0
  52. package/lib/icons/icon-close.min.css +1 -0
  53. package/lib/icons/icon-error.css +140 -0
  54. package/lib/icons/icon-error.min.css +1 -0
  55. package/lib/icons/icon-info.css +140 -0
  56. package/lib/icons/icon-info.min.css +1 -0
  57. package/lib/icons/icon-success.css +139 -0
  58. package/lib/icons/icon-success.min.css +1 -0
  59. package/lib/icons/icon-warning.css +139 -0
  60. package/lib/icons/icon-warning.min.css +1 -0
  61. package/lib/icons/icons.css +1158 -0
  62. package/lib/icons/icons.min.css +1 -0
  63. package/lib/utils/_flex.scss +200 -0
  64. package/lib/utils/_grid.scss +211 -0
  65. package/lib/utils/_layout.scss +253 -0
  66. package/lib/utils/_spacing.scss +260 -0
  67. package/lib/utils/_typography.scss +111 -0
  68. package/lib/utils/utils.css +2434 -0
  69. package/lib/utils/utils.min.css +1 -0
  70. package/lib/utils-only.css +2801 -0
  71. package/lib/utils-only.min.css +1 -0
  72. package/lib/variables/variables.css +2 -0
  73. package/lib/variables/variables.min.css +0 -0
  74. package/package.json +194 -0
  75. package/src/__tests__/example.test.scss +12 -0
  76. package/src/accessibility.stories.js +416 -0
  77. package/src/all.scss +9 -0
  78. package/src/base/_layout.scss +97 -0
  79. package/src/base/_reset.scss +85 -0
  80. package/src/base/_typography.scss +105 -0
  81. package/src/base/base.scss +6 -0
  82. package/src/components/all.scss +22 -0
  83. package/src/components/breadcrumb/_breadcrumb-mixins.scss +173 -0
  84. package/src/components/breadcrumb/breadcrumb.scss +68 -0
  85. package/src/components/breadcrumb/breadcrumb.stories.js +483 -0
  86. package/src/components/button/__tests__/button-mixins.test.scss +35 -0
  87. package/src/components/button/_button-mixin.scss +120 -0
  88. package/src/components/button/button.scss +126 -0
  89. package/src/components/button/button.stories.js +364 -0
  90. package/src/components/card/__tests__/card-mixins.test.scss +36 -0
  91. package/src/components/card/_card-mixin.scss +196 -0
  92. package/src/components/card/card.scss +193 -0
  93. package/src/components/card/card.stories.js +635 -0
  94. package/src/components/checkbox/_checkbox-mixin.scss +208 -0
  95. package/src/components/checkbox/checkbox.scss +141 -0
  96. package/src/components/checkbox/checkbox.stories.js +303 -0
  97. package/src/components/footer/_footer-mixin.scss +385 -0
  98. package/src/components/footer/footer.scss +86 -0
  99. package/src/components/footer/footer.stories.js +740 -0
  100. package/src/components/header/_header-mixin.scss +275 -0
  101. package/src/components/header/header.scss +84 -0
  102. package/src/components/header/header.stories.js +450 -0
  103. package/src/components/navigation/_navigation-mixins.scss +270 -0
  104. package/src/components/navigation/navigation.scss +64 -0
  105. package/src/components/navigation/navigation.stories.js +410 -0
  106. package/src/components/notification/_notification-mixin.scss +239 -0
  107. package/src/components/notification/notification.scss +118 -0
  108. package/src/components/notification/notification.stories.js +378 -0
  109. package/src/components/overview.stories.js +473 -0
  110. package/src/components/pagination/_pagination-mixins.scss +280 -0
  111. package/src/components/pagination/pagination.scss +76 -0
  112. package/src/components/pagination/pagination.stories.js +729 -0
  113. package/src/components/radio-button/_radio-button-mixin.scss +207 -0
  114. package/src/components/radio-button/radio-button.scss +178 -0
  115. package/src/components/radio-button/radio-button.stories.js +379 -0
  116. package/src/components/tag/_tag-mixin.scss +261 -0
  117. package/src/components/tag/tag.scss +244 -0
  118. package/src/components/tag/tag.stories.js +482 -0
  119. package/src/components/text-input/_text-input-mixin.scss +203 -0
  120. package/src/components/text-input/text-input.scss +150 -0
  121. package/src/components/text-input/text-input.stories.js +723 -0
  122. package/src/icons/_icon.scss +121 -0
  123. package/src/icons/icon-arrow-left.scss +23 -0
  124. package/src/icons/icon-arrow-right.scss +23 -0
  125. package/src/icons/icon-check.scss +23 -0
  126. package/src/icons/icon-close.scss +24 -0
  127. package/src/icons/icon-error.scss +24 -0
  128. package/src/icons/icon-info.scss +24 -0
  129. package/src/icons/icon-success.scss +23 -0
  130. package/src/icons/icon-warning.scss +23 -0
  131. package/src/icons/icons.scss +12 -0
  132. package/src/icons/icons.stories.js +249 -0
  133. package/src/icons/svg/arrow-left.svg +3 -0
  134. package/src/icons/svg/arrow-right.svg +3 -0
  135. package/src/icons/svg/check.svg +3 -0
  136. package/src/icons/svg/close.svg +4 -0
  137. package/src/icons/svg/error.svg +5 -0
  138. package/src/icons/svg/info.svg +5 -0
  139. package/src/icons/svg/success.svg +4 -0
  140. package/src/icons/svg/warning.svg +5 -0
  141. package/src/utils/__tests__/utilities.test.scss +37 -0
  142. package/src/utils/_flex.scss +200 -0
  143. package/src/utils/_grid.scss +211 -0
  144. package/src/utils/_layout.scss +253 -0
  145. package/src/utils/_spacing.scss +260 -0
  146. package/src/utils/_typography.scss +111 -0
  147. package/src/utils/utils.scss +8 -0
  148. package/src/variables/_borders.scss +15 -0
  149. package/src/variables/_breakpoints.scss +11 -0
  150. package/src/variables/_colors.scss +97 -0
  151. package/src/variables/_shadows.scss +14 -0
  152. package/src/variables/_spacing.scss +24 -0
  153. package/src/variables/_typography.scss +47 -0
  154. package/src/variables/variables.scss +9 -0
@@ -0,0 +1,379 @@
1
+ // Radio Button component stories for Storybook
2
+ // Showcases all radio button variants, sizes, states, and features
3
+
4
+ export default {
5
+ title: 'Core/Radio Button',
6
+ parameters: {
7
+ docs: {
8
+ description: {
9
+ component: 'CSS-only radio button component using IVDS design tokens. Provides multiple variants, sizes, states, and features for form selections where only one option can be chosen.'
10
+ }
11
+ },
12
+ a11y: {
13
+ config: {
14
+ rules: [
15
+ {
16
+ id: 'color-contrast',
17
+ enabled: true
18
+ },
19
+ {
20
+ id: 'label-title-only',
21
+ enabled: true
22
+ }
23
+ ]
24
+ }
25
+ }
26
+ }
27
+ };
28
+
29
+ // Basic radio button
30
+ export const Default = () => `
31
+ <label class="ivds-radio-button">
32
+ <input type="radio" class="ivds-radio-button__input" name="default-example" />
33
+ <div class="ivds-radio-button__circle"></div>
34
+ <span class="ivds-radio-button__label">Default Radio Button</span>
35
+ </label>
36
+ `;
37
+
38
+ // Radio button with description
39
+ export const WithDescription = () => `
40
+ <label class="ivds-radio-button">
41
+ <input type="radio" class="ivds-radio-button__input" name="description-example" />
42
+ <div class="ivds-radio-button__circle"></div>
43
+ <div>
44
+ <span class="ivds-radio-button__label">Premium Shipping</span>
45
+ <div class="ivds-radio-button__description">
46
+ Delivery within 1-2 business days. Additional charges may apply.
47
+ </div>
48
+ </div>
49
+ </label>
50
+ `;
51
+
52
+ // Radio button sizes
53
+ export const Sizes = () => `
54
+ <div style="display: flex; flex-direction: column; gap: 1.5rem;">
55
+ <label class="ivds-radio-button ivds-radio-button--small">
56
+ <input type="radio" class="ivds-radio-button__input" name="size-example" />
57
+ <div class="ivds-radio-button__circle"></div>
58
+ <span class="ivds-radio-button__label">Small Radio Button</span>
59
+ </label>
60
+
61
+ <label class="ivds-radio-button">
62
+ <input type="radio" class="ivds-radio-button__input" name="size-example" />
63
+ <div class="ivds-radio-button__circle"></div>
64
+ <span class="ivds-radio-button__label">Default Radio Button</span>
65
+ </label>
66
+
67
+ <label class="ivds-radio-button ivds-radio-button--large">
68
+ <input type="radio" class="ivds-radio-button__input" name="size-example" checked />
69
+ <div class="ivds-radio-button__circle"></div>
70
+ <span class="ivds-radio-button__label">Large Radio Button</span>
71
+ </label>
72
+ </div>
73
+ `;
74
+
75
+ // Radio button states
76
+ export const States = () => `
77
+ <div style="display: flex; flex-direction: column; gap: 1.5rem;">
78
+ <label class="ivds-radio-button">
79
+ <input type="radio" class="ivds-radio-button__input" name="state-example" />
80
+ <div class="ivds-radio-button__circle"></div>
81
+ <span class="ivds-radio-button__label">Unselected</span>
82
+ </label>
83
+
84
+ <label class="ivds-radio-button">
85
+ <input type="radio" class="ivds-radio-button__input" name="state-example" checked />
86
+ <div class="ivds-radio-button__circle"></div>
87
+ <span class="ivds-radio-button__label">Selected</span>
88
+ </label>
89
+ </div>
90
+ `;
91
+
92
+ // Disabled states
93
+ export const DisabledStates = () => `
94
+ <div style="display: flex; flex-direction: column; gap: 1.5rem;">
95
+ <label class="ivds-radio-button ivds-radio-button--disabled">
96
+ <input type="radio" class="ivds-radio-button__input" name="disabled-example" disabled />
97
+ <div class="ivds-radio-button__circle"></div>
98
+ <span class="ivds-radio-button__label">Disabled Unselected</span>
99
+ </label>
100
+
101
+ <label class="ivds-radio-button ivds-radio-button--disabled">
102
+ <input type="radio" class="ivds-radio-button__input" name="disabled-example" checked disabled />
103
+ <div class="ivds-radio-button__circle"></div>
104
+ <span class="ivds-radio-button__label">Disabled Selected</span>
105
+ </label>
106
+ </div>
107
+ `;
108
+
109
+ // Validation states
110
+ export const ValidationStates = () => `
111
+ <div style="display: flex; flex-direction: column; gap: 1.5rem;">
112
+ <label class="ivds-radio-button ivds-radio-button--error">
113
+ <input type="radio" class="ivds-radio-button__input" name="validation-example" />
114
+ <div class="ivds-radio-button__circle"></div>
115
+ <span class="ivds-radio-button__label">Error State</span>
116
+ </label>
117
+
118
+ <label class="ivds-radio-button ivds-radio-button--success">
119
+ <input type="radio" class="ivds-radio-button__input" name="validation-example" checked />
120
+ <div class="ivds-radio-button__circle"></div>
121
+ <span class="ivds-radio-button__label">Success State</span>
122
+ </label>
123
+ </div>
124
+ `;
125
+
126
+ // Radio button groups
127
+ export const RadioButtonGroups = () => `
128
+ <div style="display: flex; flex-direction: column; gap: 2rem;">
129
+ <div class="ivds-radio-button-group">
130
+ <div class="ivds-radio-button-group__label">
131
+ Preferred Contact Method
132
+ </div>
133
+ <div class="ivds-radio-button-group__description">
134
+ Choose how you'd like us to contact you.
135
+ </div>
136
+
137
+ <label class="ivds-radio-button">
138
+ <input type="radio" class="ivds-radio-button__input" name="contact-method" value="email" />
139
+ <div class="ivds-radio-button__circle"></div>
140
+ <span class="ivds-radio-button__label">Email</span>
141
+ </label>
142
+
143
+ <label class="ivds-radio-button">
144
+ <input type="radio" class="ivds-radio-button__input" name="contact-method" value="phone" />
145
+ <div class="ivds-radio-button__circle"></div>
146
+ <span class="ivds-radio-button__label">Phone</span>
147
+ </label>
148
+
149
+ <label class="ivds-radio-button">
150
+ <input type="radio" class="ivds-radio-button__input" name="contact-method" value="sms" />
151
+ <div class="ivds-radio-button__circle"></div>
152
+ <span class="ivds-radio-button__label">SMS</span>
153
+ </label>
154
+ </div>
155
+
156
+ <div class="ivds-radio-button-group ivds-radio-button-group--horizontal">
157
+ <div class="ivds-radio-button-group__label ivds-radio-button-group__label--required">
158
+ Account Type
159
+ </div>
160
+
161
+ <label class="ivds-radio-button">
162
+ <input type="radio" class="ivds-radio-button__input" name="account-type" value="personal" required />
163
+ <div class="ivds-radio-button__circle"></div>
164
+ <span class="ivds-radio-button__label">Personal</span>
165
+ </label>
166
+
167
+ <label class="ivds-radio-button">
168
+ <input type="radio" class="ivds-radio-button__input" name="account-type" value="business" />
169
+ <div class="ivds-radio-button__circle"></div>
170
+ <span class="ivds-radio-button__label">Business</span>
171
+ </label>
172
+ </div>
173
+ </div>
174
+ `;
175
+
176
+ // Card variant
177
+ export const CardVariant = () => `
178
+ <div style="display: flex; flex-direction: column; gap: 1rem; max-width: 400px;">
179
+ <label class="ivds-radio-button">
180
+ <input type="radio" class="ivds-radio-button__input" name="plan-selection" value="premium" />
181
+ <div class="ivds-radio-button__circle"></div>
182
+ <div class="ivds-radio-button--card">
183
+ <div class="ivds-radio-button__label" style="font-weight: 500; margin-bottom: 0.25rem;">
184
+ Premium Plan - $29/month
185
+ </div>
186
+ <div class="ivds-radio-button__description" style="margin-left: 0;">
187
+ Access to all features, priority support, and advanced analytics.
188
+ </div>
189
+ </div>
190
+ </label>
191
+
192
+ <label class="ivds-radio-button">
193
+ <input type="radio" class="ivds-radio-button__input" name="plan-selection" value="basic" />
194
+ <div class="ivds-radio-button__circle"></div>
195
+ <div class="ivds-radio-button--card">
196
+ <div class="ivds-radio-button__label" style="font-weight: 500; margin-bottom: 0.25rem;">
197
+ Basic Plan - $9/month
198
+ </div>
199
+ <div class="ivds-radio-button__description" style="margin-left: 0;">
200
+ Essential features for getting started.
201
+ </div>
202
+ </div>
203
+ </label>
204
+
205
+ <label class="ivds-radio-button">
206
+ <input type="radio" class="ivds-radio-button__input" name="plan-selection" value="free" checked />
207
+ <div class="ivds-radio-button__circle"></div>
208
+ <div class="ivds-radio-button--card">
209
+ <div class="ivds-radio-button__label" style="font-weight: 500; margin-bottom: 0.25rem;">
210
+ Free Plan - $0/month
211
+ </div>
212
+ <div class="ivds-radio-button__description" style="margin-left: 0;">
213
+ Limited features with basic functionality.
214
+ </div>
215
+ </div>
216
+ </label>
217
+ </div>
218
+ `;
219
+
220
+ // Radio button group with error
221
+ export const GroupWithError = () => `
222
+ <div class="ivds-radio-button-group">
223
+ <div class="ivds-radio-button-group__label ivds-radio-button-group__label--required">
224
+ Shipping Method
225
+ </div>
226
+ <div class="ivds-radio-button-group__description">
227
+ Please select a shipping method to continue.
228
+ </div>
229
+
230
+ <label class="ivds-radio-button ivds-radio-button--error">
231
+ <input type="radio" class="ivds-radio-button__input" name="shipping-method" value="standard" />
232
+ <div class="ivds-radio-button__circle"></div>
233
+ <div>
234
+ <span class="ivds-radio-button__label">Standard Shipping</span>
235
+ <div class="ivds-radio-button__description">
236
+ 5-7 business days - Free
237
+ </div>
238
+ </div>
239
+ </label>
240
+
241
+ <label class="ivds-radio-button ivds-radio-button--error">
242
+ <input type="radio" class="ivds-radio-button__input" name="shipping-method" value="express" />
243
+ <div class="ivds-radio-button__circle"></div>
244
+ <div>
245
+ <span class="ivds-radio-button__label">Express Shipping</span>
246
+ <div class="ivds-radio-button__description">
247
+ 2-3 business days - $9.99
248
+ </div>
249
+ </div>
250
+ </label>
251
+
252
+ <label class="ivds-radio-button ivds-radio-button--error">
253
+ <input type="radio" class="ivds-radio-button__input" name="shipping-method" value="overnight" />
254
+ <div class="ivds-radio-button__circle"></div>
255
+ <div>
256
+ <span class="ivds-radio-button__label">Overnight Shipping</span>
257
+ <div class="ivds-radio-button__description">
258
+ Next business day - $24.99
259
+ </div>
260
+ </div>
261
+ </label>
262
+
263
+ <div class="ivds-radio-button-group__error">
264
+ Please select a shipping method.
265
+ </div>
266
+ </div>
267
+ `;
268
+
269
+ // Legacy radio component (for backward compatibility)
270
+ export const LegacyRadio = () => `
271
+ <div style="display: flex; flex-direction: column; gap: 1rem;">
272
+ <div style="font-weight: 500; margin-bottom: 0.5rem;">Legacy Radio Component:</div>
273
+
274
+ <label class="ivds-radio">
275
+ <input type="radio" class="ivds-radio__input" name="legacy-example" />
276
+ <div class="ivds-radio__button"></div>
277
+ <span class="ivds-radio__label">Option 1</span>
278
+ </label>
279
+
280
+ <label class="ivds-radio">
281
+ <input type="radio" class="ivds-radio__input" name="legacy-example" checked />
282
+ <div class="ivds-radio__button"></div>
283
+ <span class="ivds-radio__label">Option 2 (Selected)</span>
284
+ </label>
285
+
286
+ <label class="ivds-radio">
287
+ <input type="radio" class="ivds-radio__input" name="legacy-example" disabled />
288
+ <div class="ivds-radio__button"></div>
289
+ <span class="ivds-radio__label">Option 3 (Disabled)</span>
290
+ </label>
291
+ </div>
292
+ `;
293
+
294
+ // Accessibility example
295
+ export const AccessibilityFeatures = () => `
296
+ <div style="display: flex; flex-direction: column; gap: 1.5rem; max-width: 500px;">
297
+ <fieldset class="ivds-radio-button-group" style="border: none; padding: 0; margin: 0;">
298
+ <legend class="ivds-radio-button-group__label">
299
+ Notification Preferences
300
+ </legend>
301
+ <div class="ivds-radio-button-group__description">
302
+ Choose how often you'd like to receive notifications.
303
+ </div>
304
+
305
+ <label class="ivds-radio-button">
306
+ <input
307
+ type="radio"
308
+ class="ivds-radio-button__input"
309
+ name="notifications"
310
+ value="immediate"
311
+ id="immediate-notifications"
312
+ aria-describedby="immediate-description"
313
+ />
314
+ <div class="ivds-radio-button__circle"></div>
315
+ <div>
316
+ <span class="ivds-radio-button__label">Immediate</span>
317
+ <div id="immediate-description" class="ivds-radio-button__description">
318
+ Receive notifications as soon as events occur.
319
+ </div>
320
+ </div>
321
+ </label>
322
+
323
+ <label class="ivds-radio-button">
324
+ <input
325
+ type="radio"
326
+ class="ivds-radio-button__input"
327
+ name="notifications"
328
+ value="daily"
329
+ id="daily-notifications"
330
+ aria-describedby="daily-description"
331
+ />
332
+ <div class="ivds-radio-button__circle"></div>
333
+ <div>
334
+ <span class="ivds-radio-button__label">Daily Summary</span>
335
+ <div id="daily-description" class="ivds-radio-button__description">
336
+ Receive a daily digest of all notifications.
337
+ </div>
338
+ </div>
339
+ </label>
340
+
341
+ <label class="ivds-radio-button">
342
+ <input
343
+ type="radio"
344
+ class="ivds-radio-button__input"
345
+ name="notifications"
346
+ value="weekly"
347
+ id="weekly-notifications"
348
+ aria-describedby="weekly-description"
349
+ checked
350
+ />
351
+ <div class="ivds-radio-button__circle"></div>
352
+ <div>
353
+ <span class="ivds-radio-button__label">Weekly Summary</span>
354
+ <div id="weekly-description" class="ivds-radio-button__description">
355
+ Receive a weekly digest of all notifications.
356
+ </div>
357
+ </div>
358
+ </label>
359
+
360
+ <label class="ivds-radio-button">
361
+ <input
362
+ type="radio"
363
+ class="ivds-radio-button__input"
364
+ name="notifications"
365
+ value="none"
366
+ id="no-notifications"
367
+ aria-describedby="none-description"
368
+ />
369
+ <div class="ivds-radio-button__circle"></div>
370
+ <div>
371
+ <span class="ivds-radio-button__label">No Notifications</span>
372
+ <div id="none-description" class="ivds-radio-button__description">
373
+ Turn off all notifications.
374
+ </div>
375
+ </div>
376
+ </label>
377
+ </fieldset>
378
+ </div>
379
+ `;
@@ -0,0 +1,261 @@
1
+ // Tag component mixins and private styles
2
+ // This file contains mixins for tag variants, sizes, and internal utilities
3
+
4
+ @use '../../variables/variables' as vars;
5
+
6
+ // Base tag mixin with common styles
7
+ @mixin tag-base {
8
+ display: inline-flex;
9
+ align-items: center;
10
+ font-family: var(--fontFamily-sans, system-ui, -apple-system, sans-serif);
11
+ font-weight: var(--fontWeight-medium, 500);
12
+ line-height: var(--lineHeight-tight, 1.25);
13
+ border-radius: var(--borderRadius-md, 0.375rem);
14
+ border: var(--borderWidth-1, 1px) solid transparent;
15
+ text-decoration: none;
16
+ white-space: nowrap;
17
+ transition: all 0.15s ease-in-out;
18
+ user-select: none;
19
+
20
+ &:focus-within {
21
+ outline: 2px solid var(--color-brand-primary-500, #0ea5e9);
22
+ outline-offset: 2px;
23
+ }
24
+ }
25
+
26
+ // Tag variant mixin
27
+ @mixin tag-variant($bg-color, $text-color, $border-color: transparent, $hover-bg: null, $hover-border: null) {
28
+ background-color: $bg-color;
29
+ color: $text-color;
30
+ border-color: $border-color;
31
+
32
+ @if $hover-bg {
33
+ &:hover {
34
+ background-color: $hover-bg;
35
+
36
+ @if $hover-border {
37
+ border-color: $hover-border;
38
+ }
39
+ }
40
+ }
41
+ }
42
+
43
+ // Tag size mixin
44
+ @mixin tag-size($padding-y, $padding-x, $font-size, $min-height: null) {
45
+ padding: $padding-y $padding-x;
46
+ font-size: $font-size;
47
+
48
+ @if $min-height {
49
+ min-height: $min-height;
50
+ }
51
+ }
52
+
53
+ // Tag with icon mixin
54
+ @mixin tag-with-icon($gap: var(--spacing-2, 0.5rem)) {
55
+ gap: $gap;
56
+
57
+ .ivds-tag__icon {
58
+ display: inline-flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ flex-shrink: 0;
62
+
63
+ svg {
64
+ width: 1em;
65
+ height: 1em;
66
+ fill: currentcolor;
67
+ }
68
+ }
69
+ }
70
+
71
+ // Removable tag mixin
72
+ @mixin tag-removable {
73
+ padding-right: var(--spacing-1, 0.25rem);
74
+
75
+ .ivds-tag__remove {
76
+ display: inline-flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ margin-left: var(--spacing-2, 0.5rem);
80
+ padding: var(--spacing-1, 0.25rem);
81
+ background: transparent;
82
+ border: none;
83
+ border-radius: var(--borderRadius-sm, 0.25rem);
84
+ cursor: pointer;
85
+ color: inherit;
86
+ opacity: 0.7;
87
+ transition: opacity 0.15s ease-in-out, background-color 0.15s ease-in-out;
88
+
89
+ &:hover {
90
+ opacity: 1;
91
+ background-color: rgba(0, 0, 0, 0.1);
92
+ }
93
+
94
+ &:focus {
95
+ outline: 2px solid var(--color-brand-primary-500, #0ea5e9);
96
+ outline-offset: 1px;
97
+ opacity: 1;
98
+ }
99
+
100
+ &:active {
101
+ transform: scale(0.95);
102
+ }
103
+
104
+ svg {
105
+ width: 0.875em;
106
+ height: 0.875em;
107
+ fill: currentcolor;
108
+ }
109
+ }
110
+ }
111
+
112
+ // Tag link mixin (for clickable tags)
113
+ @mixin tag-link {
114
+ cursor: pointer;
115
+ text-decoration: none;
116
+
117
+ &:hover {
118
+ text-decoration: none;
119
+ }
120
+
121
+ &:focus {
122
+ outline: 2px solid var(--color-brand-primary-500, #0ea5e9);
123
+ outline-offset: 2px;
124
+ }
125
+
126
+ &:active {
127
+ transform: translateY(1px);
128
+ }
129
+ }
130
+
131
+ // Tag outlined variant mixin
132
+ @mixin tag-outlined($border-color, $text-color, $hover-bg: null) {
133
+ background-color: transparent;
134
+ border-color: $border-color;
135
+ color: $text-color;
136
+
137
+ @if $hover-bg {
138
+ &:hover {
139
+ background-color: $hover-bg;
140
+ }
141
+ }
142
+ }
143
+
144
+ // Tag solid variant mixin (for high contrast)
145
+ @mixin tag-solid($bg-color, $text-color, $hover-bg: null) {
146
+ background-color: $bg-color;
147
+ color: $text-color;
148
+ border-color: $bg-color;
149
+
150
+ @if $hover-bg {
151
+ &:hover {
152
+ background-color: $hover-bg;
153
+ border-color: $hover-bg;
154
+ }
155
+ }
156
+ }
157
+
158
+ // Tag group mixin
159
+ @mixin tag-group($gap: var(--spacing-2, 0.5rem)) {
160
+ display: flex;
161
+ flex-wrap: wrap;
162
+ gap: $gap;
163
+ align-items: center;
164
+ }
165
+
166
+ // Tag size variants
167
+ @mixin tag-small {
168
+ @include tag-size(var(--spacing-1, 0.25rem), var(--spacing-2, 0.5rem), var(--fontSize-xs, 0.75rem), 20px);
169
+
170
+ .ivds-tag__icon svg {
171
+ width: 0.875em;
172
+ height: 0.875em;
173
+ }
174
+
175
+ &.ivds-tag--removable {
176
+ .ivds-tag__remove {
177
+ margin-left: var(--spacing-1, 0.25rem);
178
+ padding: 2px;
179
+
180
+ svg {
181
+ width: 0.75em;
182
+ height: 0.75em;
183
+ }
184
+ }
185
+ }
186
+ }
187
+
188
+ @mixin tag-large {
189
+ @include tag-size(var(--spacing-2, 0.5rem), var(--spacing-4, 1rem), var(--fontSize-base, 1rem), 32px);
190
+
191
+ .ivds-tag__icon svg {
192
+ width: 1.125em;
193
+ height: 1.125em;
194
+ }
195
+
196
+ &.ivds-tag--removable {
197
+ .ivds-tag__remove {
198
+ margin-left: var(--spacing-3, 0.75rem);
199
+ padding: var(--spacing-1, 0.25rem);
200
+
201
+ svg {
202
+ width: 1em;
203
+ height: 1em;
204
+ }
205
+ }
206
+ }
207
+ }
208
+
209
+ // Tag status variants (for different semantic meanings)
210
+ @mixin tag-status-new {
211
+ position: relative;
212
+
213
+ &::after {
214
+ content: '';
215
+ position: absolute;
216
+ top: -2px;
217
+ right: -2px;
218
+ width: 6px;
219
+ height: 6px;
220
+ background-color: var(--color-semantic-success-500, #22c55e);
221
+ border-radius: 50%;
222
+ border: 1px solid var(--color-semantic-neutral-50, #f8fafc);
223
+ }
224
+ }
225
+
226
+ @mixin tag-status-updated {
227
+ position: relative;
228
+
229
+ &::after {
230
+ content: '';
231
+ position: absolute;
232
+ top: -2px;
233
+ right: -2px;
234
+ width: 6px;
235
+ height: 6px;
236
+ background-color: var(--color-semantic-info-500, #3b82f6);
237
+ border-radius: 50%;
238
+ border: 1px solid var(--color-semantic-neutral-50, #f8fafc);
239
+ }
240
+ }
241
+
242
+ // Tag interactive states
243
+ @mixin tag-interactive {
244
+ cursor: pointer;
245
+
246
+ &:hover {
247
+ transform: translateY(-1px);
248
+ box-shadow: var(--shadow-sm, 0 1px 2px 0 rgba(0, 0, 0, 0.05));
249
+ }
250
+
251
+ &:active {
252
+ transform: translateY(0);
253
+ }
254
+ }
255
+
256
+ // Tag disabled state
257
+ @mixin tag-disabled {
258
+ opacity: 0.5;
259
+ cursor: not-allowed;
260
+ pointer-events: none;
261
+ }