@citizenplane/pimp 16.0.3 → 16.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.
Files changed (61) hide show
  1. package/dist/pimp.es.js +313 -285
  2. package/dist/pimp.umd.js +21 -21
  3. package/dist/style.css +1 -1
  4. package/package.json +2 -1
  5. package/src/components/CpHeading.vue +4 -5
  6. package/src/components/CpText.vue +141 -0
  7. package/src/components/index.ts +2 -0
  8. package/src/stories/BaseInputLabel.stories.ts +36 -9
  9. package/src/stories/Colors.mdx +9 -0
  10. package/src/stories/Colors.stories.ts +177 -0
  11. package/src/stories/CpAccordion.stories.ts +187 -158
  12. package/src/stories/CpAccordionGroup.stories.ts +50 -94
  13. package/src/stories/CpAirlineLogo.stories.ts +49 -28
  14. package/src/stories/CpAlert.stories.ts +195 -158
  15. package/src/stories/CpBadge.stories.ts +259 -193
  16. package/src/stories/CpButton.stories.ts +257 -426
  17. package/src/stories/CpCheckbox.stories.ts +101 -29
  18. package/src/stories/CpContextualMenu.stories.ts +9 -8
  19. package/src/stories/CpDate.stories.ts +52 -25
  20. package/src/stories/CpDatepicker.stories.ts +57 -88
  21. package/src/stories/CpDialog.stories.ts +22 -1
  22. package/src/stories/CpHeading.stories.ts +59 -20
  23. package/src/stories/CpIcon.stories.ts +98 -31
  24. package/src/stories/CpInput.stories.ts +142 -67
  25. package/src/stories/CpItemActions.stories.ts +22 -27
  26. package/src/stories/CpLoader.stories.ts +54 -6
  27. package/src/stories/CpMenuItem.stories.ts +52 -26
  28. package/src/stories/CpMultiselect.stories.ts +52 -71
  29. package/src/stories/CpPartnerBadge.stories.ts +53 -74
  30. package/src/stories/CpRadio.stories.ts +44 -48
  31. package/src/stories/CpRadioGroup.stories.ts +46 -39
  32. package/src/stories/CpSelect.stories.ts +98 -39
  33. package/src/stories/CpSelectMenu.stories.ts +49 -57
  34. package/src/stories/CpSelectableButton.stories.ts +170 -81
  35. package/src/stories/CpSwitch.stories.ts +135 -133
  36. package/src/stories/CpTable.stories.ts +54 -1
  37. package/src/stories/CpTableEmptyState.stories.ts +11 -7
  38. package/src/stories/CpTabs.stories.ts +22 -4
  39. package/src/stories/CpTelInput.stories.ts +25 -23
  40. package/src/stories/CpText.stories.ts +131 -0
  41. package/src/stories/CpTextarea.stories.ts +59 -23
  42. package/src/stories/CpToast.stories.ts +53 -103
  43. package/src/stories/CpTooltip.stories.ts +82 -77
  44. package/src/stories/CpTransitionCounter.stories.ts +4 -0
  45. package/src/stories/CpTransitionExpand.stories.ts +11 -6
  46. package/src/stories/CpTransitionListItems.stories.ts +5 -0
  47. package/src/stories/CpTransitionSize.stories.ts +8 -0
  48. package/src/stories/CpTransitionSlide.stories.ts +4 -0
  49. package/src/stories/CpTransitionTabContent.stories.ts +4 -0
  50. package/src/stories/Dimensions.mdx +9 -0
  51. package/src/stories/Dimensions.stories.ts +119 -0
  52. package/src/stories/Easings.mdx +9 -0
  53. package/src/stories/Easings.stories.ts +101 -0
  54. package/src/stories/FocusRings.mdx +9 -0
  55. package/src/stories/FocusRings.stories.ts +74 -0
  56. package/src/stories/Shadows.mdx +9 -0
  57. package/src/stories/Shadows.stories.ts +100 -0
  58. package/src/stories/Typography.mdx +9 -0
  59. package/src/stories/Typography.stories.ts +181 -0
  60. package/src/stories/documentationStyles.ts +2 -10
  61. package/src/stories/tokenUtils.ts +259 -0
@@ -4,8 +4,12 @@ import type { Meta, StoryObj } from '@storybook/vue3'
4
4
 
5
5
  import CpSwitch from '@/components/CpSwitch.vue'
6
6
 
7
+ import { docCellStyle, docLabelStyle, docRowWrapStyle } from '@/stories/documentationStyles'
8
+
9
+ const switchColors = ['blue', 'purple'] as const
10
+
7
11
  const meta = {
8
- title: 'Form/CpSwitch',
12
+ title: 'Atoms/CpSwitch',
9
13
  component: CpSwitch,
10
14
  argTypes: {
11
15
  autofocus: {
@@ -14,7 +18,7 @@ const meta = {
14
18
  },
15
19
  color: {
16
20
  control: 'select',
17
- options: ['blue', 'purple'],
21
+ options: switchColors,
18
22
  description: 'Color variant of the switch',
19
23
  },
20
24
  disabled: {
@@ -55,6 +59,9 @@ const meta = {
55
59
  export default meta
56
60
  type Story = StoryObj<typeof meta>
57
61
 
62
+ /**
63
+ * Default switch. Use the controls to experiment with each prop in isolation.
64
+ */
58
65
  export const Default: Story = {
59
66
  args: {
60
67
  label: 'Label',
@@ -74,100 +81,121 @@ export const Default: Story = {
74
81
  },
75
82
  template: `
76
83
  <div style="padding: 20px;">
77
- <CpSwitch
78
- v-model="value"
79
- v-bind="args"
80
- />
84
+ <CpSwitch v-model="value" v-bind="args" />
81
85
  </div>
82
86
  `,
83
87
  }),
84
88
  }
85
89
 
86
- export const WithHaptics: Story = {
87
- args: {
88
- ...Default.args,
89
- enableHaptics: true,
90
- },
91
- render: (args) => ({
90
+ /* -------------------------------------------------------------------------- */
91
+ /* States */
92
+ /* -------------------------------------------------------------------------- */
93
+
94
+ /**
95
+ * Off, on, disabled off and disabled on compared side by side.
96
+ */
97
+ export const States: Story = {
98
+ parameters: { controls: { disable: true } },
99
+ render: () => ({
92
100
  components: { CpSwitch },
93
101
  setup() {
94
- const value = ref(false)
95
- return { args, value }
102
+ return { docCellStyle, docLabelStyle, docRowWrapStyle }
96
103
  },
97
104
  template: `
98
- <div style="padding: 20px;">
99
- <CpSwitch
100
- v-model="value"
101
- v-bind="args"
102
- />
105
+ <div :style="docRowWrapStyle">
106
+ <div :style="docCellStyle">
107
+ <span :style="docLabelStyle">Off</span>
108
+ <CpSwitch :model-value="false" label="Label" />
109
+ </div>
110
+ <div :style="docCellStyle">
111
+ <span :style="docLabelStyle">On</span>
112
+ <CpSwitch :model-value="true" label="Label" />
113
+ </div>
114
+ <div :style="docCellStyle">
115
+ <span :style="docLabelStyle">Disabled off</span>
116
+ <CpSwitch :model-value="false" :disabled="true" label="Label" />
117
+ </div>
118
+ <div :style="docCellStyle">
119
+ <span :style="docLabelStyle">Disabled on</span>
120
+ <CpSwitch :model-value="true" :disabled="true" label="Label" />
121
+ </div>
103
122
  </div>
104
123
  `,
105
124
  }),
106
125
  }
107
126
 
108
- export const Disabled: Story = {
109
- args: {
110
- ...Default.args,
111
- disabled: true,
112
- },
113
- }
127
+ /* -------------------------------------------------------------------------- */
128
+ /* Colors */
129
+ /* -------------------------------------------------------------------------- */
114
130
 
115
- export const DisabledChecked: Story = {
116
- args: {
117
- ...Default.args,
118
- disabled: true,
119
- modelValue: true,
120
- },
121
- }
122
-
123
- export const Required: Story = {
124
- args: {
125
- ...Default.args,
126
- isRequired: true,
127
- },
128
- render: (args) => ({
131
+ /**
132
+ * Color variants rendered side by side.
133
+ */
134
+ export const Colors: Story = {
135
+ parameters: { controls: { disable: true } },
136
+ render: () => ({
129
137
  components: { CpSwitch },
130
138
  setup() {
131
- const value = ref(false)
132
- return { args, value }
139
+ return { switchColors, docCellStyle, docLabelStyle, docRowWrapStyle }
133
140
  },
134
141
  template: `
135
- <div style="padding: 20px;">
136
- <CpSwitch
137
- v-model="value"
138
- v-bind="args"
139
- />
142
+ <div :style="docRowWrapStyle">
143
+ <div v-for="color in switchColors" :key="color" :style="docCellStyle">
144
+ <span :style="docLabelStyle">{{ color }}</span>
145
+ <CpSwitch :model-value="true" :color="color" label="Label" />
146
+ </div>
140
147
  </div>
141
148
  `,
142
149
  }),
143
150
  }
144
151
 
145
- export const Reversed: Story = {
146
- args: {
147
- ...Default.args,
148
- reverseLabel: true,
149
- },
150
- render: (args) => ({
152
+ /* -------------------------------------------------------------------------- */
153
+ /* Sizes */
154
+ /* -------------------------------------------------------------------------- */
155
+
156
+ /**
157
+ * The switch inherits its size from the font-size of its container. Wrap it
158
+ * inside a `transform: scale()` to obtain smaller or larger switches.
159
+ */
160
+ export const Sizes: Story = {
161
+ parameters: { controls: { disable: true } },
162
+ render: () => ({
151
163
  components: { CpSwitch },
152
164
  setup() {
153
- const value = ref(false)
154
- return { args, value }
165
+ const values = ref({
166
+ sm: false,
167
+ md: true,
168
+ lg: false,
169
+ })
170
+ return { values }
155
171
  },
156
172
  template: `
157
- <div style="padding: 20px;">
158
- <CpSwitch
159
- v-model="value"
160
- v-bind="args"
161
- />
173
+ <div style="padding: 20px; display: flex; flex-direction: column; gap: 20px;">
174
+ <div style="transform: scale(0.8); transform-origin: left center;">
175
+ <CpSwitch v-model="values.sm" label="Height 16px" />
176
+ </div>
177
+ <div>
178
+ <CpSwitch v-model="values.md" label="Height 20px" />
179
+ </div>
180
+ <div style="transform: scale(1.2); transform-origin: left center;">
181
+ <CpSwitch v-model="values.lg" label="Height 24px" />
182
+ </div>
162
183
  </div>
163
184
  `,
164
185
  }),
165
186
  }
166
187
 
167
- export const WithHelper: Story = {
188
+ /* -------------------------------------------------------------------------- */
189
+ /* Variants */
190
+ /* -------------------------------------------------------------------------- */
191
+
192
+ /**
193
+ * Display the label before the switch using `reverseLabel`.
194
+ */
195
+ export const Reversed: Story = {
168
196
  args: {
169
197
  ...Default.args,
170
- helper: 'This is a helper text that provides additional information',
198
+ reverseLabel: true,
171
199
  },
172
200
  render: (args) => ({
173
201
  components: { CpSwitch },
@@ -177,42 +205,54 @@ export const WithHelper: Story = {
177
205
  },
178
206
  template: `
179
207
  <div style="padding: 20px;">
180
- <CpSwitch
181
- v-model="value"
182
- v-bind="args"
183
- />
208
+ <CpSwitch v-model="value" v-bind="args" />
184
209
  </div>
185
210
  `,
186
211
  }),
187
212
  }
188
213
 
189
- export const WithTooltip: Story = {
190
- args: {
191
- ...Default.args,
192
- tooltip: 'This is a tooltip text',
193
- },
194
- render: (args) => ({
214
+ /**
215
+ * Add a helper text, a tooltip next to the label, or both.
216
+ */
217
+ export const HelpAndTooltip: Story = {
218
+ parameters: { controls: { disable: true } },
219
+ render: () => ({
195
220
  components: { CpSwitch },
196
221
  setup() {
197
- const value = ref(false)
198
- return { args, value }
222
+ const values = ref({ helper: false, tooltip: false, both: false })
223
+ return { values, docCellStyle, docLabelStyle, docRowWrapStyle }
199
224
  },
200
225
  template: `
201
- <div style="padding: 20px;">
202
- <CpSwitch
203
- v-model="value"
204
- v-bind="args"
205
- />
226
+ <div :style="docRowWrapStyle">
227
+ <div :style="docCellStyle">
228
+ <span :style="docLabelStyle">With helper</span>
229
+ <CpSwitch v-model="values.helper" label="Label" helper="This is a helper text that provides additional information" />
230
+ </div>
231
+ <div :style="docCellStyle">
232
+ <span :style="docLabelStyle">With tooltip</span>
233
+ <CpSwitch v-model="values.tooltip" label="Label" tooltip="This is a tooltip text" />
234
+ </div>
235
+ <div :style="docCellStyle">
236
+ <span :style="docLabelStyle">With both</span>
237
+ <CpSwitch
238
+ v-model="values.both"
239
+ label="Label"
240
+ helper="This is a helper text"
241
+ tooltip="This is a tooltip text"
242
+ />
243
+ </div>
206
244
  </div>
207
245
  `,
208
246
  }),
209
247
  }
210
248
 
211
- export const WithHelperAndTooltip: Story = {
249
+ /**
250
+ * Triggers a haptic feedback on supported devices when toggled.
251
+ */
252
+ export const WithHaptics: Story = {
212
253
  args: {
213
254
  ...Default.args,
214
- helper: 'This is a helper text that provides additional information',
215
- tooltip: 'This is a tooltip text',
255
+ enableHaptics: true,
216
256
  },
217
257
  render: (args) => ({
218
258
  components: { CpSwitch },
@@ -222,16 +262,21 @@ export const WithHelperAndTooltip: Story = {
222
262
  },
223
263
  template: `
224
264
  <div style="padding: 20px;">
225
- <CpSwitch
226
- v-model="value"
227
- v-bind="args"
228
- />
265
+ <CpSwitch v-model="value" v-bind="args" />
229
266
  </div>
230
267
  `,
231
268
  }),
232
269
  }
233
270
 
271
+ /* -------------------------------------------------------------------------- */
272
+ /* Group */
273
+ /* -------------------------------------------------------------------------- */
274
+
275
+ /**
276
+ * Multiple switches bound together, sharing the same `groupName`.
277
+ */
234
278
  export const SwitchGroup: Story = {
279
+ parameters: { controls: { disable: true } },
235
280
  render: () => ({
236
281
  components: { CpSwitch },
237
282
  setup() {
@@ -239,59 +284,16 @@ export const SwitchGroup: Story = {
239
284
  switch1: false,
240
285
  switch2: true,
241
286
  switch3: false,
287
+ switch4: false,
242
288
  })
243
289
  return { switches }
244
290
  },
245
291
  template: `
246
292
  <div style="padding: 20px; display: flex; flex-direction: column; gap: 16px;">
247
- <CpSwitch
248
- v-model="switches.switch1"
249
- label="First Switch"
250
- group-name="switch-group"
251
- />
252
- <CpSwitch
253
- v-model="switches.switch2"
254
- label="Second Switch"
255
- group-name="switch-group"
256
- />
257
- <CpSwitch
258
- v-model="switches.switch3"
259
- label="Third Switch"
260
- group-name="switch-group"
261
- disabled
262
- />
263
- <CpSwitch
264
- v-model="switches.switch4"
265
- label="Fourth Switch"
266
- group-name="switch-group"
267
- />
268
- </div>
269
- `,
270
- }),
271
- }
272
-
273
- export const Sizes: Story = {
274
- render: () => ({
275
- components: { CpSwitch },
276
- setup() {
277
- const values = ref({
278
- sm: false,
279
- md: true,
280
- lg: false,
281
- })
282
- return { values }
283
- },
284
- template: `
285
- <div style="padding: 20px; display: flex; flex-direction: column; gap: 20px;">
286
- <div style="transform: scale(0.8); transform-origin: left center;">
287
- <CpSwitch v-model="values.sm" label="Height 16px" />
288
- </div>
289
- <div>
290
- <CpSwitch v-model="values.md" label="Height 20px" />
291
- </div>
292
- <div style="transform: scale(1.2); transform-origin: left center;">
293
- <CpSwitch v-model="values.lg" label="Height 24px" />
294
- </div>
293
+ <CpSwitch v-model="switches.switch1" label="First Switch" group-name="switch-group" />
294
+ <CpSwitch v-model="switches.switch2" label="Second Switch" group-name="switch-group" />
295
+ <CpSwitch v-model="switches.switch3" label="Third Switch" group-name="switch-group" disabled />
296
+ <CpSwitch v-model="switches.switch4" label="Fourth Switch" group-name="switch-group" />
295
297
  </div>
296
298
  `,
297
299
  }),
@@ -8,7 +8,7 @@ import CpTable from '@/components/CpTable.vue'
8
8
  import { PAGINATION_FORMATS } from '@/constants'
9
9
 
10
10
  const meta = {
11
- title: 'Data display/CpTable',
11
+ title: 'Organisms/CpTable',
12
12
  component: CpTable,
13
13
  parameters: {
14
14
  backgrounds: {
@@ -34,6 +34,10 @@ const sampleData = [
34
34
  { name: 'Charlie Wilson', age: 42, email: 'charlie@example.com', status: 'Inactive', date: '2026-01-05' },
35
35
  ]
36
36
 
37
+ /**
38
+ * Default table with sample columns and rows. Use the controls to
39
+ * experiment with each prop in isolation.
40
+ */
37
41
  export const Default: Story = {
38
42
  args: {
39
43
  columns: sampleColumns,
@@ -66,6 +70,11 @@ export const Default: Story = {
66
70
  }),
67
71
  }
68
72
 
73
+ /**
74
+ * Enable the column manager so users can show/hide, pin and reorder
75
+ * columns. Individual columns expose `isHidden`, `isProtected` and
76
+ * `isFull` flags to control the initial layout.
77
+ */
69
78
  export const EnableColumnEdition: Story = {
70
79
  args: {
71
80
  ...Default.args,
@@ -80,6 +89,10 @@ export const EnableColumnEdition: Story = {
80
89
  },
81
90
  }
82
91
 
92
+ /**
93
+ * Rows become interactive — hover highlights and the `onRowClick` event
94
+ * fires on click.
95
+ */
83
96
  export const ClickableRows: Story = {
84
97
  args: {
85
98
  ...Default.args,
@@ -87,6 +100,9 @@ export const ClickableRows: Story = {
87
100
  },
88
101
  }
89
102
 
103
+ /**
104
+ * Loading state — skeleton rows are displayed while the data is fetched.
105
+ */
90
106
  export const Loading: Story = {
91
107
  args: {
92
108
  ...Default.args,
@@ -94,6 +110,9 @@ export const Loading: Story = {
94
110
  },
95
111
  }
96
112
 
113
+ /**
114
+ * Empty dataset — the `noResultPlaceholder` copy replaces the rows.
115
+ */
97
116
  export const Empty: Story = {
98
117
  args: {
99
118
  ...Default.args,
@@ -101,6 +120,10 @@ export const Empty: Story = {
101
120
  },
102
121
  }
103
122
 
123
+ /**
124
+ * Configure pagination through the `pagination` prop. `format` switches
125
+ * between `PAGES` and alternative formats.
126
+ */
104
127
  export const WithPagination: Story = {
105
128
  args: {
106
129
  ...Default.args,
@@ -112,6 +135,10 @@ export const WithPagination: Story = {
112
135
  },
113
136
  }
114
137
 
138
+ /**
139
+ * Group rows by providing an array of `{ groupBy, rows }` objects. A
140
+ * custom `#groupBy` slot renders the section header.
141
+ */
115
142
  export const WithGroupBy: Story = {
116
143
  args: {
117
144
  ...Default.args,
@@ -152,6 +179,12 @@ export const WithGroupBy: Story = {
152
179
  }),
153
180
  }
154
181
 
182
+ /**
183
+ * Attach per-row actions through `rowOptions`. `quickOptionsLimit`
184
+ * controls how many actions appear inline before the overflow menu; each
185
+ * action can be async (`isAsync` + `isLoading`) or critical
186
+ * (`isCritical`).
187
+ */
155
188
  export const WithCustomRowOptions: Story = {
156
189
  args: {
157
190
  ...Default.args,
@@ -219,6 +252,10 @@ export const WithCustomRowOptions: Story = {
219
252
  }),
220
253
  }
221
254
 
255
+ /**
256
+ * Rows without a "primary" action — every option lives in the overflow
257
+ * menu. Useful when actions are secondary to the row click.
258
+ */
222
259
  export const WithoutDefaultAction: Story = {
223
260
  args: {
224
261
  ...Default.args,
@@ -267,6 +304,10 @@ export const WithoutDefaultAction: Story = {
267
304
  }),
268
305
  }
269
306
 
307
+ /**
308
+ * Setting `quickOptionsLimit: 0` forces the primary action to appear
309
+ * inline without any overflow menu.
310
+ */
270
311
  export const WithOnlyDefaultAction: Story = {
271
312
  args: {
272
313
  ...Default.args,
@@ -321,6 +362,10 @@ export const WithOnlyDefaultAction: Story = {
321
362
  }),
322
363
  }
323
364
 
365
+ /**
366
+ * When the table overflows horizontally, a subtle scroll cue appears on
367
+ * the right edge to hint at the extra content.
368
+ */
324
369
  export const ScrollCue: Story = {
325
370
  args: {
326
371
  ...Default.args,
@@ -371,6 +416,10 @@ export const ScrollCue: Story = {
371
416
  }),
372
417
  }
373
418
 
419
+ /**
420
+ * A row can override the column layout with `{ fullWidth: '...' }` to
421
+ * spread a single cell across the whole table (e.g. summaries or notes).
422
+ */
374
423
  export const FullWidthRow: Story = {
375
424
  args: {
376
425
  ...Default.args,
@@ -393,6 +442,10 @@ export const FullWidthRow: Story = {
393
442
  }),
394
443
  }
395
444
 
445
+ /**
446
+ * Mark a row as selected by adding `isSelected: true`. The row adopts a
447
+ * highlighted background.
448
+ */
396
449
  export const SelectedRow: Story = {
397
450
  args: {
398
451
  ...Default.args,
@@ -1,9 +1,9 @@
1
- import type { Meta, StoryObj } from '@storybook/vue3'
1
+ import type { Args, Meta, StoryObj } from '@storybook/vue3'
2
2
 
3
3
  import CpTableEmptyState from '@/components/CpTableEmptyState.vue'
4
4
 
5
5
  const meta = {
6
- title: 'Data display/CpTableEmptyState',
6
+ title: 'Molecules/CpTableEmptyState',
7
7
  component: CpTableEmptyState,
8
8
  argTypes: {
9
9
  placeholder: {
@@ -12,24 +12,28 @@ const meta = {
12
12
  },
13
13
  },
14
14
  decorators: [
15
- () => ({ template: '<div style="padding: 20px; border-radius: 8px; background-color: #fff;"><story/></div>' }),
15
+ () => ({
16
+ template: '<div style="padding: 20px; border-radius: 8px; background-color: #fff;"><story /></div>',
17
+ }),
16
18
  ],
17
19
  } satisfies Meta<typeof CpTableEmptyState>
18
20
 
19
21
  export default meta
20
22
  type Story = StoryObj<typeof meta>
21
23
 
24
+ /**
25
+ * Empty-state block rendered inside a table when no rows match the
26
+ * current filters. Use the controls to experiment with each prop.
27
+ */
22
28
  export const Default: Story = {
23
29
  args: {
24
30
  placeholder: 'No results found',
25
31
  },
26
- render: (args) => ({
32
+ render: (args: Args) => ({
27
33
  components: { CpTableEmptyState },
28
34
  setup() {
29
35
  return { args }
30
36
  },
31
- template: `
32
- <CpTableEmptyState v-bind="args" />
33
- `,
37
+ template: '<CpTableEmptyState v-bind="args" />',
34
38
  }),
35
39
  }
@@ -6,7 +6,7 @@ import type { Args, Meta, StoryObj } from '@storybook/vue3'
6
6
  import CpTabs from '@/components/CpTabs.vue'
7
7
 
8
8
  const meta = {
9
- title: 'Navigation/CpTabs',
9
+ title: 'Molecules/CpTabs',
10
10
  component: CpTabs,
11
11
  argTypes: {
12
12
  defaultActiveIndex: {
@@ -28,15 +28,18 @@ export default meta
28
28
 
29
29
  type Story = StoryObj<typeof meta>
30
30
 
31
- const defaultTemplate = '<CpTabs v-bind="args" @on-tab-click="args.onOnTabClick" />'
32
31
  const defaultRender = (args: Args) => ({
33
32
  components: { CpTabs },
34
33
  setup() {
35
34
  return { args }
36
35
  },
37
- template: defaultTemplate,
36
+ template: '<CpTabs v-bind="args" @on-tab-click="args.onOnTabClick" />',
38
37
  })
39
38
 
39
+ /**
40
+ * Default tabs rendered from an array of `{ title }` objects. Use the
41
+ * controls to experiment with each prop in isolation.
42
+ */
40
43
  export const Default: Story = {
41
44
  args: {
42
45
  defaultActiveIndex: 0,
@@ -47,6 +50,10 @@ export const Default: Story = {
47
50
  render: defaultRender,
48
51
  }
49
52
 
53
+ /**
54
+ * Tabs augmented with leading icons through the `icon` property on each
55
+ * tab object.
56
+ */
50
57
  export const WithIcons: Story = {
51
58
  args: {
52
59
  ...Default.args,
@@ -59,6 +66,10 @@ export const WithIcons: Story = {
59
66
  render: defaultRender,
60
67
  }
61
68
 
69
+ /**
70
+ * Tabs that display a count badge on the right — typically used for
71
+ * notifications or list sizes.
72
+ */
62
73
  export const WithCounts: Story = {
63
74
  args: {
64
75
  ...Default.args,
@@ -71,6 +82,9 @@ export const WithCounts: Story = {
71
82
  render: defaultRender,
72
83
  }
73
84
 
85
+ /**
86
+ * Icons and counts combined on the same tab.
87
+ */
74
88
  export const WithIconsAndCounts: Story = {
75
89
  args: {
76
90
  ...Default.args,
@@ -83,6 +97,10 @@ export const WithIconsAndCounts: Story = {
83
97
  render: defaultRender,
84
98
  }
85
99
 
100
+ /**
101
+ * Tabs nested inside a dialog — verifies the integration with overlay
102
+ * surfaces and the focus ring behaviour.
103
+ */
86
104
  export const InDialog: Story = {
87
105
  args: {
88
106
  ...Default.args,
@@ -105,7 +123,7 @@ export const InDialog: Story = {
105
123
  <CpTabs v-bind="args" @on-tab-click="args.onOnTabClick" v-if="isVisible" />
106
124
  </cp-dialog>
107
125
  </cp-transition-dialog>
108
- <div style="display: flex; justify-content: center; align-items: center; min-height: 240px; min-width:240px;">
126
+ <div style="display: flex; justify-content: center; align-items: center; min-height: 240px; min-width: 240px;">
109
127
  <cp-button @click="isVisible = !isVisible">Open dialog</cp-button>
110
128
  </div>
111
129
  `,