fds-vue-core 2.1.11 → 2.1.16

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 (59) hide show
  1. package/dist/fds-vue-core.cjs.js +372 -284
  2. package/dist/fds-vue-core.cjs.js.map +1 -1
  3. package/dist/fds-vue-core.es.js +373 -285
  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/Blocks/FdsBlockLink/types.ts +1 -0
  16. package/src/components/Buttons/ButtonBaseProps.ts +4 -0
  17. package/src/components/Buttons/FdsButtonCopy/FdsButtonCopy.stories.ts +1 -1
  18. package/src/components/Buttons/FdsButtonDownload/FdsButtonDownload.stories.ts +4 -4
  19. package/src/components/Buttons/FdsButtonDownload/FdsButtonDownload.vue +12 -2
  20. package/src/components/Buttons/FdsButtonDownload/types.ts +2 -0
  21. package/src/components/Buttons/FdsButtonIcon/FdsButtonIcon.stories.ts +2 -2
  22. package/src/components/Buttons/FdsButtonMinor/FdsButtonMinor.stories.ts +2 -2
  23. package/src/components/Buttons/FdsButtonMinor/FdsButtonMinor.vue +3 -0
  24. package/src/components/Buttons/FdsButtonPrimary/FdsButtonPrimary.stories.ts +4 -4
  25. package/src/components/Buttons/FdsButtonPrimary/FdsButtonPrimary.vue +0 -5
  26. package/src/components/Buttons/FdsButtonSecondary/FdsButtonSecondary.stories.ts +2 -2
  27. package/src/components/FdsIcon/FdsIcon.stories.ts +1 -1
  28. package/src/components/FdsModal/FdsModal.stories.ts +7 -7
  29. package/src/components/FdsModal/FdsModal.vue +6 -1
  30. package/src/components/FdsPagination/FdsPagination.stories.ts +5 -5
  31. package/src/components/FdsSearchSelect/FdsSearchSelect.stories.ts +9 -9
  32. package/src/components/FdsSpinner/FdsSpinner.stories.ts +1 -1
  33. package/src/components/FdsSticker/FdsSticker.stories.ts +23 -20
  34. package/src/components/FdsSticker/FdsSticker.vue +8 -6
  35. package/src/components/FdsSticker/types.ts +1 -0
  36. package/src/components/FdsTreeView/FdsTreeView.stories.ts +1 -1
  37. package/src/components/FdsTruncatedText/FdsTruncatedText.stories.ts +4 -4
  38. package/src/components/FdsTruncatedText/FdsTruncatedText.vue +6 -7
  39. package/src/components/Form/FdsCheckbox/FdsCheckbox.stories.ts +4 -4
  40. package/src/components/Form/FdsCheckbox/FdsCheckbox.vue +6 -6
  41. package/src/components/Form/FdsInput/FdsInput.stories.ts +5 -5
  42. package/src/components/Form/FdsInput/FdsInput.vue +14 -19
  43. package/src/components/Form/FdsRadio/FdsRadio.stories.ts +1 -1
  44. package/src/components/Form/FdsRadio/FdsRadio.vue +19 -6
  45. package/src/components/Form/FdsRadio/types.ts +2 -0
  46. package/src/components/Form/FdsSelect/FdsSelect.stories.ts +4 -4
  47. package/src/components/Form/FdsSelect/FdsSelect.vue +5 -1
  48. package/src/components/Form/FdsTextarea/FdsTextarea.stories.ts +2 -2
  49. package/src/components/Table/FdsTable/FdsTable.stories.ts +3 -3
  50. package/src/components/Table/FdsTableHead/FdsTableHead.stories.ts +6 -6
  51. package/src/components/Table/FdsTableHead/FdsTableHead.vue +9 -15
  52. package/src/components/Table/FdsTableHead/types.ts +1 -0
  53. package/src/components/Tabs/FdsTabs/FdsTabs.stories.ts +9 -9
  54. package/src/components/Tabs/FdsTabs/FdsTabs.vue +5 -1
  55. package/src/components/Tabs/FdsTabsItem/FdsTabsItem.vue +28 -2
  56. package/src/components/Tabs/FdsTabsItem/types.ts +4 -0
  57. package/src/components/Typography/FdsText/FdsText.stories.ts +14 -14
  58. package/src/components/Typography/FdsText/FdsText.vue +18 -2
  59. package/src/components/Typography/FdsText/types.ts +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fds-vue-core",
3
- "version": "2.1.11",
3
+ "version": "2.1.16",
4
4
  "description": "FDS Vue Core Component Library",
5
5
  "type": "module",
6
6
  "main": "./dist/fds-vue-core.cjs.js",
@@ -70,13 +70,12 @@
70
70
  "vue-imask": "^7.6.1"
71
71
  },
72
72
  "devDependencies": {
73
- "@chromatic-com/storybook": "^4.1.1",
74
- "@storybook/addon-a11y": "^9.1.10",
75
- "@storybook/addon-controls": "^9.0.8",
76
- "@storybook/addon-docs": "^9.1.11",
77
- "@storybook/addon-onboarding": "^9.1.10",
78
- "@storybook/addon-vitest": "^9.1.10",
79
- "@storybook/vue3-vite": "^9.1.10",
73
+ "@chromatic-com/storybook": "^4.1.3",
74
+ "@storybook/addon-a11y": "^10.1.10",
75
+ "@storybook/addon-docs": "^10.1.10",
76
+ "@storybook/addon-onboarding": "^10.1.10",
77
+ "@storybook/addon-vitest": "^10.1.10",
78
+ "@storybook/vue3-vite": "^10.1.10",
80
79
  "@tailwindcss/vite": "^4.1.18",
81
80
  "@tsconfig/node22": "^22.0.5",
82
81
  "@types/node": "^22.16.5",
@@ -90,14 +89,13 @@
90
89
  "@vue/eslint-config-typescript": "^14.6.0",
91
90
  "@vue/tsconfig": "^0.8.1",
92
91
  "eslint": "^9.39.2",
93
- "eslint-plugin-storybook": "^9.1.10",
92
+ "eslint-plugin-storybook": "^10.1.10",
94
93
  "eslint-plugin-vue": "~10.6.2",
95
94
  "lit": "^3.3.1",
96
95
  "playwright": "^1.57.0",
97
96
  "prettier": "3.7.4",
98
97
  "sass": "^1.96.0",
99
- "storybook": "^9.1.10",
100
- "storybook-vue-slots": "^9.1.5",
98
+ "storybook": "^10.1.10",
101
99
  "typescript": "~5.9.3",
102
100
  "vite": "^7.2.7",
103
101
  "vite-plugin-dts": "^4.5.4",
@@ -1,10 +1,50 @@
1
1
  import type { Meta, StoryObj } from '@storybook/vue3'
2
2
  import FdsBlockAlert from './FdsBlockAlert.vue'
3
3
 
4
+ const blockAlertTransform = (
5
+ _src: string,
6
+ storyContext: {
7
+ args?: {
8
+ visible?: boolean
9
+ label?: string
10
+ closeable?: boolean
11
+ collapsable?: boolean
12
+ expanded?: boolean
13
+ locale?: string
14
+ default?: string
15
+ }
16
+ },
17
+ ) => {
18
+ const args = storyContext?.args || {}
19
+ const attrs = []
20
+
21
+ if (args.label) attrs.push(`label="${args.label}"`)
22
+ if (args.closeable) attrs.push(':closeable="true"')
23
+ if (args.collapsable) attrs.push(':collapsable="true"')
24
+ if (args.expanded) attrs.push(':expanded="true"')
25
+ if (args.locale && args.locale !== 'sv') attrs.push(`locale="${args.locale}"`)
26
+
27
+ const attrsStr = attrs.length ? ` ${attrs.join(' ')}` : ''
28
+ let content = ''
29
+
30
+ if (args.default) {
31
+ content = `\n <p>${args.default}</p>\n`
32
+ }
33
+
34
+ return `<FdsBlockAlert${attrsStr}>${content}</FdsBlockAlert>`
35
+ }
36
+
4
37
  const meta: Meta<typeof FdsBlockAlert> = {
5
38
  title: 'FDS/Blocks/FdsBlockAlert',
6
39
  component: FdsBlockAlert,
7
40
  tags: ['autodocs'],
41
+ parameters: {
42
+ docs: {
43
+ source: {
44
+ transform: blockAlertTransform,
45
+ },
46
+ },
47
+ },
8
48
  argTypes: {
9
49
  closeable: { control: { type: 'boolean' } },
10
50
  collapsable: { control: { type: 'boolean' } },
@@ -26,44 +66,12 @@ const meta: Meta<typeof FdsBlockAlert> = {
26
66
  export default meta
27
67
  type Story = StoryObj<typeof meta>
28
68
 
29
- const blockAlertTransform = (storyContext: {
30
- args?: {
31
- visible?: boolean
32
- label?: string
33
- closeable?: boolean
34
- collapsable?: boolean
35
- expanded?: boolean
36
- locale?: string
37
- default?: string
38
- }
39
- }) => {
40
- const args = storyContext?.args || {}
41
- const attrs = []
42
-
43
- if (args.label) attrs.push(`label="${args.label}"`)
44
- if (args.closeable) attrs.push(':closeable="true"')
45
- if (args.collapsable) attrs.push(':collapsable="true"')
46
- if (args.expanded) attrs.push(':expanded="true"')
47
- if (args.locale && args.locale !== 'sv') attrs.push(`locale="${args.locale}"`)
48
-
49
- const attrsStr = attrs.length ? ` ${attrs.join(' ')}` : ''
50
- const content = args.default ? `\n <p>${args.default}</p>\n` : ''
51
- return `<FdsBlockAlert${attrsStr}>${content}</FdsBlockAlert>`
52
- }
53
-
54
69
  export const Default: Story = {
55
- render: (args) => ({
70
+ render: (args: Story['args']) => ({
56
71
  components: { FdsBlockAlert },
57
72
  setup: () => ({ args }),
58
73
  template: `<FdsBlockAlert v-bind="args"><p>{{ args.default }}</p></FdsBlockAlert>`,
59
74
  }),
60
- parameters: {
61
- docs: {
62
- source: {
63
- transform: blockAlertTransform,
64
- },
65
- },
66
- },
67
75
  args: {
68
76
  label: 'About this component',
69
77
  default: 'This is an alert block with some important information.',
@@ -79,6 +87,15 @@ export const WithLabel: Story = {
79
87
  </FdsBlockAlert>
80
88
  `,
81
89
  }),
90
+ parameters: {
91
+ docs: {
92
+ source: {
93
+ transform: () => `<FdsBlockAlert label="Information">
94
+ <p>This alert block has a <a href="test" class="link">test</a> label and provides important information to the user.</p>
95
+ </FdsBlockAlert>`,
96
+ },
97
+ },
98
+ },
82
99
  }
83
100
 
84
101
  export const Collapsable: Story = {
@@ -91,4 +108,14 @@ export const Collapsable: Story = {
91
108
  </FdsBlockAlert>
92
109
  `,
93
110
  }),
111
+ parameters: {
112
+ docs: {
113
+ source: {
114
+ transform: () => `<FdsBlockAlert label="Collapsable Alert" collapsable>
115
+ <p>This alert block can be collapsed and expanded. The content below is only visible when expanded.</p>
116
+ <p>Additional details about the alert can be shown here.</p>
117
+ </FdsBlockAlert>`,
118
+ },
119
+ },
120
+ },
94
121
  }
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { computed, ref, watch } from 'vue'
2
+ import { computed, ref, watch, type Slot } from 'vue'
3
3
  import { useHasSlot } from '../../../composables/useHasSlots'
4
4
  import FdsButtonIcon from '../../Buttons/FdsButtonIcon/FdsButtonIcon.vue'
5
5
  import FdsIcon from '../../FdsIcon/FdsIcon.vue'
@@ -54,6 +54,10 @@ function handleToggle() {
54
54
  isExpanded.value = !isExpanded.value
55
55
  emit('toggle')
56
56
  }
57
+
58
+ defineSlots<{
59
+ default?: Slot
60
+ }>()
57
61
  </script>
58
62
 
59
63
  <template>
@@ -1,10 +1,53 @@
1
1
  import type { Meta, StoryObj } from '@storybook/vue3'
2
2
  import FdsBlockContent from './FdsBlockContent.vue'
3
3
 
4
+ const blockContentTransform = (
5
+ _src: string,
6
+ storyContext: {
7
+ args?: {
8
+ heading?: string
9
+ headerInfo?: string
10
+ default?: string
11
+ tight?: boolean
12
+ color?: string
13
+ borderLeft?: boolean
14
+ }
15
+ },
16
+ ) => {
17
+ const args = storyContext?.args || {}
18
+ const attrs = []
19
+ if (args.heading) attrs.push(`heading="${args.heading}"`)
20
+ if (args.tight) attrs.push(`:tight="true"`)
21
+ if (args.color && args.color !== 'blue') attrs.push(`color="${args.color}"`)
22
+ if (args.borderLeft) attrs.push(`:borderLeft="true"`)
23
+
24
+ const attrsStr = attrs.length ? ` ${attrs.join(' ')}` : ''
25
+ let content = ''
26
+
27
+ if (args.headerInfo || args.default) {
28
+ content = '\n'
29
+ if (args.headerInfo) {
30
+ content += ` <template #headerInfo>\n <div v-html='${args.headerInfo}' />\n </template>\n`
31
+ }
32
+ if (args.default) {
33
+ content += ` <p>${args.default}</p>\n`
34
+ }
35
+ }
36
+
37
+ return `<FdsBlockContent${attrsStr}>${content}</FdsBlockContent>`
38
+ }
39
+
4
40
  const meta: Meta<typeof FdsBlockContent> = {
5
41
  title: 'FDS/Blocks/FdsBlockContent',
6
42
  component: FdsBlockContent,
7
43
  tags: ['autodocs'],
44
+ parameters: {
45
+ docs: {
46
+ source: {
47
+ transform: blockContentTransform,
48
+ },
49
+ },
50
+ },
8
51
  argTypes: {
9
52
  heading: { control: { type: 'text' } },
10
53
  borderLeft: { control: { type: 'radio' }, options: ['', 'green', 'yellow', 'red'] },
@@ -28,41 +71,8 @@ const meta: Meta<typeof FdsBlockContent> = {
28
71
  export default meta
29
72
  type Story = StoryObj<typeof meta>
30
73
 
31
- const blockContentTransform = (storyContext: {
32
- args?: {
33
- heading?: string
34
- headerInfo?: string
35
- default?: string
36
- tight?: boolean
37
- color?: string
38
- borderLeft?: boolean
39
- }
40
- }) => {
41
- const args = storyContext?.args || {}
42
- const attrs = []
43
- if (args.heading) attrs.push(`heading="${args.heading}"`)
44
- if (args.tight) attrs.push(':tight="true"')
45
- if (args.color && args.color !== 'blue') attrs.push(`color="${args.color}"`)
46
- if (args.borderLeft) attrs.push(':borderLeft="true"')
47
-
48
- const attrsStr = attrs.length ? ` ${attrs.join(' ')}` : ''
49
- let content = ''
50
-
51
- if (args.headerInfo || args.default) {
52
- content = '\n'
53
- if (args.headerInfo) {
54
- content += ` <template #headerInfo>\n <div v-html="${args.headerInfo}" />\n </template>\n`
55
- }
56
- if (args.default) {
57
- content += ` <p>${args.default}</p>\n`
58
- }
59
- }
60
-
61
- return `<FdsBlockContent${attrsStr}>${content}</FdsBlockContent>`
62
- }
63
-
64
74
  export const Default: Story = {
65
- render: (args) => ({
75
+ render: (args: Story['args']) => ({
66
76
  components: { FdsBlockContent },
67
77
  setup: () => ({ args }),
68
78
  template: `
@@ -73,13 +83,6 @@ export const Default: Story = {
73
83
  <p>{{ args.default }}</p>
74
84
  </FdsBlockContent>`,
75
85
  }),
76
- parameters: {
77
- docs: {
78
- source: {
79
- transform: blockContentTransform,
80
- },
81
- },
82
- },
83
86
  args: {
84
87
  heading: 'About this component',
85
88
  default:
@@ -2,10 +2,42 @@ import type { Meta, StoryObj } from '@storybook/vue3'
2
2
  import icons from '../../../assets/icons'
3
3
  import FdsBlockExpander from './FdsBlockExpander.vue'
4
4
 
5
+ const blockExpanderTransform = (
6
+ _src: string,
7
+ storyContext: {
8
+ args?: {
9
+ label?: string
10
+ preIcon?: string
11
+ open?: boolean
12
+ disabled?: boolean
13
+ default?: string
14
+ }
15
+ },
16
+ ) => {
17
+ const args = storyContext?.args || {}
18
+ const attrs = []
19
+
20
+ if (args.label) attrs.push(`label="${args.label}"`)
21
+ if (args.preIcon) attrs.push(`preIcon="${args.preIcon}"`)
22
+ if (args.open) attrs.push(':open="true"')
23
+ if (args.disabled) attrs.push(':disabled="true"')
24
+
25
+ const attrsStr = attrs.length ? ` ${attrs.join(' ')}` : ''
26
+ const content = args.default ? `\n <p>${args.default}</p>\n` : ''
27
+ return `<FdsBlockExpander${attrsStr}>${content}</FdsBlockExpander>`
28
+ }
29
+
5
30
  const meta: Meta<typeof FdsBlockExpander> = {
6
31
  title: 'FDS/Blocks/FdsBlockExpander',
7
32
  component: FdsBlockExpander,
8
33
  tags: ['autodocs'],
34
+ parameters: {
35
+ docs: {
36
+ source: {
37
+ transform: blockExpanderTransform,
38
+ },
39
+ },
40
+ },
9
41
  argTypes: {
10
42
  disabled: { control: { type: 'boolean' } },
11
43
  open: { control: { type: 'boolean' } },
@@ -25,41 +57,12 @@ const meta: Meta<typeof FdsBlockExpander> = {
25
57
  export default meta
26
58
  type Story = StoryObj<typeof meta>
27
59
 
28
- const blockExpanderTransform = (storyContext: {
29
- args?: {
30
- label?: string
31
- preIcon?: string
32
- open?: boolean
33
- disabled?: boolean
34
- default?: string
35
- }
36
- }) => {
37
- const args = storyContext?.args || {}
38
- const attrs = []
39
-
40
- if (args.label) attrs.push(`label="${args.label}"`)
41
- if (args.preIcon) attrs.push(`preIcon="${args.preIcon}"`)
42
- if (args.open) attrs.push(':open="true"')
43
- if (args.disabled) attrs.push(':disabled="true"')
44
-
45
- const attrsStr = attrs.length ? ` ${attrs.join(' ')}` : ''
46
- const content = args.default ? `\n <p>${args.default}</p>\n` : ''
47
- return `<FdsBlockExpander${attrsStr}>${content}</FdsBlockExpander>`
48
- }
49
-
50
60
  export const Default: Story = {
51
- render: (args) => ({
61
+ render: (args: Story['args']) => ({
52
62
  components: { FdsBlockExpander },
53
63
  setup: () => ({ args }),
54
64
  template: `<FdsBlockExpander v-bind="args"><p>{{ args.default }}</p></FdsBlockExpander>`,
55
65
  }),
56
- parameters: {
57
- docs: {
58
- source: {
59
- transform: blockExpanderTransform,
60
- },
61
- },
62
- },
63
66
  args: {
64
67
  label: 'Expandable Content',
65
68
  default: 'This is the expandable content that shows when the block is opened.',
@@ -1,21 +1,35 @@
1
1
  <script setup lang="ts">
2
- import { computed, ref, watch } from 'vue'
2
+ import { computed, ref, useAttrs, watch, type Slot } from 'vue'
3
+ import { useHasSlot } from '../../../composables/useHasSlots'
3
4
  import FdsIcon from '../../FdsIcon/FdsIcon.vue'
4
5
  import type { FdsExpanderBlockProps } from './types'
5
6
 
7
+ defineOptions({
8
+ inheritAttrs: false,
9
+ })
10
+
11
+ const attrs = useAttrs()
12
+
6
13
  const props = withDefaults(defineProps<FdsExpanderBlockProps>(), {
7
14
  disabled: false,
8
15
  label: '',
9
16
  open: false,
10
17
  preIcon: undefined,
18
+ id: undefined,
19
+ dataTestid: undefined,
11
20
  })
12
21
 
22
+ const hasExtraRowSlot = useHasSlot('extra-row')
23
+
13
24
  const emit = defineEmits<{
14
25
  (e: 'toggle'): void
15
26
  }>()
16
27
 
17
28
  const isOpen = ref(props.open)
18
29
 
30
+ const autoId = `fds-block-expander-${Math.random().toString(36).slice(2, 9)}`
31
+ const blockExpanderId = computed(() => props.id ?? autoId)
32
+
19
33
  // Watch for changes to the open prop
20
34
  watch(
21
35
  () => props.open,
@@ -30,37 +44,58 @@ const expanderClasses = computed(() => [
30
44
  ])
31
45
 
32
46
  const headerClasses = computed(() => [
33
- 'flex w-full items-start text-left justify-between bg-white text-blue-600 rounded-2xl p-[calc(1rem-2px)] border-2 border-white transition-colors border-2 border-white hover:border-blue-500 active:bg-blue_t-100 active:border-white focus-visible:border-blue-500 focus-visible:border-dashed focus-visible:outline-0',
47
+ 'flex w-full flex-col text-left bg-white text-blue-600 rounded-2xl p-[calc(1rem-2px)] border-2 border-white transition-colors border-2 border-white hover:border-blue-500 active:bg-blue_t-100 active:border-white focus-visible:border-blue-500 focus-visible:border-dashed focus-visible:outline-0',
34
48
  props.disabled ? 'cursor-not-allowed hover:border-2 hover:border-transparent active:bg-white' : 'cursor-pointer',
35
49
  isOpen.value ? 'rounded-b-none' : 'rounded-b-2xl',
50
+ hasExtraRowSlot.value ? '' : '',
36
51
  ])
37
52
 
53
+ const buttonRowClasses = computed(() => ['flex justify-between items-start w-full', hasExtraRowSlot.value ? '' : ''])
54
+
55
+ const buttonAttrs = computed(() => ({
56
+ ...attrs,
57
+ 'data-testid': props.dataTestid,
58
+ id: blockExpanderId.value,
59
+ }))
60
+
38
61
  function handleToggle() {
39
62
  if (props.disabled) return
40
63
  isOpen.value = !isOpen.value
41
64
  emit('toggle')
42
65
  }
66
+
67
+ defineSlots<{
68
+ default?: Slot
69
+ 'extra-row'?: Slot
70
+ }>()
43
71
  </script>
44
72
 
45
73
  <template>
46
74
  <div :class="expanderClasses">
47
- <button type="button" :class="headerClasses" @click="handleToggle">
48
- <span class="inline-flex items-center">
49
- <span v-if="preIcon" class="flex items-center mr-4">
50
- <FdsIcon :name="preIcon" :size="24" class="fill-blue-500" :class="{ 'fill-gray-500': disabled }" />
51
- </span>
52
- <span class="inline-flex items-center">
53
- <span class="font-bold font-heading text-lg leading-md" :class="{ 'text-gray-500': disabled }">
54
- {{ label }}
75
+ <button v-bind="buttonAttrs" type="button" :class="headerClasses" @click="handleToggle">
76
+ <span :class="buttonRowClasses">
77
+ <span class="w-full flex justify-between items-start">
78
+ <span class="inline-flex items-center">
79
+ <span v-if="preIcon" class="flex items-center mr-4">
80
+ <FdsIcon :name="preIcon" :size="24" class="fill-blue-500" :class="{ 'fill-gray-500': disabled }" />
81
+ </span>
82
+ <span class="inline-flex items-center">
83
+ <span class="font-bold font-heading text-lg leading-md" :class="{ 'text-gray-500': disabled }">
84
+ {{ label }}
85
+ </span>
86
+ </span>
55
87
  </span>
88
+ <FdsIcon
89
+ name="arrowDown"
90
+ :size="24"
91
+ class="ml-4 transition-transform duration-200 fill-blue-500 min-w-6 min-h-6"
92
+ :class="{ 'rotate-180': isOpen, 'fill-gray-500': disabled }"
93
+ />
56
94
  </span>
57
95
  </span>
58
- <FdsIcon
59
- name="arrowDown"
60
- :size="24"
61
- class="ml-4 transition-transform duration-200 fill-blue-500 min-w-6 min-h-6"
62
- :class="{ 'rotate-180': isOpen, 'fill-gray-500': disabled }"
63
- />
96
+ <span v-if="hasExtraRowSlot && !isOpen" class="w-full flex mt-2">
97
+ <slot name="extra-row" />
98
+ </span>
64
99
  </button>
65
100
  <div :aria-hidden="!isOpen" class="mb-0-last-child block px-4 pb-6 rounded-b-2xl bg-white" v-show="isOpen">
66
101
  <slot />
@@ -5,4 +5,6 @@ export interface FdsExpanderBlockProps {
5
5
  label?: string
6
6
  open?: boolean
7
7
  preIcon?: FdsIconName
8
+ id?: string
9
+ dataTestid?: string
8
10
  }
@@ -2,10 +2,51 @@ import type { Meta, StoryObj } from '@storybook/vue3'
2
2
  import icons from '../../../assets/icons'
3
3
  import FdsBlockInfo from './FdsBlockInfo.vue'
4
4
 
5
+ const blockInfoTransform = (
6
+ _src: string,
7
+ storyContext: {
8
+ args?: {
9
+ heading?: string
10
+ headerInfo?: string
11
+ default?: string
12
+ icon?: string
13
+ tight?: boolean
14
+ }
15
+ },
16
+ ) => {
17
+ const args = storyContext?.args || {}
18
+ const attrs = []
19
+
20
+ if (args.icon) attrs.push(`icon="${args.icon}"`)
21
+ if (args.tight) attrs.push(`:tight="true"`)
22
+
23
+ const attrsStr = attrs.length ? ` ${attrs.join(' ')}` : ''
24
+ let content = ''
25
+
26
+ if (args.headerInfo || args.default) {
27
+ content = '\n'
28
+ if (args.headerInfo) {
29
+ content += ` <template #headerInfo>\n <div v-html='${args.headerInfo}' />\n </template>\n`
30
+ }
31
+ if (args.default) {
32
+ content += ` <p>${args.default}</p>\n`
33
+ }
34
+ }
35
+
36
+ return `<FdsBlockInfo${attrsStr}>${content}</FdsBlockInfo>`
37
+ }
38
+
5
39
  const meta: Meta<typeof FdsBlockInfo> = {
6
40
  title: 'FDS/Blocks/FdsBlockInfo',
7
41
  component: FdsBlockInfo,
8
42
  tags: ['autodocs'],
43
+ parameters: {
44
+ docs: {
45
+ source: {
46
+ transform: blockInfoTransform,
47
+ },
48
+ },
49
+ },
9
50
  argTypes: {
10
51
  heading: { control: { type: 'text' } },
11
52
  size: { control: { type: 'select' }, options: ['small', 'large'] },
@@ -30,39 +71,8 @@ const meta: Meta<typeof FdsBlockInfo> = {
30
71
  export default meta
31
72
  type Story = StoryObj<typeof meta>
32
73
 
33
- const blockInfoTransform = (storyContext: {
34
- args?: {
35
- heading?: string
36
- headerInfo?: string
37
- default?: string
38
- icon?: string
39
- tight?: boolean
40
- }
41
- }) => {
42
- const args = storyContext?.args || {}
43
- const attrs = []
44
-
45
- if (args.icon) attrs.push(`icon="${args.icon}"`)
46
- if (args.tight) attrs.push(':tight="true"')
47
-
48
- const attrsStr = attrs.length ? ` ${attrs.join(' ')}` : ''
49
- let content = ''
50
-
51
- if (args.headerInfo || args.default) {
52
- content = '\n'
53
- if (args.headerInfo) {
54
- content += ` <template #headerInfo>\n <div v-html="${args.headerInfo}" />\n </template>\n`
55
- }
56
- if (args.default) {
57
- content += ` <p>${args.default}</p>\n`
58
- }
59
- }
60
-
61
- return `<FdsBlockInfo${attrsStr}>${content}</FdsBlockInfo>`
62
- }
63
-
64
74
  export const Default: Story = {
65
- render: (args) => ({
75
+ render: (args: NonNullable<Story['args']>) => ({
66
76
  components: { FdsBlockInfo },
67
77
  setup: () => ({ args }),
68
78
  template: `
@@ -73,13 +83,6 @@ export const Default: Story = {
73
83
  <p>{{ args.default }}</p>
74
84
  </FdsBlockInfo>`,
75
85
  }),
76
- parameters: {
77
- docs: {
78
- source: {
79
- transform: blockInfoTransform,
80
- },
81
- },
82
- },
83
86
  args: {
84
87
  heading: 'About this component',
85
88
  default: