fds-vue-core 2.1.11 → 2.1.15

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 (56) hide show
  1. package/dist/fds-vue-core.cjs.js +312 -240
  2. package/dist/fds-vue-core.cjs.js.map +1 -1
  3. package/dist/fds-vue-core.es.js +313 -241
  4. package/dist/fds-vue-core.es.js.map +1 -1
  5. package/package.json +9 -11
  6. package/src/components/Blocks/FdsBlockAlert/FdsBlockAlert.stories.ts +60 -33
  7. package/src/components/Blocks/FdsBlockAlert/FdsBlockAlert.vue +5 -1
  8. package/src/components/Blocks/FdsBlockContent/FdsBlockContent.stories.ts +44 -41
  9. package/src/components/Blocks/FdsBlockExpander/FdsBlockExpander.stories.ts +33 -30
  10. package/src/components/Blocks/FdsBlockExpander/FdsBlockExpander.vue +51 -16
  11. package/src/components/Blocks/FdsBlockExpander/types.ts +2 -0
  12. package/src/components/Blocks/FdsBlockInfo/FdsBlockInfo.stories.ts +42 -39
  13. package/src/components/Blocks/FdsBlockLink/FdsBlockLink.stories.ts +42 -39
  14. package/src/components/Blocks/FdsBlockLink/FdsBlockLink.vue +7 -2
  15. package/src/components/Buttons/ButtonBaseProps.ts +4 -0
  16. package/src/components/Buttons/FdsButtonCopy/FdsButtonCopy.stories.ts +1 -1
  17. package/src/components/Buttons/FdsButtonDownload/FdsButtonDownload.stories.ts +4 -4
  18. package/src/components/Buttons/FdsButtonDownload/FdsButtonDownload.vue +12 -2
  19. package/src/components/Buttons/FdsButtonDownload/types.ts +2 -0
  20. package/src/components/Buttons/FdsButtonIcon/FdsButtonIcon.stories.ts +2 -2
  21. package/src/components/Buttons/FdsButtonMinor/FdsButtonMinor.stories.ts +2 -2
  22. package/src/components/Buttons/FdsButtonMinor/FdsButtonMinor.vue +3 -0
  23. package/src/components/Buttons/FdsButtonPrimary/FdsButtonPrimary.stories.ts +4 -4
  24. package/src/components/Buttons/FdsButtonPrimary/FdsButtonPrimary.vue +0 -5
  25. package/src/components/Buttons/FdsButtonSecondary/FdsButtonSecondary.stories.ts +2 -2
  26. package/src/components/FdsIcon/FdsIcon.stories.ts +1 -1
  27. package/src/components/FdsModal/FdsModal.stories.ts +7 -7
  28. package/src/components/FdsModal/FdsModal.vue +6 -1
  29. package/src/components/FdsPagination/FdsPagination.stories.ts +5 -5
  30. package/src/components/FdsSearchSelect/FdsSearchSelect.stories.ts +9 -9
  31. package/src/components/FdsSpinner/FdsSpinner.stories.ts +1 -1
  32. package/src/components/FdsSticker/FdsSticker.stories.ts +23 -20
  33. package/src/components/FdsSticker/FdsSticker.vue +6 -5
  34. package/src/components/FdsTreeView/FdsTreeView.stories.ts +1 -1
  35. package/src/components/FdsTruncatedText/FdsTruncatedText.stories.ts +4 -4
  36. package/src/components/FdsTruncatedText/FdsTruncatedText.vue +6 -7
  37. package/src/components/Form/FdsCheckbox/FdsCheckbox.stories.ts +4 -4
  38. package/src/components/Form/FdsCheckbox/FdsCheckbox.vue +6 -6
  39. package/src/components/Form/FdsInput/FdsInput.stories.ts +5 -5
  40. package/src/components/Form/FdsInput/FdsInput.vue +14 -19
  41. package/src/components/Form/FdsRadio/FdsRadio.stories.ts +1 -1
  42. package/src/components/Form/FdsRadio/FdsRadio.vue +6 -6
  43. package/src/components/Form/FdsSelect/FdsSelect.stories.ts +4 -4
  44. package/src/components/Form/FdsSelect/FdsSelect.vue +5 -1
  45. package/src/components/Form/FdsTextarea/FdsTextarea.stories.ts +2 -2
  46. package/src/components/Table/FdsTable/FdsTable.stories.ts +3 -3
  47. package/src/components/Table/FdsTableHead/FdsTableHead.stories.ts +6 -6
  48. package/src/components/Table/FdsTableHead/FdsTableHead.vue +9 -15
  49. package/src/components/Table/FdsTableHead/types.ts +1 -0
  50. package/src/components/Tabs/FdsTabs/FdsTabs.stories.ts +9 -9
  51. package/src/components/Tabs/FdsTabs/FdsTabs.vue +5 -1
  52. package/src/components/Tabs/FdsTabsItem/FdsTabsItem.vue +26 -2
  53. package/src/components/Tabs/FdsTabsItem/types.ts +2 -0
  54. package/src/components/Typography/FdsText/FdsText.stories.ts +14 -14
  55. package/src/components/Typography/FdsText/FdsText.vue +18 -2
  56. package/src/components/Typography/FdsText/types.ts +1 -0
@@ -128,7 +128,7 @@ export default meta
128
128
  type Story = StoryObj<typeof meta>
129
129
 
130
130
  export const Basic: Story = {
131
- render: (args) => ({
131
+ render: (args: Story['args']) => ({
132
132
  components: { FdsTreeView },
133
133
  setup: () => ({ args }),
134
134
  template: '<FdsTreeView v-bind="args" />',
@@ -1,5 +1,5 @@
1
- import { ref } from 'vue'
2
1
  import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import { ref } from 'vue'
3
3
  import FdsTruncatedText from './FdsTruncatedText.vue'
4
4
 
5
5
  const meta: Meta<typeof FdsTruncatedText> = {
@@ -29,7 +29,7 @@ export default meta
29
29
  type Story = StoryObj<typeof meta>
30
30
 
31
31
  export const Default: Story = {
32
- render: (args) => ({
32
+ render: (args: NonNullable<Story['args']>) => ({
33
33
  components: { FdsTruncatedText },
34
34
  setup: () => {
35
35
  const open = ref(args.open)
@@ -43,7 +43,7 @@ export const Default: Story = {
43
43
  }
44
44
 
45
45
  export const WithSlot: Story = {
46
- render: (args) => ({
46
+ render: (args: NonNullable<Story['args']>) => ({
47
47
  components: { FdsTruncatedText },
48
48
  setup: () => {
49
49
  const open = ref(args.open)
@@ -61,7 +61,7 @@ export const WithSlot: Story = {
61
61
  }
62
62
 
63
63
  export const Open: Story = {
64
- render: (args) => ({
64
+ render: (args: NonNullable<Story['args']>) => ({
65
65
  components: { FdsTruncatedText },
66
66
  setup: () => {
67
67
  const open = ref(args.open)
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
+ import { computed, onMounted, ref, watch, type Slot } from 'vue'
2
3
  import { useHasSlot } from '../../composables/useHasSlots'
3
- import { computed, onMounted, ref, watch } from 'vue'
4
4
  import FdsButtonMinor from '../Buttons/FdsButtonMinor/FdsButtonMinor.vue'
5
5
  import type { FdsTruncatedTextProps } from './types'
6
6
 
@@ -54,6 +54,10 @@ onMounted(() => {
54
54
  }
55
55
  }
56
56
  })
57
+
58
+ defineSlots<{
59
+ default?: Slot
60
+ }>()
57
61
  </script>
58
62
 
59
63
  <template>
@@ -66,12 +70,7 @@ onMounted(() => {
66
70
  >
67
71
  <slot />
68
72
  </div>
69
- <div
70
- v-else
71
- ref="contentRef"
72
- :class="['content', { open: isOpen }]"
73
- :style="{ maxWidth: `${containerWidth}px` }"
74
- >
73
+ <div v-else ref="contentRef" :class="['content', { open: isOpen }]" :style="{ maxWidth: `${containerWidth}px` }">
75
74
  {{ content }}
76
75
  </div>
77
76
  <FdsButtonMinor
@@ -36,7 +36,7 @@ export const Default: Story = {
36
36
  checked: false,
37
37
  label: 'Checkbox label',
38
38
  },
39
- render: (args) => ({
39
+ render: (args: NonNullable<Story['args']>) => ({
40
40
  components: { FdsCheckbox },
41
41
  setup() {
42
42
  const checked = ref(args.checked)
@@ -65,7 +65,7 @@ export const Checked: Story = {
65
65
  args: {
66
66
  checked: true,
67
67
  },
68
- render: (args) => ({
68
+ render: (args: NonNullable<Story['args']>) => ({
69
69
  components: { FdsCheckbox },
70
70
  setup() {
71
71
  const checked = ref(args.checked)
@@ -97,7 +97,7 @@ export const Indeterminate: Story = {
97
97
  args: {
98
98
  indeterminate: true,
99
99
  },
100
- render: (args) => ({
100
+ render: (args: NonNullable<Story['args']>) => ({
101
101
  components: { FdsCheckbox },
102
102
  setup() {
103
103
  const checked = ref(args.checked)
@@ -130,7 +130,7 @@ export const Disabled: Story = {
130
130
  disabled: true,
131
131
  checked: true,
132
132
  },
133
- render: (args) => ({
133
+ render: (args: NonNullable<Story['args']>) => ({
134
134
  components: { FdsCheckbox },
135
135
  setup() {
136
136
  const checked = ref(args.checked)
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
+ import { computed, nextTick, watch, type Slot } from 'vue'
2
3
  import { useHasSlot } from '../../../composables/useHasSlots'
3
- import { computed, nextTick, watch } from 'vue'
4
4
  import type { FdsCheckboxProps } from './types'
5
5
 
6
6
  // Support v-model as boolean (single checkbox) or array (checkbox group)
@@ -119,15 +119,15 @@ watch(
119
119
  },
120
120
  { immediate: true },
121
121
  )
122
+
123
+ defineSlots<{
124
+ default?: Slot
125
+ }>()
122
126
  </script>
123
127
 
124
128
  <template>
125
129
  <div :class="wrapperClasses">
126
- <label
127
- :for="inputId"
128
- :class="[innerWrapperClasses, { 'cursor-not-allowed': disabled }]"
129
- v-bind="$attrs"
130
- >
130
+ <label :for="inputId" :class="[innerWrapperClasses, { 'cursor-not-allowed': disabled }]" v-bind="$attrs">
131
131
  <input
132
132
  :id="inputId"
133
133
  :name="name"
@@ -112,7 +112,7 @@ export default meta
112
112
  type Story = StoryObj<typeof meta>
113
113
 
114
114
  export const Basic: Story = {
115
- render: (args) => ({
115
+ render: (args: Story['args']) => ({
116
116
  components: { FdsInput },
117
117
  setup: () => ({ args }),
118
118
  template: '<FdsInput v-bind="args" />',
@@ -140,7 +140,7 @@ export const WithVModel: Story = {
140
140
  }
141
141
 
142
142
  export const WithMeta: Story = {
143
- render: (args) => ({
143
+ render: (args: Story['args']) => ({
144
144
  components: { FdsInput },
145
145
  setup: () => ({ args }),
146
146
  template: '<FdsInput v-bind="args" meta="Detta är hjälptext som visas under labeln" />',
@@ -184,7 +184,7 @@ export const WithValidation: Story = {
184
184
  }
185
185
 
186
186
  export const Disabled: Story = {
187
- render: (args) => ({
187
+ render: (args: Story['args']) => ({
188
188
  components: { FdsInput },
189
189
  setup: () => ({ args }),
190
190
  template: '<FdsInput v-bind="args" />',
@@ -197,7 +197,7 @@ export const Disabled: Story = {
197
197
  }
198
198
 
199
199
  export const Required: Story = {
200
- render: (args) => ({
200
+ render: (args: Story['args']) => ({
201
201
  components: { FdsInput },
202
202
  setup: () => ({ args }),
203
203
  template: '<FdsInput v-bind="args" />',
@@ -210,7 +210,7 @@ export const Required: Story = {
210
210
  }
211
211
 
212
212
  export const WithLabelLeft: Story = {
213
- render: (args) => ({
213
+ render: (args: Story['args']) => ({
214
214
  components: { FdsInput },
215
215
  setup: () => ({ args }),
216
216
  template: '<FdsInput v-bind="args" />',
@@ -32,6 +32,8 @@ const emit = defineEmits<{
32
32
  (e: 'input', ev: Event): void
33
33
  (e: 'clearInput'): void
34
34
  (e: 'update:value', value: string): void
35
+ (e: 'keyup', ev: KeyboardEvent): void
36
+ (e: 'keyup.enter', ev: KeyboardEvent): void
35
37
  }>()
36
38
 
37
39
  const autoId = `fds-input-${Math.random().toString(36).slice(2, 9)}`
@@ -170,13 +172,10 @@ watch(
170
172
  :for="inputId"
171
173
  class="block font-bold text-gray-900 cursor-pointer"
172
174
  :class="{ 'mb-0': meta, 'mb-1': !meta }"
173
- >{{ label }}</label
174
- >
175
- <div
176
- v-if="meta"
177
- class="font-thin"
178
- :class="{ 'mb-1': !labelLeft }"
179
175
  >
176
+ {{ label }}
177
+ </label>
178
+ <div v-if="meta" class="font-thin" :class="{ 'mb-1': !labelLeft }">
180
179
  {{ meta }}
181
180
  </div>
182
181
  </div>
@@ -196,17 +195,16 @@ watch(
196
195
  :class="inputClasses"
197
196
  v-bind="$attrs"
198
197
  @input="$emit('input', $event)"
198
+ @keyup="
199
+ (ev) => {
200
+ $emit('keyup', ev)
201
+ if (ev.key === 'Enter') $emit('keyup.enter', ev)
202
+ }
203
+ "
199
204
  />
200
205
  <div :class="validationIconClasses">
201
- <FdsIcon
202
- v-if="isInvalid"
203
- name="alert"
204
- class="fill-red-600"
205
- />
206
- <FdsIcon
207
- v-if="isValid"
208
- name="bigSuccess"
209
- />
206
+ <FdsIcon v-if="isInvalid" name="alert" class="fill-red-600" />
207
+ <FdsIcon v-if="isValid" name="bigSuccess" />
210
208
  <FdsButtonIcon
211
209
  v-if="clearButton && !!internalValue && !disabled"
212
210
  icon="cross"
@@ -223,10 +221,7 @@ watch(
223
221
  </div>
224
222
  </div>
225
223
  </div>
226
- <div
227
- v-if="showInvalidMessage"
228
- class="text-red-600 font-bold mt-1"
229
- >
224
+ <div v-if="showInvalidMessage" class="text-red-600 font-bold mt-1">
230
225
  {{ invalidMessage }}
231
226
  </div>
232
227
  </div>
@@ -28,7 +28,7 @@ export default meta
28
28
  type Story = StoryObj<typeof meta>
29
29
 
30
30
  export const Default: Story = {
31
- render: (args) => ({
31
+ render: (args: NonNullable<Story['args']>) => ({
32
32
  components: { FdsRadio },
33
33
  setup() {
34
34
  const checked = ref(args.checked)
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
+ import { computed, type Slot } from 'vue'
2
3
  import { useHasSlot } from '../../../composables/useHasSlots'
3
- import { computed } from 'vue'
4
4
  import type { FdsRadioProps } from './types'
5
5
 
6
6
  // Support v-model for selected value in a radio group (string|number)
@@ -51,15 +51,15 @@ const inputClasses = computed(() => [
51
51
  'peer z-2 bg-white min-w-[20px] min-h-[20px] focus-visible:outline-none rounded-full accent-blue-500',
52
52
  props.disabled && 'cursor-not-allowed',
53
53
  ])
54
+
55
+ defineSlots<{
56
+ default?: Slot
57
+ }>()
54
58
  </script>
55
59
 
56
60
  <template>
57
61
  <div :class="wrapperClasses">
58
- <label
59
- :for="inputId"
60
- :class="[innerWrapperClasses, { 'cursor-not-allowed': disabled }]"
61
- v-bind="$attrs"
62
- >
62
+ <label :for="inputId" :class="[innerWrapperClasses, { 'cursor-not-allowed': disabled }]" v-bind="$attrs">
63
63
  <input
64
64
  :id="inputId"
65
65
  :name="name"
@@ -37,7 +37,7 @@ export default meta
37
37
  type Story = StoryObj<typeof meta>
38
38
 
39
39
  export const Default: Story = {
40
- render: (args) => ({
40
+ render: (args: Story['args']) => ({
41
41
  components: { FdsSelect },
42
42
  setup: () => ({ args }),
43
43
  template: `<FdsSelect v-bind="args" />`,
@@ -46,7 +46,7 @@ export const Default: Story = {
46
46
 
47
47
  export const Disabled: Story = {
48
48
  args: { disabled: true },
49
- render: (args) => ({
49
+ render: (args: Story['args']) => ({
50
50
  components: { FdsSelect },
51
51
  setup: () => ({ args }),
52
52
  template: `<FdsSelect v-bind="args" />`,
@@ -58,7 +58,7 @@ export const Invalid: Story = {
58
58
  valid: 'false',
59
59
  invalidMessage: 'Välj ett giltigt alternativ',
60
60
  },
61
- render: (args) => ({
61
+ render: (args: Story['args']) => ({
62
62
  components: { FdsSelect },
63
63
  setup: () => ({ args }),
64
64
  template: `<FdsSelect v-bind="args" />`,
@@ -70,7 +70,7 @@ export const Valid: Story = {
70
70
  valid: 'true',
71
71
  modelValue: 'option1',
72
72
  },
73
- render: (args) => ({
73
+ render: (args: Story['args']) => ({
74
74
  components: { FdsSelect },
75
75
  setup: () => ({ args }),
76
76
  template: `<FdsSelect v-bind="args" />`,
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { computed, useSlots } from 'vue'
2
+ import { computed, useSlots, type Slot } from 'vue'
3
3
  import FdsIcon from '../../FdsIcon/FdsIcon.vue'
4
4
  import type { FdsSelectProps } from './types'
5
5
 
@@ -64,6 +64,10 @@ function handleChange(ev: Event) {
64
64
  emit('change', ev)
65
65
  emit('input', ev)
66
66
  }
67
+
68
+ defineSlots<{
69
+ default?: Slot
70
+ }>()
67
71
  </script>
68
72
 
69
73
  <template>
@@ -35,7 +35,7 @@ export default meta
35
35
  type Story = StoryObj<typeof meta>
36
36
 
37
37
  export const Default: Story = {
38
- render: (args) => ({
38
+ render: (args: Story['args']) => ({
39
39
  components: { FdsTextarea },
40
40
  setup: () => ({ args }),
41
41
  template: `<FdsTextarea v-bind="args" />`,
@@ -44,7 +44,7 @@ export const Default: Story = {
44
44
 
45
45
  export const Disabled: Story = {
46
46
  args: { disabled: true },
47
- render: (args) => ({
47
+ render: (args: Story['args']) => ({
48
48
  components: { FdsTextarea },
49
49
  setup: () => ({ args }),
50
50
  template: `<FdsTextarea v-bind="args" />`,
@@ -56,7 +56,7 @@ const sampleData = [
56
56
  ]
57
57
 
58
58
  export const Default: Story = {
59
- render: (args) => ({
59
+ render: (args: Story['args']) => ({
60
60
  components: { FdsTable, FdsTableHead },
61
61
  setup: () => ({ args, sampleData }),
62
62
  template: `
@@ -93,7 +93,7 @@ export const Default: Story = {
93
93
 
94
94
  export const Bordered: Story = {
95
95
  args: { bordered: true },
96
- render: (args) => ({
96
+ render: (args: Story['args']) => ({
97
97
  components: { FdsTable, FdsTableHead },
98
98
  setup: () => ({ args, sampleData }),
99
99
  template: `
@@ -130,7 +130,7 @@ export const Bordered: Story = {
130
130
 
131
131
  export const Compact: Story = {
132
132
  args: { compact: true },
133
- render: (args) => ({
133
+ render: (args: Story['args']) => ({
134
134
  components: { FdsTable, FdsTableHead },
135
135
  setup: () => ({ args, sampleData }),
136
136
  template: `
@@ -21,7 +21,7 @@ export default meta
21
21
  type Story = StoryObj<typeof meta>
22
22
 
23
23
  export const Default: Story = {
24
- render: (args) => ({
24
+ render: (args: Story['args']) => ({
25
25
  components: { FdsTableHead },
26
26
  setup: () => ({ args }),
27
27
  template: `
@@ -42,7 +42,7 @@ export const Default: Story = {
42
42
  }
43
43
 
44
44
  export const Sortable: Story = {
45
- render: (args) => ({
45
+ render: (args: Story['args']) => ({
46
46
  components: { FdsTableHead },
47
47
  setup: () => ({ args }),
48
48
  template: `
@@ -64,7 +64,7 @@ export const Sortable: Story = {
64
64
 
65
65
  export const SortedAsc: Story = {
66
66
  args: { icon: 'ascending' },
67
- render: (args) => ({
67
+ render: (args: Story['args']) => ({
68
68
  components: { FdsTableHead },
69
69
  setup: () => ({ args }),
70
70
  template: `
@@ -86,7 +86,7 @@ export const SortedAsc: Story = {
86
86
 
87
87
  export const SortedDesc: Story = {
88
88
  args: { icon: 'descending' },
89
- render: (args) => ({
89
+ render: (args: Story['args']) => ({
90
90
  components: { FdsTableHead },
91
91
  setup: () => ({ args }),
92
92
  template: `
@@ -108,7 +108,7 @@ export const SortedDesc: Story = {
108
108
 
109
109
  export const CenterAligned: Story = {
110
110
  args: { align: 'center' },
111
- render: (args) => ({
111
+ render: (args: Story['args']) => ({
112
112
  components: { FdsTableHead },
113
113
  setup: () => ({ args }),
114
114
  template: `
@@ -130,7 +130,7 @@ export const CenterAligned: Story = {
130
130
 
131
131
  export const RightAligned: Story = {
132
132
  args: { align: 'right' },
133
- render: (args) => ({
133
+ render: (args: Story['args']) => ({
134
134
  components: { FdsTableHead },
135
135
  setup: () => ({ args }),
136
136
  template: `
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
+ import { computed, type Slot } from 'vue'
2
3
  import { useHasSlot } from '../../../composables/useHasSlots'
3
- import { computed } from 'vue'
4
4
  import FdsIcon from '../../FdsIcon/FdsIcon.vue'
5
5
  import type { FdsTableHeadProps } from './types'
6
6
 
@@ -25,28 +25,22 @@ const iconName = computed(() => props.icon)
25
25
 
26
26
  defineEmits<{
27
27
  (e: 'sort'): void
28
+ (e: 'click', ev: MouseEvent): void
29
+ }>()
30
+
31
+ defineSlots<{
32
+ default?: Slot
28
33
  }>()
29
34
  </script>
30
35
 
31
36
  <template>
32
37
  <th class="fds-table-head">
33
- <button
34
- v-if="iconName"
35
- :class="headerClasses"
36
- @click="$emit('sort')"
37
- >
38
+ <button v-if="iconName" :class="headerClasses" @click="$emit('sort')">
38
39
  <span v-if="hasSlot"><slot /></span>
39
40
  <span v-else>{{ heading }}</span>
40
- <FdsIcon
41
- :name="iconName"
42
- size="24px"
43
- class="fill-blue-500"
44
- />
41
+ <FdsIcon :name="iconName" size="24px" class="fill-blue-500" />
45
42
  </button>
46
- <div
47
- v-else
48
- :class="headerClasses"
49
- >
43
+ <div v-else :class="headerClasses">
50
44
  <span v-if="hasSlot"><slot /></span>
51
45
  <span v-else>{{ heading }}</span>
52
46
  </div>
@@ -2,4 +2,5 @@ export interface FdsTableHeadProps {
2
2
  heading?: string
3
3
  align?: 'left' | 'center' | 'right'
4
4
  icon?: 'sort' | 'ascending' | 'descending'
5
+ onClick?: () => void
5
6
  }
@@ -1,6 +1,6 @@
1
1
  import type { Meta, StoryObj } from '@storybook/vue3'
2
- import FdsTabs from './FdsTabs.vue'
3
2
  import FdsTabsItem from '../FdsTabsItem/FdsTabsItem.vue'
3
+ import FdsTabs from './FdsTabs.vue'
4
4
 
5
5
  const meta: Meta<typeof FdsTabs> = {
6
6
  title: 'FDS/FdsTabs',
@@ -33,7 +33,7 @@ const tabsTransform = (storyContext: { args?: { block?: boolean; variant?: strin
33
33
  }
34
34
 
35
35
  export const Default: Story = {
36
- render: (args) => ({
36
+ render: (args: Story['args']) => ({
37
37
  components: { FdsTabs, FdsTabsItem },
38
38
  setup: () => ({ args }),
39
39
  template: `
@@ -54,7 +54,7 @@ export const Default: Story = {
54
54
  }
55
55
 
56
56
  export const Secondary: Story = {
57
- render: (args) => ({
57
+ render: (args: Story['args']) => ({
58
58
  components: { FdsTabs, FdsTabsItem },
59
59
  setup: () => ({ args }),
60
60
  template: `
@@ -84,7 +84,7 @@ export const Secondary: Story = {
84
84
  }
85
85
 
86
86
  export const Block: Story = {
87
- render: (args) => ({
87
+ render: (args: Story['args']) => ({
88
88
  components: { FdsTabs, FdsTabsItem },
89
89
  setup: () => ({ args }),
90
90
  template: `
@@ -114,7 +114,7 @@ export const Block: Story = {
114
114
  }
115
115
 
116
116
  export const WithDisabled: Story = {
117
- render: (args) => ({
117
+ render: (args: Story['args']) => ({
118
118
  components: { FdsTabs, FdsTabsItem },
119
119
  setup: () => ({ args }),
120
120
  template: `
@@ -139,7 +139,7 @@ export const WithDisabled: Story = {
139
139
  }
140
140
 
141
141
  export const WithRouterLinks: Story = {
142
- render: (args) => ({
142
+ render: (args: Story['args']) => ({
143
143
  components: { FdsTabs, FdsTabsItem },
144
144
  setup: () => ({ args }),
145
145
  template: `
@@ -166,7 +166,7 @@ export const WithRouterLinks: Story = {
166
166
  }
167
167
 
168
168
  export const WithExactMatch: Story = {
169
- render: (args) => ({
169
+ render: (args: Story['args']) => ({
170
170
  components: { FdsTabs, FdsTabsItem },
171
171
  setup: () => ({ args }),
172
172
  template: `
@@ -193,7 +193,7 @@ export const WithExactMatch: Story = {
193
193
  }
194
194
 
195
195
  export const WithAnchorLinks: Story = {
196
- render: (args) => ({
196
+ render: (args: Story['args']) => ({
197
197
  components: { FdsTabs, FdsTabsItem },
198
198
  setup: () => ({ args }),
199
199
  template: `
@@ -220,7 +220,7 @@ export const WithAnchorLinks: Story = {
220
220
  }
221
221
 
222
222
  export const WithButtons: Story = {
223
- render: (args) => ({
223
+ render: (args: Story['args']) => ({
224
224
  components: { FdsTabs, FdsTabsItem },
225
225
  setup: () => ({ args }),
226
226
  template: `
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { computed, provide } from 'vue'
2
+ import { computed, provide, type Slot } from 'vue'
3
3
  import type { FdsTabsProps } from './types'
4
4
 
5
5
  const props = withDefaults(defineProps<FdsTabsProps>(), {
@@ -18,6 +18,10 @@ const tabsClasses = computed(() => [
18
18
 
19
19
  provide('tabsVariant', props.variant)
20
20
  provide('tabsBlock', props.block)
21
+
22
+ defineSlots<{
23
+ default?: Slot
24
+ }>()
21
25
  </script>
22
26
 
23
27
  <template>
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { computed, getCurrentInstance, inject, useAttrs } from 'vue'
2
+ import { computed, getCurrentInstance, inject, useAttrs, type Slot } from 'vue'
3
3
  import type { FdsTabsItemProps } from './types'
4
4
 
5
5
  defineOptions({
@@ -8,6 +8,24 @@ defineOptions({
8
8
 
9
9
  const attrs = useAttrs()
10
10
 
11
+ const emit = defineEmits<{
12
+ (e: 'click', ev: MouseEvent): void
13
+ }>()
14
+
15
+ const onClick = (ev: MouseEvent) => {
16
+ if (props.disabled) {
17
+ ev.preventDefault()
18
+ return
19
+ }
20
+ emit('click', ev)
21
+ }
22
+
23
+ const handleClick = (ev: MouseEvent) => {
24
+ if (componentType.value === 'button' && !props.disabled) {
25
+ onClick(ev)
26
+ }
27
+ }
28
+
11
29
  // Try to get route from vue-router if available
12
30
  const instance = getCurrentInstance()
13
31
  const route = computed(() => {
@@ -109,6 +127,10 @@ const variantClasses = computed(() => {
109
127
  const disabledClasses = computed(() => (props.disabled ? 'cursor-not-allowed pointer-events-none opacity-35' : ''))
110
128
 
111
129
  const buttonClasses = computed(() => [...baseClasses.value, ...variantClasses.value, disabledClasses.value])
130
+
131
+ defineSlots<{
132
+ default?: Slot
133
+ }>()
112
134
  </script>
113
135
 
114
136
  <template>
@@ -119,7 +141,9 @@ const buttonClasses = computed(() => [...baseClasses.value, ...variantClasses.va
119
141
  :disabled="componentType === 'button' ? disabled : undefined"
120
142
  :aria-disabled="disabled"
121
143
  :aria-current="isActive ? 'page' : undefined"
144
+ @click="handleClick"
122
145
  >
123
- <slot>{{ label }}</slot>
146
+ {{ label }}
147
+ <slot></slot>
124
148
  </component>
125
149
  </template>
@@ -13,4 +13,6 @@ export interface FdsTabsItemProps {
13
13
  disabled?: boolean
14
14
  /** Tab label text */
15
15
  label?: string
16
+ /** Click handler */
17
+ onClick?: ((ev: MouseEvent) => void) | Array<(ev: MouseEvent) => void>
16
18
  }