@bethinkpl/design-system 40.1.0 → 41.0.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 (66) hide show
  1. package/dist/design-system.css +1 -1
  2. package/dist/design-system.js +7437 -7344
  3. package/dist/design-system.js.map +1 -1
  4. package/dist/lib/js/components/Cards/Card/Card.vue.d.ts +0 -9
  5. package/dist/lib/js/components/Cards/CardExpandable/CardExpandable.vue.d.ts +0 -36
  6. package/dist/lib/js/components/DatePickers/DatePicker/DatePicker.vue.d.ts +1 -1
  7. package/dist/lib/js/components/Drawer/DrawerTile/DrawerTile.vue.d.ts +2 -2
  8. package/dist/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.consts.d.ts +17 -0
  9. package/dist/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.vue.d.ts +27 -0
  10. package/dist/lib/js/components/LabelValue/LabelValueItemGroup/LabelValueItemGroup.vue.d.ts +13 -0
  11. package/dist/lib/js/components/Pagination/Pagination.vue.d.ts +6 -2
  12. package/dist/lib/js/components/RichList/BasicRichListItem/BasicRichListItem.vue.d.ts +3 -12
  13. package/dist/lib/js/components/RichList/RichListItem/RichListItem.vue.d.ts +1 -1
  14. package/dist/lib/js/components/SelectList/SelectListItem/SelectListItem.vue.d.ts +6 -2
  15. package/dist/lib/js/components/SelectList/SelectListItemToggle/SelectListItemToggle.vue.d.ts +6 -2
  16. package/dist/lib/js/components/Stepper/Stepper.vue.d.ts +23 -0
  17. package/dist/lib/js/components/Stepper/index.d.ts +3 -0
  18. package/dist/lib/js/components/SurveyQuestions/SurveyQuestionOpenEnded/SurveyQuestionOpenEnded.vue.d.ts +0 -36
  19. package/dist/lib/js/components/SurveyQuestions/SurveyQuestionScale/SurveyQuestionScale.vue.d.ts +0 -36
  20. package/dist/lib/js/components/TextGroup/TextGroup.vue.d.ts +0 -3
  21. package/dist/lib/js/components/Tile/Tile.vue.d.ts +1 -1
  22. package/dist/lib/js/components/Toast/Toast.vue.d.ts +0 -36
  23. package/dist/lib/js/components/Toggles/ToggleButton/ToggleButton.vue.d.ts +1 -1
  24. package/dist/lib/js/components/TopNav/TopNav/TopNav.vue.d.ts +17 -0
  25. package/dist/lib/js/components/TopNav/TopNavBranding/TopNavBranding.vue.d.ts +33 -0
  26. package/dist/lib/js/components/TopNav/topNavStoryLogo.d.ts +1 -0
  27. package/dist/lib/js/index.d.ts +6 -5
  28. package/lib/js/components/Cards/Card/Card.vue +0 -11
  29. package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.consts.ts +20 -0
  30. package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.spec.ts +125 -0
  31. package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.stories.ts +69 -0
  32. package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.vue +101 -0
  33. package/lib/js/components/LabelValue/LabelValueItemGroup/LabelValueItemGroup.spec.ts +24 -0
  34. package/lib/js/components/LabelValue/LabelValueItemGroup/LabelValueItemGroup.stories.ts +31 -0
  35. package/lib/js/components/LabelValue/LabelValueItemGroup/LabelValueItemGroup.vue +19 -0
  36. package/lib/js/components/RichList/BasicRichListItem/BasicRichListItem.stories.ts +93 -8
  37. package/lib/js/components/RichList/BasicRichListItem/BasicRichListItem.vue +3 -0
  38. package/lib/js/components/RichList/RichListItem/RichListItem.stories.ts +83 -0
  39. package/lib/js/components/RichList/RichListItem/RichListItem.vue +11 -4
  40. package/lib/js/components/SelectList/SelectListItem/SelectListItem.stories.ts +7 -0
  41. package/lib/js/components/SelectList/SelectListItem/SelectListItem.vue +9 -3
  42. package/lib/js/components/Stepper/Stepper.spec.ts +99 -0
  43. package/lib/js/components/Stepper/Stepper.stories.ts +62 -0
  44. package/lib/js/components/Stepper/Stepper.vue +97 -0
  45. package/lib/js/components/Stepper/index.ts +3 -0
  46. package/lib/js/components/TextGroup/TextGroup.vue +0 -5
  47. package/lib/js/components/TopNav/TopNav/TopNav.spec.ts +56 -0
  48. package/lib/js/components/TopNav/TopNav/TopNav.stories.ts +99 -0
  49. package/lib/js/components/TopNav/TopNav/TopNav.vue +79 -0
  50. package/lib/js/components/TopNav/TopNavBranding/TopNavBranding.spec.ts +103 -0
  51. package/lib/js/components/TopNav/TopNavBranding/TopNavBranding.stories.ts +107 -0
  52. package/lib/js/components/TopNav/TopNavBranding/TopNavBranding.vue +102 -0
  53. package/lib/js/components/TopNav/topNavStoryLogo.ts +19 -0
  54. package/lib/js/index.ts +6 -5
  55. package/lib/js/styles/Radiuses/Radiuses.stories.ts +44 -0
  56. package/lib/js/styles/Shadows/Shadows.stories.scss +33 -0
  57. package/lib/js/styles/Shadows/Shadows.stories.ts +37 -0
  58. package/package.json +1 -1
  59. package/dist/lib/js/components/Drawer/DrawerListItem/DrawerListItem.consts.d.ts +0 -5
  60. package/dist/lib/js/components/Drawer/DrawerListItem/DrawerListItem.vue.d.ts +0 -406
  61. package/dist/lib/js/components/Drawer/DrawerListItemGroup/DrawerListItemGroup.vue.d.ts +0 -2
  62. package/lib/js/components/Drawer/DrawerListItem/DrawerListItem.consts.ts +0 -7
  63. package/lib/js/components/Drawer/DrawerListItem/DrawerListItem.stories.ts +0 -44
  64. package/lib/js/components/Drawer/DrawerListItem/DrawerListItem.vue +0 -83
  65. package/lib/js/components/Drawer/DrawerListItemGroup/DrawerListItemGroup.stories.ts +0 -31
  66. package/lib/js/components/Drawer/DrawerListItemGroup/DrawerListItemGroup.vue +0 -21
@@ -12,6 +12,9 @@ import {
12
12
  } from './RichListItem.consts';
13
13
  import { ICON_COLORS, ICONS } from '../../Icons/Icon';
14
14
  import { DsImage } from '../../../index';
15
+ import SlotPlaceholder, {
16
+ SLOT_PLACEHOLDER_SIZES,
17
+ } from '../../../../../.storybook/SlotPlaceholder/SlotPlaceholder.vue';
15
18
  import { useArgs } from '@storybook/preview-api';
16
19
  import { withActions } from '@storybook/addon-actions/decorator';
17
20
 
@@ -66,6 +69,9 @@ const expandStory = (story: StoryFn<typeof RichListItem>, args = {}) => {
66
69
  content: {
67
70
  control: 'text',
68
71
  },
72
+ leadingAccessory: {
73
+ control: 'text',
74
+ },
69
75
  metadata: {
70
76
  control: 'text',
71
77
  },
@@ -107,6 +113,7 @@ const expandStory = (story: StoryFn<typeof RichListItem>, args = {}) => {
107
113
  draggableIconClassName: 'draggableIconClassName-1',
108
114
 
109
115
  content: 'Content Slot',
116
+ leadingAccessory: '',
110
117
  metadata: 'Metadata Slot',
111
118
  actions: 'ACS',
112
119
 
@@ -170,6 +177,9 @@ const InteractiveStoryTemplate: StoryFn<typeof RichListItem> = (args) => {
170
177
  <template v-if="content" #content>
171
178
  <div v-html="content" />
172
179
  </template>
180
+ <template v-if="leadingAccessory" #leadingAccessory>
181
+ <div v-html="leadingAccessory" />
182
+ </template>
173
183
  <template v-if="metadata" #metadata>
174
184
  <div v-html="metadata" />
175
185
  </template>
@@ -183,6 +193,74 @@ const InteractiveStoryTemplate: StoryFn<typeof RichListItem> = (args) => {
183
193
  export const Interactive = InteractiveStoryTemplate.bind({});
184
194
  expandStory(Interactive);
185
195
 
196
+ const PlaceholderSlotsStoryTemplate: StoryFn<typeof RichListItem> = (args) => {
197
+ const [_, updateArgs] = useArgs();
198
+
199
+ return {
200
+ components: { RichListItem, SlotPlaceholder },
201
+ setup() {
202
+ return args;
203
+ },
204
+ data() {
205
+ return {
206
+ SLOT_PLACEHOLDER_SIZES,
207
+ };
208
+ },
209
+ methods: {
210
+ updateIsSelected(isSelected) {
211
+ updateArgs({ isSelected });
212
+ },
213
+ },
214
+ template: `
215
+ <rich-list-item
216
+ :size="size"
217
+ :type="type"
218
+ :layout="layout"
219
+ :is-interactive="isInteractive"
220
+ :is-draggable="isDraggable"
221
+ :is-dimmed="isDimmed"
222
+ :border-color="borderColor"
223
+ :border-color-hex="borderColorHex"
224
+ :draggable-icon-class-name="draggableIconClassName"
225
+ :state="state"
226
+ :background-color="backgroundColor"
227
+ :elevation="elevation"
228
+ :has-draggable-handler="hasDraggableHandler"
229
+ :has-actions-slot-divider="hasActionsSlotDivider"
230
+ :is-selectable="isSelectable"
231
+ :is-selected="isSelected"
232
+ @update:is-selected="updateIsSelected"
233
+ >
234
+ <template #media>
235
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="media" />
236
+ </template>
237
+ <template #leadingAccessory>
238
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="leadingAccessory" />
239
+ </template>
240
+ <template #content>
241
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="content" />
242
+ </template>
243
+ <template #metadata>
244
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="metadata" />
245
+ </template>
246
+ <template #actions>
247
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="actions" />
248
+ </template>
249
+ </rich-list-item>`,
250
+ };
251
+ };
252
+
253
+ export const PlaceholderSlots = PlaceholderSlotsStoryTemplate.bind({});
254
+ expandStory(PlaceholderSlots);
255
+ // All slots are provided by the story template, so their controls are not editable.
256
+ PlaceholderSlots.argTypes = {
257
+ ...PlaceholderSlots.argTypes,
258
+ content: { control: false },
259
+ leadingAccessory: { control: false },
260
+ metadata: { control: false },
261
+ actions: { control: false },
262
+ } as ArgTypes;
263
+
186
264
  const WithMediaStoryTemplate: StoryFn<typeof RichListItem> = (args) => {
187
265
  const [_, updateArgs] = useArgs();
188
266
 
@@ -245,3 +323,8 @@ expandStory(WithMedia, {
245
323
  imageSrcUsedInStoryBook:
246
324
  'https://storage.googleapis.com/media-manager/lek/018f6291-3956-7342-8e6b-0ee901d48643/018f6291-3a56-7213-aef6-b5da7253839f.jpg',
247
325
  });
326
+ // The media story does not use the leadingAccessory slot, so its control is not editable.
327
+ WithMedia.argTypes = {
328
+ ...WithMedia.argTypes,
329
+ leadingAccessory: { control: false },
330
+ } as ArgTypes;
@@ -37,6 +37,9 @@
37
37
  @click.prevent="$emit('icon-click')"
38
38
  />
39
39
  </div>
40
+ <div v-if="$slots.leadingAccessory" class="ds-richListItem__leadingAccessory">
41
+ <slot name="leadingAccessory" />
42
+ </div>
40
43
  <div class="ds-richListItem__content">
41
44
  <slot name="content" />
42
45
  </div>
@@ -136,7 +139,8 @@ $rich-list-item-media-horizontal-height: 80px;
136
139
  }
137
140
 
138
141
  #{$root}__dragAndDrop,
139
- #{$root}__iconWrapper {
142
+ #{$root}__iconWrapper,
143
+ #{$root}__leadingAccessory {
140
144
  align-items: center;
141
145
  padding: $space-3 $space-1 $space-3 $space-8;
142
146
  }
@@ -171,7 +175,8 @@ $rich-list-item-media-horizontal-height: 80px;
171
175
  padding: 0 $space-2 0 0;
172
176
 
173
177
  #{$root}__dragAndDrop,
174
- #{$root}__iconWrapper {
178
+ #{$root}__iconWrapper,
179
+ #{$root}__leadingAccessory {
175
180
  padding: $space-3 0 $space-3 $space-6;
176
181
  }
177
182
 
@@ -211,7 +216,8 @@ $rich-list-item-media-horizontal-height: 80px;
211
216
  }
212
217
 
213
218
  #{$root}__dragAndDrop,
214
- #{$root}__iconWrapper {
219
+ #{$root}__iconWrapper,
220
+ #{$root}__leadingAccessory {
215
221
  align-items: flex-start;
216
222
  padding: $space-6 0 0 $space-6;
217
223
  }
@@ -244,7 +250,8 @@ $rich-list-item-media-horizontal-height: 80px;
244
250
 
245
251
  &.-ds-small {
246
252
  #{$root}__dragAndDrop,
247
- #{$root}__iconWrapper {
253
+ #{$root}__iconWrapper,
254
+ #{$root}__leadingAccessory {
248
255
  padding: $space-4 $space-2 0 $space-4;
249
256
  }
250
257
 
@@ -39,6 +39,9 @@ const StoryTemplate: StoryFn<typeof SelectListItem> = (args) => ({
39
39
  <template v-if="args.accessorySlot" #accessory>
40
40
  <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" :label="args.accessorySlot" />
41
41
  </template>
42
+ <template v-if="args.metadataSlot" #metadata>
43
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" :label="args.metadataSlot" />
44
+ </template>
42
45
  </select-list-item>
43
46
  `,
44
47
  });
@@ -55,6 +58,7 @@ const args = {
55
58
  isSelected: false,
56
59
  selectionMode: SELECT_LIST_ITEM_SELECTION_MODE.SELECT_ONLY,
57
60
  accessorySlot: 'accessory',
61
+ metadataSlot: 'metadata',
58
62
  } as Args;
59
63
 
60
64
  const argTypes = {
@@ -77,6 +81,9 @@ const argTypes = {
77
81
  accessorySlot: {
78
82
  control: 'text',
79
83
  },
84
+ metadataSlot: {
85
+ control: 'text',
86
+ },
80
87
  } as ArgTypes;
81
88
 
82
89
  Interactive.argTypes = argTypes;
@@ -30,13 +30,15 @@
30
30
  <span class="ds-selectListItem__text">{{ label }}</span>
31
31
  </span>
32
32
 
33
+ <slot name="metadata" />
34
+
33
35
  <ds-icon
34
36
  v-if="isSelected"
35
37
  class="ds-selectListItem__iconRight"
36
38
  :icon="ICONS.FA_CHECK_SOLID"
37
39
  :size="ICON_SIZES.XX_SMALL"
38
40
  />
39
- <div v-else class="ds-selectListItem__placeholderRight" />
41
+ <div v-else-if="!hasMetadata" class="ds-selectListItem__placeholderRight" />
40
42
  </div>
41
43
  </template>
42
44
 
@@ -107,12 +109,10 @@
107
109
 
108
110
  &__iconRight {
109
111
  color: $color-primary-icon;
110
- margin-left: $space-6;
111
112
  }
112
113
 
113
114
  &__placeholderRight {
114
115
  flex-shrink: 0;
115
- margin-left: $space-6;
116
116
  width: $icon-xs;
117
117
  }
118
118
 
@@ -194,6 +194,12 @@ const {
194
194
  state?: SelectListItemState;
195
195
  }>();
196
196
 
197
+ const slots = defineSlots<{
198
+ accessory?: () => any;
199
+ metadata?: () => any;
200
+ }>();
201
+
197
202
  const isLoading = computed(() => state === SELECT_LIST_ITEM_STATES.LOADING);
198
203
  const isDisabled = computed(() => state === SELECT_LIST_ITEM_STATES.DISABLED);
204
+ const hasMetadata = computed(() => !!slots.metadata);
199
205
  </script>
@@ -0,0 +1,99 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { mount } from '@vue/test-utils';
3
+
4
+ import Stepper from './Stepper.vue';
5
+
6
+ interface createComponentOptions {
7
+ title?: string;
8
+ counterLabel?: string;
9
+ hasCounterValue?: boolean;
10
+ totalSteps?: number;
11
+ currentStep?: number;
12
+ }
13
+
14
+ describe('Stepper', () => {
15
+ const createComponent = ({
16
+ title,
17
+ counterLabel,
18
+ hasCounterValue,
19
+ totalSteps = 5,
20
+ currentStep = 1,
21
+ }: createComponentOptions = {}) => {
22
+ return mount(Stepper, {
23
+ props: {
24
+ title,
25
+ counterLabel,
26
+ hasCounterValue,
27
+ totalSteps,
28
+ currentStep,
29
+ },
30
+ });
31
+ };
32
+
33
+ it('should create', () => {
34
+ const component = createComponent();
35
+
36
+ expect(component.exists()).toBe(true);
37
+ });
38
+
39
+ it('renders one step per total step', () => {
40
+ const component = createComponent({ totalSteps: 4 });
41
+
42
+ expect(component.findAll('.ds-stepper__step')).toHaveLength(4);
43
+ });
44
+
45
+ it('marks the steps up to the current step as active', () => {
46
+ const component = createComponent({ totalSteps: 5, currentStep: 2 });
47
+
48
+ const steps = component.findAll('.ds-stepper__step');
49
+ expect(steps[0].classes()).toContain('-ds-active');
50
+ expect(steps[1].classes()).toContain('-ds-active');
51
+ expect(steps[2].classes()).not.toContain('-ds-active');
52
+ expect(steps[3].classes()).not.toContain('-ds-active');
53
+ expect(steps[4].classes()).not.toContain('-ds-active');
54
+ });
55
+
56
+ it('renders the title when provided', () => {
57
+ const title = 'My title';
58
+ const component = createComponent({ title });
59
+
60
+ expect(component.find('.ds-stepper__title').text()).toBe(title);
61
+ });
62
+
63
+ it('renders the counter value with the current and total steps by default', () => {
64
+ const component = createComponent({ totalSteps: 5, currentStep: 3 });
65
+
66
+ expect(component.find('.ds-stepper__counterValue').text()).toBe('3/5');
67
+ });
68
+
69
+ it('renders the counter label when provided', () => {
70
+ const counterLabel = 'Counter Label';
71
+ const component = createComponent({ counterLabel });
72
+
73
+ expect(component.find('.ds-stepper__counterLabel').text()).toBe(counterLabel);
74
+ });
75
+
76
+ it('does not render the counter label when it is not provided', () => {
77
+ const component = createComponent({ counterLabel: undefined });
78
+
79
+ expect(component.find('.ds-stepper__counterLabel').exists()).toBe(false);
80
+ });
81
+
82
+ it('hides only the counter value when hasCounterValue is false', () => {
83
+ const counterLabel = 'Counter Label';
84
+ const component = createComponent({ counterLabel, hasCounterValue: false });
85
+
86
+ expect(component.find('.ds-stepper__counterValue').exists()).toBe(false);
87
+ expect(component.find('.ds-stepper__counterLabel').text()).toBe(counterLabel);
88
+ });
89
+
90
+ it('does not render the header when there is no title, no counter label and the counter value is hidden', () => {
91
+ const component = createComponent({
92
+ title: undefined,
93
+ counterLabel: undefined,
94
+ hasCounterValue: false,
95
+ });
96
+
97
+ expect(component.find('.ds-stepper__header').exists()).toBe(false);
98
+ });
99
+ });
@@ -0,0 +1,62 @@
1
+ import Stepper from './Stepper.vue';
2
+
3
+ import { Args, ArgTypes, Meta, StoryFn } from '@storybook/vue3';
4
+
5
+ export default {
6
+ title: 'Components/Stepper',
7
+ component: Stepper,
8
+ } as Meta<typeof Stepper>;
9
+
10
+ const StoryTemplate: StoryFn<typeof Stepper> = (args) => ({
11
+ components: { Stepper },
12
+ setup() {
13
+ return args;
14
+ },
15
+ template: `
16
+ <stepper
17
+ :title="title"
18
+ :counter-label="counterLabel"
19
+ :has-counter-value="hasCounterValue"
20
+ :total-steps="totalSteps"
21
+ :current-step="currentStep"
22
+ />
23
+ `,
24
+ });
25
+
26
+ export const Interactive = StoryTemplate.bind({});
27
+
28
+ const args = {
29
+ title: 'Title here',
30
+ counterLabel: 'Counter Label',
31
+ hasCounterValue: true,
32
+ totalSteps: 5,
33
+ currentStep: 1,
34
+ } as Args;
35
+
36
+ const argTypes = {
37
+ title: {
38
+ control: 'text',
39
+ },
40
+ counterLabel: {
41
+ control: 'text',
42
+ },
43
+ hasCounterValue: {
44
+ control: 'boolean',
45
+ },
46
+ totalSteps: {
47
+ control: { type: 'number', min: 1 },
48
+ },
49
+ currentStep: {
50
+ control: { type: 'number', min: 0 },
51
+ },
52
+ } as ArgTypes;
53
+
54
+ Interactive.argTypes = argTypes;
55
+ Interactive.args = args;
56
+
57
+ Interactive.parameters = {
58
+ design: {
59
+ type: 'figma',
60
+ url: 'https://www.figma.com/design/xym3gXf0vBCofzksDtRDaU/INI-201-E-commerce?node-id=240-17773&m=dev',
61
+ },
62
+ };
@@ -0,0 +1,97 @@
1
+ <template>
2
+ <div class="ds-stepper">
3
+ <div v-if="title || counterLabel || hasCounterValue" class="ds-stepper__header">
4
+ <div class="ds-stepper__title">
5
+ {{ title }}
6
+ </div>
7
+ <div v-if="counterLabel || hasCounterValue" class="ds-stepper__counter">
8
+ <span v-if="counterLabel" class="ds-stepper__counterLabel">
9
+ {{ counterLabel }}
10
+ </span>
11
+ <span v-if="hasCounterValue" class="ds-stepper__counterValue">
12
+ {{ currentStep }}/{{ totalSteps }}
13
+ </span>
14
+ </div>
15
+ </div>
16
+ <div class="ds-stepper__steps">
17
+ <div
18
+ v-for="step in totalSteps"
19
+ :key="step"
20
+ class="ds-stepper__step"
21
+ :class="{ '-ds-active': step <= currentStep }"
22
+ />
23
+ </div>
24
+ </div>
25
+ </template>
26
+
27
+ <style lang="scss" scoped>
28
+ @import '../../../styles/settings/colors/tokens';
29
+ @import '../../../styles/settings/spacings';
30
+ @import '../../../styles/settings/typography/tokens';
31
+ @import '../../../styles/settings/radiuses';
32
+
33
+ .ds-stepper {
34
+ display: flex;
35
+ flex-direction: column;
36
+ gap: $space-2;
37
+ width: 100%;
38
+
39
+ &__header {
40
+ align-items: baseline;
41
+ display: flex;
42
+ gap: $space-4;
43
+ width: 100%;
44
+ }
45
+
46
+ &__title {
47
+ @include heading-m-default-regular;
48
+
49
+ color: $color-neutral-text-heavy;
50
+ flex: 1 0 0;
51
+ min-width: 0;
52
+ overflow: hidden;
53
+ text-overflow: ellipsis;
54
+ white-space: nowrap;
55
+ }
56
+
57
+ &__counter {
58
+ @include label-m-default-regular;
59
+
60
+ align-items: baseline;
61
+ color: $color-neutral-text-weak;
62
+ display: flex;
63
+ flex-shrink: 0;
64
+ gap: $space-2;
65
+ text-align: right;
66
+ }
67
+
68
+ &__steps {
69
+ align-items: center;
70
+ display: flex;
71
+ gap: $space-2;
72
+ width: 100%;
73
+ }
74
+
75
+ &__step {
76
+ background-color: $color-neutral-background-medium;
77
+ border-radius: $radius-xs;
78
+ flex: 1 0 0;
79
+ height: 4px;
80
+ min-width: 0;
81
+
82
+ &.-ds-active {
83
+ background-color: $color-primary-background-strong;
84
+ }
85
+ }
86
+ }
87
+ </style>
88
+
89
+ <script setup lang="ts">
90
+ const { hasCounterValue = true } = defineProps<{
91
+ title?: string;
92
+ counterLabel?: string;
93
+ hasCounterValue?: boolean;
94
+ totalSteps: number;
95
+ currentStep: number;
96
+ }>();
97
+ </script>
@@ -0,0 +1,3 @@
1
+ import Stepper from './Stepper.vue';
2
+
3
+ export default Stepper;
@@ -372,7 +372,6 @@ import {
372
372
  TEXT_GROUP_PROMINENCE,
373
373
  } from './TextGroup.consts';
374
374
  import DsTooltip from '../Tooltip';
375
- import { RemovedProp } from '../../utils/type.utils';
376
375
 
377
376
  const {
378
377
  size = TEXT_GROUP_SIZES.MEDIUM,
@@ -414,10 +413,6 @@ const {
414
413
  isSupportingTextTooltipEnabledOnMobile?: boolean;
415
414
  isSupportingTextTooltipAutoFilledWithContent?: boolean;
416
415
  supportingTextTooltipContent?: string;
417
-
418
- // Removed prop kept as a removal marker so existing usages fail type-checking.
419
- /** @deprecated use `mainTextColor` set to `primary` instead */
420
- isSelected?: RemovedProp<'use mainTextColor=primary instead'>;
421
416
  }>();
422
417
 
423
418
  const prominenceClassName = computed(() => `-ds-${prominence}`);
@@ -0,0 +1,56 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { mount } from '@vue/test-utils';
3
+ import { h } from 'vue';
4
+
5
+ import TopNav from './TopNav.vue';
6
+
7
+ describe('TopNav', () => {
8
+ it('should create', () => {
9
+ const component = mount(TopNav);
10
+
11
+ expect(component.exists()).toBe(true);
12
+ expect(component.find('.ds-topNav').exists()).toBe(true);
13
+ });
14
+
15
+ it('renders default slot content', () => {
16
+ const component = mount(TopNav, {
17
+ slots: {
18
+ default: () => h('span', { class: 'child' }, 'Default content'),
19
+ },
20
+ });
21
+
22
+ expect(component.find('.ds-topNav__default .child').text()).toBe('Default content');
23
+ });
24
+
25
+ it('renders the leading slot when provided', () => {
26
+ const component = mount(TopNav, {
27
+ slots: {
28
+ leading: () => h('span', { class: 'child' }, 'Leading content'),
29
+ },
30
+ });
31
+
32
+ expect(component.find('.ds-topNav__leading .child').text()).toBe('Leading content');
33
+ });
34
+
35
+ it('does not render the leading wrapper when the slot is not provided', () => {
36
+ const component = mount(TopNav);
37
+
38
+ expect(component.find('.ds-topNav__leading').exists()).toBe(false);
39
+ });
40
+
41
+ it('renders the trailing slot when provided', () => {
42
+ const component = mount(TopNav, {
43
+ slots: {
44
+ trailing: () => h('span', { class: 'child' }, 'Trailing content'),
45
+ },
46
+ });
47
+
48
+ expect(component.find('.ds-topNav__trailing .child').text()).toBe('Trailing content');
49
+ });
50
+
51
+ it('does not render the trailing wrapper when the slot is not provided', () => {
52
+ const component = mount(TopNav);
53
+
54
+ expect(component.find('.ds-topNav__trailing').exists()).toBe(false);
55
+ });
56
+ });
@@ -0,0 +1,99 @@
1
+ import TopNav from './TopNav.vue';
2
+
3
+ import { Meta, StoryFn } from '@storybook/vue3';
4
+ import TopNavBranding from '../TopNavBranding/TopNavBranding.vue';
5
+ import Flag from '../../Flag/Flag.vue';
6
+ import { FLAG_SIZES } from '../../Flag/Flag.consts';
7
+ import * as FLAGS from '../../Flag/flags';
8
+ import IconButton from '../../Buttons/IconButton/IconButton.vue';
9
+ import {
10
+ ICON_BUTTON_COLORS,
11
+ ICON_BUTTON_SIZES,
12
+ ICON_BUTTON_TYPES,
13
+ } from '../../Buttons/IconButton/IconButton.consts';
14
+ import { BUTTON_RADIUSES } from '../../Buttons/Button/Button.consts';
15
+ import { ICONS } from '../../Icons/Icon';
16
+ import Avatar from '../../Avatar/Avatar.vue';
17
+ import { AVATAR_SIZES } from '../../Avatar/Avatar.consts';
18
+ import SlotPlaceholder, {
19
+ SLOT_PLACEHOLDER_SIZES,
20
+ } from '../../../../../.storybook/SlotPlaceholder/SlotPlaceholder.vue';
21
+ import { TOP_NAV_STORY_LOGO } from '../topNavStoryLogo';
22
+
23
+ export default {
24
+ title: 'Components/TopNav/TopNav',
25
+ component: TopNav,
26
+ } as Meta<typeof TopNav>;
27
+
28
+ const FilledTemplate: StoryFn<typeof TopNav> = () => ({
29
+ components: { TopNav, TopNavBranding, Flag, IconButton, Avatar },
30
+ setup() {
31
+ return {
32
+ logo: TOP_NAV_STORY_LOGO,
33
+ FLAGS,
34
+ FLAG_SIZES,
35
+ ICONS,
36
+ ICON_BUTTON_COLORS,
37
+ ICON_BUTTON_SIZES,
38
+ ICON_BUTTON_TYPES,
39
+ BUTTON_RADIUSES,
40
+ AVATAR_SIZES,
41
+ };
42
+ },
43
+ template: `
44
+ <top-nav>
45
+ <template #leading>
46
+ <icon-button
47
+ :icon="ICONS.FA_BARS"
48
+ :size="ICON_BUTTON_SIZES.MEDIUM"
49
+ :type="ICON_BUTTON_TYPES.ICON_ONLY"
50
+ :color="ICON_BUTTON_COLORS.NEUTRAL"
51
+ :radius="BUTTON_RADIUSES.ROUNDED"
52
+ />
53
+ </template>
54
+ <top-nav-branding title="Bethink">
55
+ <template #logo>
56
+ <span v-html="logo" style="display: inline-flex;" />
57
+ </template>
58
+ <template #accessory>
59
+ <flag :flag="FLAGS.FLAG_POLAND" :size="FLAG_SIZES.XXS" />
60
+ </template>
61
+ </top-nav-branding>
62
+ <template #trailing>
63
+ <avatar username="Bethink User" :size="AVATAR_SIZES.X_SMALL" />
64
+ </template>
65
+ </top-nav>
66
+ `,
67
+ });
68
+
69
+ export const Filled = FilledTemplate.bind({});
70
+
71
+ const SlotPlaceholdersTemplate: StoryFn<typeof TopNav> = () => ({
72
+ components: { TopNav, SlotPlaceholder },
73
+ setup() {
74
+ return { SLOT_PLACEHOLDER_SIZES };
75
+ },
76
+ template: `
77
+ <top-nav>
78
+ <template #leading>
79
+ <slot-placeholder label="leading" :size="SLOT_PLACEHOLDER_SIZES.MEDIUM" />
80
+ </template>
81
+ <slot-placeholder label="default" :size="SLOT_PLACEHOLDER_SIZES.MEDIUM" />
82
+ <template #trailing>
83
+ <slot-placeholder label="trailing" :size="SLOT_PLACEHOLDER_SIZES.MEDIUM" />
84
+ </template>
85
+ </top-nav>
86
+ `,
87
+ });
88
+
89
+ export const SlotPlaceholders = SlotPlaceholdersTemplate.bind({});
90
+
91
+ const parameters = {
92
+ design: {
93
+ type: 'figma',
94
+ url: 'https://www.figma.com/design/xym3gXf0vBCofzksDtRDaU/INI-201-E-commerce?node-id=345-21287&m=dev',
95
+ },
96
+ };
97
+
98
+ Filled.parameters = parameters;
99
+ SlotPlaceholders.parameters = parameters;