@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 CpCheckbox from '@/components/CpCheckbox.vue'
6
6
 
7
+ import { docCellStyle, docLabelStyle, docRowWrapStyle } from '@/stories/documentationStyles'
8
+
9
+ const checkboxColors = ['accent', 'blue'] as const
10
+
7
11
  const meta = {
8
- title: 'Form/CpCheckbox',
12
+ title: 'Atoms/CpCheckbox',
9
13
  component: CpCheckbox,
10
14
  argTypes: {
11
15
  modelValue: {
@@ -30,7 +34,7 @@ const meta = {
30
34
  },
31
35
  color: {
32
36
  control: 'select',
33
- options: ['accent', 'blue'],
37
+ options: checkboxColors,
34
38
  description: 'Color variant of the checkbox',
35
39
  },
36
40
  reverseLabel: {
@@ -55,6 +59,9 @@ const meta = {
55
59
  export default meta
56
60
  type Story = StoryObj<typeof meta>
57
61
 
62
+ /**
63
+ * Default checkbox. Use the controls to experiment with each prop in isolation.
64
+ */
58
65
  export const Default: Story = {
59
66
  args: {
60
67
  checkboxLabel: 'checkbox label',
@@ -74,29 +81,85 @@ export const Default: Story = {
74
81
  },
75
82
  template: `
76
83
  <div style="padding: 20px;">
77
- <CpCheckbox
78
- v-model="value"
79
- v-bind="args"
80
- />
84
+ <CpCheckbox v-model="value" v-bind="args" />
81
85
  </div>
82
86
  `,
83
87
  }),
84
88
  }
85
89
 
86
- export const Checked: Story = {
87
- args: {
88
- ...Default.args,
89
- modelValue: true,
90
- },
90
+ /* -------------------------------------------------------------------------- */
91
+ /* States */
92
+ /* -------------------------------------------------------------------------- */
93
+
94
+ /**
95
+ * Every state available for the checkbox, compared side by side.
96
+ */
97
+ export const States: Story = {
98
+ parameters: { controls: { disable: true } },
99
+ render: () => ({
100
+ components: { CpCheckbox },
101
+ setup() {
102
+ return { docCellStyle, docLabelStyle, docRowWrapStyle }
103
+ },
104
+ template: `
105
+ <div :style="docRowWrapStyle">
106
+ <div :style="docCellStyle">
107
+ <span :style="docLabelStyle">Unchecked</span>
108
+ <CpCheckbox :model-value="false" checkbox-label="Label" />
109
+ </div>
110
+ <div :style="docCellStyle">
111
+ <span :style="docLabelStyle">Checked</span>
112
+ <CpCheckbox :model-value="true" checkbox-label="Label" />
113
+ </div>
114
+ <div :style="docCellStyle">
115
+ <span :style="docLabelStyle">Indeterminate</span>
116
+ <CpCheckbox :model-value="false" :indeterminate="true" checkbox-label="Label" />
117
+ </div>
118
+ <div :style="docCellStyle">
119
+ <span :style="docLabelStyle">Disabled</span>
120
+ <CpCheckbox :model-value="false" :is-disabled="true" checkbox-label="Label" />
121
+ </div>
122
+ <div :style="docCellStyle">
123
+ <span :style="docLabelStyle">Disabled checked</span>
124
+ <CpCheckbox :model-value="true" :is-disabled="true" checkbox-label="Label" />
125
+ </div>
126
+ </div>
127
+ `,
128
+ }),
91
129
  }
92
130
 
93
- export const Disabled: Story = {
94
- args: {
95
- ...Default.args,
96
- isDisabled: true,
97
- },
131
+ /* -------------------------------------------------------------------------- */
132
+ /* Colors */
133
+ /* -------------------------------------------------------------------------- */
134
+
135
+ /**
136
+ * Color variants rendered side by side.
137
+ */
138
+ export const Colors: Story = {
139
+ parameters: { controls: { disable: true } },
140
+ render: () => ({
141
+ components: { CpCheckbox },
142
+ setup() {
143
+ return { checkboxColors, docCellStyle, docLabelStyle, docRowWrapStyle }
144
+ },
145
+ template: `
146
+ <div :style="docRowWrapStyle">
147
+ <div v-for="color in checkboxColors" :key="color" :style="docCellStyle">
148
+ <span :style="docLabelStyle">{{ color }}</span>
149
+ <CpCheckbox :model-value="true" :color="color" checkbox-label="Label" />
150
+ </div>
151
+ </div>
152
+ `,
153
+ }),
98
154
  }
99
155
 
156
+ /* -------------------------------------------------------------------------- */
157
+ /* Variants */
158
+ /* -------------------------------------------------------------------------- */
159
+
160
+ /**
161
+ * Add a helper text below the label.
162
+ */
100
163
  export const WithHelper: Story = {
101
164
  args: {
102
165
  ...Default.args,
@@ -104,13 +167,9 @@ export const WithHelper: Story = {
104
167
  },
105
168
  }
106
169
 
107
- export const Blue: Story = {
108
- args: {
109
- ...Default.args,
110
- color: 'blue',
111
- },
112
- }
113
-
170
+ /**
171
+ * Display the label before the checkbox using `reverseLabel`.
172
+ */
114
173
  export const Reversed: Story = {
115
174
  args: {
116
175
  ...Default.args,
@@ -118,7 +177,16 @@ export const Reversed: Story = {
118
177
  },
119
178
  }
120
179
 
121
- export const Indeterminate: Story = {
180
+ /* -------------------------------------------------------------------------- */
181
+ /* Group patterns */
182
+ /* -------------------------------------------------------------------------- */
183
+
184
+ /**
185
+ * Parent-child checkbox pattern using the `indeterminate` state to represent
186
+ * a partial selection.
187
+ */
188
+ export const ParentChildGroup: Story = {
189
+ parameters: { controls: { disable: true } },
122
190
  render: () => ({
123
191
  components: { CpCheckbox },
124
192
  setup() {
@@ -175,7 +243,7 @@ export const Indeterminate: Story = {
175
243
  />
176
244
  </div>
177
245
  <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 4px; font-size: 14px;">
178
- <strong>Current state: </strong>
246
+ <strong>Current state: </strong>
179
247
  <span v-if="parentState.indeterminate" style="color: #ff9800;">Indeterminate (some selected)</span>
180
248
  <span v-else-if="parentState.checked" style="color: #4caf50;">All selected</span>
181
249
  <span v-else style="color: #757575;">None selected</span>
@@ -185,7 +253,11 @@ export const Indeterminate: Story = {
185
253
  }),
186
254
  }
187
255
 
256
+ /**
257
+ * Multiple checkboxes bound to the same v-model array act as a group.
258
+ */
188
259
  export const CheckboxGroup: Story = {
260
+ parameters: { controls: { disable: true } },
189
261
  render: () => ({
190
262
  components: { CpCheckbox },
191
263
  setup() {
@@ -217,6 +289,9 @@ export const CheckboxGroup: Story = {
217
289
  }),
218
290
  }
219
291
 
292
+ /**
293
+ * Replace the label with custom content using the default slot.
294
+ */
220
295
  export const CustomContent: Story = {
221
296
  args: {
222
297
  ...Default.args,
@@ -230,10 +305,7 @@ export const CustomContent: Story = {
230
305
  },
231
306
  template: `
232
307
  <div style="padding: 20px;">
233
- <CpCheckbox
234
- v-model="value"
235
- v-bind="args"
236
- >
308
+ <CpCheckbox v-model="value" v-bind="args">
237
309
  <div style="display: flex; flex-direction: column; gap: 4px;">
238
310
  <span style="font-weight: 500;">Custom Content</span>
239
311
  <span style="font-size: 14px; color: #666;">With multiple lines and styling</span>
@@ -6,13 +6,13 @@ import CpButton from '@/components/CpButton.vue'
6
6
  import CpContextualMenu from '@/components/CpContextualMenu.vue'
7
7
 
8
8
  const meta = {
9
- title: 'Menu/CpContextualMenu',
9
+ title: 'Molecules/CpContextualMenu',
10
10
  component: CpContextualMenu,
11
11
  parameters: {
12
12
  docs: {
13
13
  description: {
14
14
  component:
15
- 'A component that displays airline logos using IATA codes. Fetches logos from Kiwi.com CDN and displays them with customizable sizes.',
15
+ 'A popover menu anchored to a trigger. Items support icons, critical styling, separators and async loading states.',
16
16
  },
17
17
  },
18
18
  },
@@ -26,14 +26,17 @@ const meta = {
26
26
  },
27
27
  },
28
28
  },
29
- tags: ['autodocs'],
30
29
  } satisfies Meta<typeof CpContextualMenu>
31
30
 
32
31
  export default meta
33
32
  type Story = StoryObj<typeof meta>
34
33
 
34
+ /**
35
+ * Click the trigger to open a menu featuring an async "Download" action,
36
+ * a separator and a critical "Delete" action.
37
+ */
35
38
  export const Default: Story = {
36
- render: (args) => ({
39
+ render: () => ({
37
40
  components: { CpButton, CpContextualMenu },
38
41
  setup() {
39
42
  const menu = ref<InstanceType<typeof CpContextualMenu>>()
@@ -53,9 +56,7 @@ export const Default: Story = {
53
56
  isLoading.value = false
54
57
  },
55
58
  },
56
- {
57
- separator: true,
58
- },
59
+ { separator: true },
59
60
  {
60
61
  label: 'Delete',
61
62
  icon: 'trash-2',
@@ -64,7 +65,7 @@ export const Default: Story = {
64
65
  },
65
66
  ])
66
67
 
67
- return { args, menu, showMenu, isLoading, items }
68
+ return { menu, showMenu, isLoading, items }
68
69
  },
69
70
  template: `
70
71
  <CpButton @click="showMenu">Open menu</CpButton>
@@ -4,8 +4,12 @@ import type { Meta, StoryObj } from '@storybook/vue3'
4
4
 
5
5
  import CpDate from '@/components/CpDate.vue'
6
6
 
7
+ import { docCellStyle, docLabelStyle, docRowColumnStyle } from '@/stories/documentationStyles'
8
+
9
+ const dateStackStyle = `${docCellStyle} width: 100%; max-width: 360px;`
10
+
7
11
  const meta = {
8
- title: 'Form/CpDate',
12
+ title: 'Atoms/CpDate',
9
13
  component: CpDate,
10
14
  argTypes: {
11
15
  size: {
@@ -63,6 +67,9 @@ const meta = {
63
67
  export default meta
64
68
  type Story = StoryObj<typeof meta>
65
69
 
70
+ /**
71
+ * Default date input. Use the controls to experiment with each prop in isolation.
72
+ */
66
73
  export const Default: Story = {
67
74
  args: {
68
75
  label: 'Date',
@@ -89,33 +96,53 @@ export const Default: Story = {
89
96
  }),
90
97
  }
91
98
 
92
- export const Required: Story = {
93
- args: {
94
- ...Default.args,
95
- label: 'Required Date',
96
- required: true,
97
- displayErrorMessage: false,
98
- },
99
- }
100
-
101
- export const WithError: Story = {
102
- args: {
103
- ...Default.args,
104
- label: 'Date with Error',
105
- isInvalid: true,
106
- required: true,
107
- errorMessage: 'Please enter a valid date',
108
- },
109
- }
99
+ /* -------------------------------------------------------------------------- */
100
+ /* States */
101
+ /* -------------------------------------------------------------------------- */
110
102
 
111
- export const Disabled: Story = {
112
- args: {
113
- ...Default.args,
114
- label: 'Disabled Date',
115
- disabled: true,
116
- },
103
+ /**
104
+ * Default, required, disabled and invalid states compared side by side.
105
+ */
106
+ export const States: Story = {
107
+ parameters: { controls: { disable: true } },
108
+ render: () => ({
109
+ components: { CpDate },
110
+ setup() {
111
+ const date = ref('')
112
+ return { date, docRowColumnStyle, dateStackStyle, docLabelStyle }
113
+ },
114
+ template: `
115
+ <div :style="docRowColumnStyle">
116
+ <div :style="dateStackStyle">
117
+ <span :style="docLabelStyle">Default</span>
118
+ <CpDate v-model="date" label="Date" />
119
+ </div>
120
+ <div :style="dateStackStyle">
121
+ <span :style="docLabelStyle">Required</span>
122
+ <CpDate v-model="date" label="Date" :required="true" :display-error-message="false" />
123
+ </div>
124
+ <div :style="dateStackStyle">
125
+ <span :style="docLabelStyle">Disabled</span>
126
+ <CpDate v-model="date" label="Date" :disabled="true" />
127
+ </div>
128
+ <div :style="dateStackStyle">
129
+ <span :style="docLabelStyle">Invalid</span>
130
+ <CpDate
131
+ v-model="date"
132
+ label="Date"
133
+ :is-invalid="true"
134
+ :required="true"
135
+ error-message="Please enter a valid date"
136
+ />
137
+ </div>
138
+ </div>
139
+ `,
140
+ }),
117
141
  }
118
142
 
143
+ /**
144
+ * Combines a date input with a text input on the same line.
145
+ */
119
146
  export const NextToInput: Story = {
120
147
  args: {
121
148
  label: 'Date',
@@ -1,86 +1,59 @@
1
1
  import { ref } from 'vue'
2
2
 
3
- import type { Meta, StoryObj } from '@storybook/vue3'
3
+ import type { Args, Meta, StoryObj } from '@storybook/vue3'
4
4
 
5
5
  import CpDatepicker from '@/components/CpDatepicker.vue'
6
6
 
7
+ const datepickerModes = ['single', 'range'] as const
8
+
7
9
  const meta = {
8
- title: 'Form/CpDatepicker',
10
+ title: 'Organisms/CpDatepicker',
9
11
  component: CpDatepicker,
10
-
11
12
  argTypes: {
12
13
  mode: {
13
14
  control: 'select',
14
- options: ['single', 'range'],
15
+ options: datepickerModes,
15
16
  description: 'Selection mode: single date or date range',
16
17
  },
17
18
  closeAfterSelect: {
18
19
  control: 'boolean',
19
20
  description: 'Whether to close the picker after selection',
20
21
  },
21
- label: {
22
- control: 'text',
23
- description: 'Label text for the datepicker',
24
- },
25
- placeholder: {
26
- control: 'text',
27
- description: 'Placeholder text for the input',
28
- },
29
- isError: {
30
- control: 'boolean',
31
- description: 'Whether the field is in an invalid state',
32
- },
33
- errorMessage: {
34
- control: 'text',
35
- description: 'Custom error message to display',
36
- },
37
- initDateOne: {
38
- control: 'text',
39
- description: 'Initial first date (YYYY-MM-DD)',
40
- },
41
- initDateTwo: {
42
- control: 'text',
43
- description: 'Initial second date for range mode (YYYY-MM-DD)',
44
- },
45
- minDate: {
46
- control: 'text',
47
- description: 'Minimum allowed date',
48
- },
49
- maxDate: {
50
- control: 'text',
51
- description: 'Maximum allowed date',
52
- },
53
- allowPastDates: {
54
- control: 'boolean',
55
- description: 'Whether to allow selecting past dates',
56
- },
57
- isInline: {
58
- control: 'boolean',
59
- description: 'Whether to display the picker inline',
60
- },
61
- singleMonth: {
62
- control: 'boolean',
63
- description: 'Whether to show only one month',
64
- },
65
- locale: {
66
- control: 'text',
67
- description: 'Locale for date formatting',
68
- },
22
+ label: { control: 'text', description: 'Label text for the datepicker' },
23
+ placeholder: { control: 'text', description: 'Placeholder text for the input' },
24
+ isError: { control: 'boolean', description: 'Whether the field is in an invalid state' },
25
+ errorMessage: { control: 'text', description: 'Custom error message to display' },
26
+ initDateOne: { control: 'text', description: 'Initial first date (YYYY-MM-DD)' },
27
+ initDateTwo: { control: 'text', description: 'Initial second date for range mode (YYYY-MM-DD)' },
28
+ minDate: { control: 'text', description: 'Minimum allowed date' },
29
+ maxDate: { control: 'text', description: 'Maximum allowed date' },
30
+ allowPastDates: { control: 'boolean', description: 'Whether to allow selecting past dates' },
31
+ isInline: { control: 'boolean', description: 'Whether to display the picker inline' },
32
+ singleMonth: { control: 'boolean', description: 'Whether to show only one month' },
33
+ locale: { control: 'text', description: 'Locale for date formatting' },
69
34
  },
70
35
  } satisfies Meta<typeof CpDatepicker>
71
36
 
72
37
  export default meta
73
38
  type Story = StoryObj<typeof meta>
74
39
 
75
- const defaultTemplate = `
76
- <div style="height: 35vh; max-width: 600px; padding: 20px;">
77
- <CpDatepicker
78
- v-bind="args"
79
- @dates="(selectedDates) => dates = selectedDates"
80
- />
81
- </div>
82
- `
40
+ const datepickerRender = (args: Args) => ({
41
+ components: { CpDatepicker },
42
+ setup() {
43
+ const dates = ref([])
44
+ return { args, dates }
45
+ },
46
+ template: `
47
+ <div style="height: 35vh; max-width: 600px; padding: 20px;">
48
+ <CpDatepicker v-bind="args" @dates="(selectedDates) => dates = selectedDates" />
49
+ </div>
50
+ `,
51
+ })
83
52
 
53
+ /**
54
+ * Default single-date picker. Use the controls to experiment with each
55
+ * prop in isolation.
56
+ */
84
57
  export const Default: Story = {
85
58
  args: {
86
59
  mode: 'single',
@@ -91,16 +64,12 @@ export const Default: Story = {
91
64
  isInline: false,
92
65
  singleMonth: false,
93
66
  },
94
- render: (args) => ({
95
- components: { CpDatepicker },
96
- setup() {
97
- const dates = ref([])
98
- return { args, dates }
99
- },
100
- template: defaultTemplate,
101
- }),
67
+ render: datepickerRender,
102
68
  }
103
69
 
70
+ /**
71
+ * Range mode lets the user pick a start and end date.
72
+ */
104
73
  export const DateRange: Story = {
105
74
  args: {
106
75
  ...Default.args,
@@ -108,12 +77,12 @@ export const DateRange: Story = {
108
77
  label: 'Select Date Range',
109
78
  placeholder: 'Choose date range',
110
79
  },
111
- render: (args) => ({
112
- ...Default.render(args),
113
- template: defaultTemplate,
114
- }),
80
+ render: datepickerRender,
115
81
  }
116
82
 
83
+ /**
84
+ * Invalid state with a custom error message.
85
+ */
117
86
  export const WithError: Story = {
118
87
  args: {
119
88
  ...Default.args,
@@ -121,44 +90,44 @@ export const WithError: Story = {
121
90
  isError: true,
122
91
  errorMessage: 'Please select a valid date',
123
92
  },
124
- render: (args) => ({
125
- ...Default.render(args),
126
- template: defaultTemplate,
127
- }),
93
+ render: datepickerRender,
128
94
  }
129
95
 
96
+ /**
97
+ * Pre-populate the picker with an initial date through `initDateOne`
98
+ * (and `initDateTwo` in range mode).
99
+ */
130
100
  export const WithInitialDates: Story = {
131
101
  args: {
132
102
  ...Default.args,
133
103
  initDateOne: '2024-03-15',
134
104
  label: 'Datepicker with Initial Date',
135
105
  },
136
- render: (args) => ({
137
- ...Default.render(args),
138
- template: defaultTemplate,
139
- }),
106
+ render: datepickerRender,
140
107
  }
141
108
 
109
+ /**
110
+ * Show a single month at a time instead of the default two-month layout —
111
+ * useful for narrow spaces.
112
+ */
142
113
  export const SingleMonth: Story = {
143
114
  args: {
144
115
  ...Default.args,
145
116
  singleMonth: true,
146
117
  label: 'Single Month View',
147
118
  },
148
- render: (args) => ({
149
- ...Default.render(args),
150
- template: defaultTemplate,
151
- }),
119
+ render: datepickerRender,
152
120
  }
153
121
 
122
+ /**
123
+ * By default the picker blocks past dates. Set `allowPastDates` to `true`
124
+ * to let the user pick any date.
125
+ */
154
126
  export const AllowPastDates: Story = {
155
127
  args: {
156
128
  ...Default.args,
157
129
  allowPastDates: true,
158
130
  label: 'Allow Past Dates',
159
131
  },
160
- render: (args) => ({
161
- ...Default.render(args),
162
- template: defaultTemplate,
163
- }),
132
+ render: datepickerRender,
164
133
  }
@@ -5,7 +5,7 @@ import type { Meta, StoryObj } from '@storybook/vue3'
5
5
  import CpDialog from '@/components/CpDialog.vue'
6
6
 
7
7
  const meta = {
8
- title: 'Navigation/CpDialog',
8
+ title: 'Organisms/CpDialog',
9
9
  component: CpDialog,
10
10
  argTypes: {
11
11
  maxWidth: {
@@ -19,6 +19,11 @@ const meta = {
19
19
  export default meta
20
20
  type Story = StoryObj<typeof meta>
21
21
 
22
+ /**
23
+ * Default dialog featuring every common part: title and subtitle slots,
24
+ * body content and a footer slot. Use the controls to experiment with each
25
+ * prop in isolation.
26
+ */
22
27
  export const Default: Story = {
23
28
  args: {
24
29
  maxWidth: 600,
@@ -47,6 +52,10 @@ export const Default: Story = {
47
52
  }),
48
53
  }
49
54
 
55
+ /**
56
+ * Pass the title and subtitle as plain strings through props instead of
57
+ * slots — the simplest way to compose a dialog.
58
+ */
50
59
  export const TitleSubtitleWithProps: Story = {
51
60
  args: {
52
61
  maxWidth: 600,
@@ -73,6 +82,9 @@ export const TitleSubtitleWithProps: Story = {
73
82
  }),
74
83
  }
75
84
 
85
+ /**
86
+ * Dialog with only body content — no title, subtitle or header.
87
+ */
76
88
  export const ContentOnly: Story = {
77
89
  args: {
78
90
  maxWidth: 600,
@@ -96,6 +108,11 @@ export const ContentOnly: Story = {
96
108
  }),
97
109
  }
98
110
 
111
+ /**
112
+ * Provide rich title and subtitle through slots. Use `titleTag`/
113
+ * `subtitleTag` to change the underlying element (e.g. `div` to allow
114
+ * flex content).
115
+ */
99
116
  export const TitleSubtitleWithSlots: Story = {
100
117
  args: {
101
118
  maxWidth: 560,
@@ -132,6 +149,10 @@ export const TitleSubtitleWithSlots: Story = {
132
149
  }),
133
150
  }
134
151
 
152
+ /**
153
+ * Enable `isClosableOnClickOutside` so the dialog dismisses when the user
154
+ * clicks the backdrop.
155
+ */
135
156
  export const ClosableOnClickOutside: Story = {
136
157
  args: {
137
158
  maxWidth: 600,