tide-design-system 2.4.7 → 2.5.2

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 (50) hide show
  1. package/.storybook/main.ts +2 -0
  2. package/README.md +3 -1
  3. package/dist/css/reset.css +5 -1
  4. package/dist/css/utilities-base.css +6 -6
  5. package/dist/css/utilities-responsive.css +24 -24
  6. package/dist/css/variables.css +3 -0
  7. package/dist/style.css +1 -1
  8. package/dist/tide-design-system.cjs +2 -2
  9. package/dist/tide-design-system.esm.d.ts +152 -70
  10. package/dist/tide-design-system.esm.js +1375 -1243
  11. package/docs/assets/full-bleed.gif +0 -0
  12. package/docs/assets/layout-grid-default.webp +0 -0
  13. package/docs/assets/layout-grid-fluid.webp +0 -0
  14. package/docs/assets/layout-grid.webp +0 -0
  15. package/docs/configuation.md +47 -0
  16. package/docs/grid-layout.md +83 -0
  17. package/docs/upgrading.md +79 -0
  18. package/index.ts +4 -0
  19. package/package.json +1 -1
  20. package/src/assets/css/reset.css +5 -1
  21. package/src/assets/css/utilities-base.css +6 -6
  22. package/src/assets/css/utilities-responsive.css +24 -24
  23. package/src/assets/css/variables.css +3 -0
  24. package/src/components/TideAccordionItem.vue +21 -13
  25. package/src/components/TideAlert.vue +1 -1
  26. package/src/components/TideButtonSegmented.vue +14 -15
  27. package/src/components/TideChipFilter.vue +13 -7
  28. package/src/components/TideInputCheckbox.vue +0 -1
  29. package/src/components/TideInputSelect.vue +1 -1
  30. package/src/components/TideInputSelectDeprecated.vue +1 -1
  31. package/src/components/TideInputText.vue +2 -2
  32. package/src/components/TideInputTextDeprecated.vue +2 -2
  33. package/src/components/TideInputTextarea.vue +2 -2
  34. package/src/components/TideInputTextareaDeprecated.vue +2 -2
  35. package/src/components/TideModal.vue +33 -20
  36. package/src/components/TidePagination.vue +17 -19
  37. package/src/components/TideRating.vue +93 -0
  38. package/src/components/TideSheet.vue +24 -21
  39. package/src/components/TideSwitch.vue +23 -20
  40. package/src/components/TideTabs.vue +58 -0
  41. package/src/stories/TideAccordionItem.stories.ts +33 -34
  42. package/src/stories/TideButtonSegmented.stories.ts +33 -25
  43. package/src/stories/TideChipFilter.stories.ts +33 -23
  44. package/src/stories/TideInputCheckbox.stories.ts +18 -10
  45. package/src/stories/TideModal.stories.ts +33 -37
  46. package/src/stories/TidePagination.stories.ts +31 -20
  47. package/src/stories/TideRating.stories.ts +120 -0
  48. package/src/stories/TideSheet.stories.ts +33 -28
  49. package/src/stories/TideSwitch.stories.ts +33 -34
  50. package/src/stories/TideTabs.stories.ts +115 -0
Binary file
Binary file
@@ -0,0 +1,47 @@
1
+ # TIDE Configuration
2
+
3
+ You can configure global TIDE behavior using `provideTideConfig()`. Place it in a top-level file such as `app.vue` (anywhere Vue’s `provide()` works). See Vue’s docs on [provide/inject](https://vuejs.org/guide/components/provide-inject) for more details.
4
+
5
+ ## `provideTideConfig()`
6
+
7
+ ``` ts
8
+ import { provideTideConfig } from 'tide-design-system';
9
+
10
+ provideTideConfig({
11
+ linkComponent: 'a', // default
12
+ });
13
+ ```
14
+
15
+ ### Config values
16
+
17
+ | Key | Type | Default | Description |
18
+ | --- | --- | --- | --- |
19
+ | `linkComponent` | `'a' \| Component` | `'a'` | Replaces the root element used by link-based TIDE components. |
20
+
21
+ ## `linkComponent` (TIDE 2.5+)
22
+
23
+ Use this to replace all `<a>` elements in TIDE components with a custom component. Useful for frameworks like Nuxt.
24
+
25
+ ### Nuxt Example (using `NuxtLink`)
26
+
27
+ ``` vue
28
+ <!-- app.vue -->
29
+ <script setup lang="ts">
30
+ import { provideTideConfig } from 'tide-design-system';
31
+ import { NuxtLink } from '#components';
32
+
33
+ provideTideConfig({
34
+ linkComponent: NuxtLink,
35
+ });
36
+ </script>
37
+ ```
38
+
39
+ This updates all TIDE components that render links, including:
40
+
41
+ - TideLink
42
+ - TideButton (`:element="ELEMENT.LINK"`)
43
+ - TideCard (`:type="TYPE_CARD.ACTION"` with `href`)
44
+ - TideBreadCrumbs
45
+ - And others
46
+
47
+ All these will now render using `<NuxtLink />` automatically.
@@ -0,0 +1,83 @@
1
+ # TIDE Layout Grid Utility
2
+
3
+ TIDE provides a lightweight CSS Grid for consistent page alignment, gutters, and max-width, with minimal markup. It separates **layout** (page width, gutters) from **component** concerns (spacing, internal layout).
4
+
5
+ <img src="./assets/layout-grid.webp" width="937" height="420" /><br>
6
+
7
+ ## Core Concepts
8
+
9
+ ### Three-Column Grid
10
+
11
+ ```
12
+ | gutter | content | gutter |
13
+ ```
14
+
15
+ Direct children are stacked in the **center content column** by default.
16
+
17
+ ### Responsive Max Width
18
+
19
+ | Variant | Max content width | Class |
20
+ | ------- | ----------------- | ------------- |
21
+ | Default | 1232px | – |
22
+ | XL | 1920px | `CSS.GRID.XL` |
23
+
24
+ ``` vue
25
+ <div :class="[CSS.GRID.LAYOUT, CSS.GRID.XL]">...</div>
26
+ ```
27
+
28
+ ### Responsive Gutters
29
+
30
+ | Breakpoint | Min gutter |
31
+ | ---------- | ------------------ |
32
+ | XS | `--tide-spacing-1` |
33
+ | XS - SM | `--tide-spacing-2` |
34
+ | SM - MD | `--tide-spacing-4` |
35
+
36
+ ---
37
+
38
+ ## Usage
39
+
40
+ ### Page Layout Context
41
+
42
+ ``` vue
43
+ <div :class="[CSS.GRID.LAYOUT]">
44
+ <section><ArticleIntro /></section>
45
+ <section><ArticleBody /></section>
46
+ </div>
47
+ ```
48
+
49
+ Direct children are **centered automatically**, like so:
50
+
51
+ <img src="./assets/layout-grid-default.webp" width="937" height="420" /><br>
52
+
53
+ ### Full-Width / Edge-to-Edge Sections
54
+
55
+ Use `CSS.GRID.FLUID` to break out of the content column:
56
+
57
+ ``` vue
58
+ <div :class="[CSS.GRID.LAYOUT]">
59
+ <section><ArticleIntro /></section>
60
+
61
+ <section :class="[CSS.GRID.FLUID]">
62
+ <HeroBanner />
63
+ </section>
64
+
65
+ <section><ArticleBody /></section>
66
+ </div>
67
+ ```
68
+
69
+ The code in this example would result in a layout like this:
70
+
71
+ <img src="./assets/layout-grid-fluid.webp" width="937" height="420" /><br>
72
+
73
+ Notice the `<HeroBanner />` is no longer confined to the center column, and instead breaks out and stretches **edge-to-edge**. This section is now considered **fluid**.
74
+
75
+ Common use cases for fluid sections:
76
+
77
+ - Header/footer
78
+ - Full-bleed carousels
79
+ - Edge-to-edge hero sections
80
+ - Sticky bars
81
+ - Page sections with toned backgrounds
82
+
83
+ <img src="./assets/full-bleed.gif" width="127" height="277" /><br>
package/docs/upgrading.md CHANGED
@@ -4,6 +4,85 @@ This document provides step-by-step instructions for upgrading from previous ver
4
4
 
5
5
  ---
6
6
 
7
+ ## Upgrading from 2.4 → 2.5
8
+
9
+ ### What changed?
10
+
11
+ TIDE **2.5** updates several *stateful* components to use Vue’s `v-model` for two-way binding. This replaces each component’s old “value prop + change emit” pattern.
12
+
13
+ Affected components:
14
+
15
+ - `TideAccordionItem`
16
+ - `TideButtonSegmented`
17
+ - `TideChipFilter`
18
+ - `TideModal`
19
+ - `TideSheet`
20
+ - `TideSwitch`
21
+
22
+ ### How to migrate
23
+
24
+ #### 1. Replace old props with `v-model`
25
+
26
+ | Component | v2.4 prop | v2.5+ |
27
+ |---|---|---|
28
+ | TideAccordionItem | `:is-expanded` | `v-model` |
29
+ | TideButtonSegmented | `:active-tab` | `v-model` |
30
+ | TideChipFilter | `:is-active` | `v-model` |
31
+ | TideModal | `:is-open` | `v-model` |
32
+ | TideSheet | `:is-open` | `v-model` |
33
+ | TideSwitch | `:is-active` | `v-model` |
34
+
35
+ ##### 2.4 example
36
+
37
+ ```
38
+ <TideButtonSegmented
39
+ :active-tab="active"
40
+ @change="active = $event"
41
+ />
42
+ ```
43
+
44
+ ##### 2.5+
45
+
46
+ ``` vue
47
+ <TideButtonSegmented v-model="active" />
48
+ ```
49
+
50
+ #### 2. Replace old emits with `@update:modelValue`
51
+
52
+ | Component | Old emit | New emit |
53
+ |---|---|---|
54
+ | TideAccordionItem | `@toggle` | `@update:modelValue` |
55
+ | TideButtonSegmented | `@change` | `@update:modelValue` |
56
+ | TideChipFilter | `@click` | `@update:modelValue` |
57
+ | TideModal | `@close` | `@update:modelValue` |
58
+ | TideSheet | `@close` | `@update:modelValue` |
59
+ | TideSwitch | `@change` | `@update:modelValue` |
60
+
61
+ Use this only for **side effects**, not basic value updates.
62
+
63
+ Or use Vue’s `watch()`:
64
+
65
+ ``` ts
66
+ watch(active, doSomething);
67
+ ```
68
+
69
+ ### Handling cancellable modals (new API)
70
+
71
+ **2.4** used `@close` + manual logic.
72
+
73
+ **2.5+** introduces `:before-close`, which cancels dismissal if it returns `false`.
74
+
75
+ ```
76
+ <TideModal
77
+ v-model="isOpen"
78
+ :before-close="() => {
79
+ if (!confirm('Close modal?')) return false;
80
+ }"
81
+ >
82
+ ```
83
+
84
+ ✅ After these changes your project should be compatible with **TIDE 2.5**.
85
+
7
86
  ## Upgrading from 2.3 → 2.4
8
87
 
9
88
  ### Summary
package/index.ts CHANGED
@@ -35,9 +35,11 @@ import TideMenuItem from '@/components/TideMenuItem.vue';
35
35
  import TideModal from '@/components/TideModal.vue';
36
36
  import TidePagination from '@/components/TidePagination.vue';
37
37
  import TidePopover from '@/components/TidePopover.vue';
38
+ import TideRating from '@/components/TideRating.vue';
38
39
  import TideSeoLinks from '@/components/TideSeoLinks.vue';
39
40
  import TideSheet from '@/components/TideSheet.vue';
40
41
  import TideSwitch from '@/components/TideSwitch.vue';
42
+ import TideTabs from '@/components/TideTabs.vue';
41
43
  import { provideTideConfig } from '@/composables/useTideConfig';
42
44
  import { useTideForm } from '@/composables/useTideForm';
43
45
  import { ALERT } from '@/types/Alert';
@@ -182,7 +184,9 @@ export {
182
184
  TideModal,
183
185
  TidePagination,
184
186
  TidePopover,
187
+ TideRating,
185
188
  TideSeoLinks,
186
189
  TideSheet,
187
190
  TideSwitch,
191
+ TideTabs,
188
192
  };
package/package.json CHANGED
@@ -63,7 +63,7 @@
63
63
  "main": "dist/tide-design-system.cjs",
64
64
  "module": "dist/tide-design-system.esm.js",
65
65
  "types": "dist/tide-design-system.esm.d.ts",
66
- "version": "2.4.7",
66
+ "version": "2.5.2",
67
67
  "dependencies": {
68
68
  "@floating-ui/vue": "^1.1.6"
69
69
  }
@@ -7,6 +7,7 @@ body {
7
7
  font-size: var(--tide-font-16);
8
8
  font-weight: 400;
9
9
  line-height: 1.4;
10
+ text-wrap: pretty;
10
11
  }
11
12
 
12
13
  /* Cannot be applied to body tag in marketplace repo due to data-css-scope */
@@ -39,13 +40,16 @@ h2 {font-size: var(--tide-font-24);} /* 24px */
39
40
  h3 {font-size: var(--tide-font-20);} /* 20px */
40
41
  h4 {font-size: var(--tide-font-16);} /* 16px */
41
42
  h5 {font-size: var(--tide-font-16);} /* 16px */
43
+ h6 {font-size: var(--tide-font-16);} /* 16px */
42
44
 
43
45
  h1,
44
46
  h2,
45
47
  h3,
46
48
  h4,
47
- h5 {
49
+ h5,
50
+ h6 {
48
51
  font-weight: 700;
52
+ text-wrap: balance;
49
53
  }
50
54
 
51
55
  img,
@@ -294,12 +294,12 @@
294
294
  .tide-transparent-400 {background-color: var(--tide-transparent-400);}
295
295
 
296
296
  /* Typographic roles */
297
- .tide-typography-display-1 {font-size: var(--tide-font-32); font-weight: 700;}
298
- .tide-typography-headline-1 {font-size: var(--tide-font-24); font-weight: 700;}
299
- .tide-typography-headline-2 {font-size: var(--tide-font-20); font-weight: 700;}
300
- .tide-typography-headline-3 {font-size: var(--tide-font-16); font-weight: 700;}
301
- .tide-typography-title-1 {font-size: var(--tide-font-20); font-weight: 600;}
302
- .tide-typography-title-2 {font-size: var(--tide-font-18); font-weight: 600;}
297
+ .tide-typography-display-1 {font-size: var(--tide-font-32); font-weight: 700; text-wrap: balance;}
298
+ .tide-typography-headline-1 {font-size: var(--tide-font-24); font-weight: 700; text-wrap: balance;}
299
+ .tide-typography-headline-2 {font-size: var(--tide-font-20); font-weight: 700; text-wrap: balance;}
300
+ .tide-typography-headline-3 {font-size: var(--tide-font-16); font-weight: 700; text-wrap: balance;}
301
+ .tide-typography-title-1 {font-size: var(--tide-font-20); font-weight: 600; text-wrap: balance;}
302
+ .tide-typography-title-2 {font-size: var(--tide-font-18); font-weight: 600; text-wrap: balance;}
303
303
  .tide-typography-body-1 {font-size: var(--tide-font-16); font-weight: 400;}
304
304
  .tide-typography-body-2 {font-size: var(--tide-font-14); font-weight: 400;}
305
305
  .tide-typography-label-1 {font-size: var(--tide-font-16); font-weight: 500;}
@@ -295,12 +295,12 @@
295
295
  .sm-tide-transparent-400 {background-color: var(--tide-transparent-400);}
296
296
 
297
297
  /* Typographic roles */
298
- .sm-tide-typography-display-1 {font-size: var(--tide-font-32); font-weight: 700;}
299
- .sm-tide-typography-headline-1 {font-size: var(--tide-font-24); font-weight: 700;}
300
- .sm-tide-typography-headline-2 {font-size: var(--tide-font-20); font-weight: 700;}
301
- .sm-tide-typography-headline-3 {font-size: var(--tide-font-16); font-weight: 700;}
302
- .sm-tide-typography-title-1 {font-size: var(--tide-font-20); font-weight: 600;}
303
- .sm-tide-typography-title-2 {font-size: var(--tide-font-18); font-weight: 600;}
298
+ .sm-tide-typography-display-1 {font-size: var(--tide-font-32); font-weight: 700; text-wrap: balance;}
299
+ .sm-tide-typography-headline-1 {font-size: var(--tide-font-24); font-weight: 700; text-wrap: balance;}
300
+ .sm-tide-typography-headline-2 {font-size: var(--tide-font-20); font-weight: 700; text-wrap: balance;}
301
+ .sm-tide-typography-headline-3 {font-size: var(--tide-font-16); font-weight: 700; text-wrap: balance;}
302
+ .sm-tide-typography-title-1 {font-size: var(--tide-font-20); font-weight: 600; text-wrap: balance;}
303
+ .sm-tide-typography-title-2 {font-size: var(--tide-font-18); font-weight: 600; text-wrap: balance;}
304
304
  .sm-tide-typography-body-1 {font-size: var(--tide-font-16); font-weight: 400;}
305
305
  .sm-tide-typography-body-2 {font-size: var(--tide-font-14); font-weight: 400;}
306
306
  .sm-tide-typography-label-1 {font-size: var(--tide-font-16); font-weight: 500;}
@@ -843,12 +843,12 @@
843
843
  .md-tide-transparent-400 {background-color: var(--tide-transparent-400);}
844
844
 
845
845
  /* Typographic roles */
846
- .md-tide-typography-display-1 {font-size: var(--tide-font-32); font-weight: 700;}
847
- .md-tide-typography-headline-1 {font-size: var(--tide-font-24); font-weight: 700;}
848
- .md-tide-typography-headline-2 {font-size: var(--tide-font-20); font-weight: 700;}
849
- .md-tide-typography-headline-3 {font-size: var(--tide-font-16); font-weight: 700;}
850
- .md-tide-typography-title-1 {font-size: var(--tide-font-20); font-weight: 600;}
851
- .md-tide-typography-title-2 {font-size: var(--tide-font-18); font-weight: 600;}
846
+ .md-tide-typography-display-1 {font-size: var(--tide-font-32); font-weight: 700; text-wrap: balance;}
847
+ .md-tide-typography-headline-1 {font-size: var(--tide-font-24); font-weight: 700; text-wrap: balance;}
848
+ .md-tide-typography-headline-2 {font-size: var(--tide-font-20); font-weight: 700; text-wrap: balance;}
849
+ .md-tide-typography-headline-3 {font-size: var(--tide-font-16); font-weight: 700; text-wrap: balance;}
850
+ .md-tide-typography-title-1 {font-size: var(--tide-font-20); font-weight: 600; text-wrap: balance;}
851
+ .md-tide-typography-title-2 {font-size: var(--tide-font-18); font-weight: 600; text-wrap: balance;}
852
852
  .md-tide-typography-body-1 {font-size: var(--tide-font-16); font-weight: 400;}
853
853
  .md-tide-typography-body-2 {font-size: var(--tide-font-14); font-weight: 400;}
854
854
  .md-tide-typography-label-1 {font-size: var(--tide-font-16); font-weight: 500;}
@@ -1391,12 +1391,12 @@
1391
1391
  .lg-tide-transparent-400 {background-color: var(--tide-transparent-400);}
1392
1392
 
1393
1393
  /* Typographic roles */
1394
- .lg-tide-typography-display-1 {font-size: var(--tide-font-32); font-weight: 700;}
1395
- .lg-tide-typography-headline-1 {font-size: var(--tide-font-24); font-weight: 700;}
1396
- .lg-tide-typography-headline-2 {font-size: var(--tide-font-20); font-weight: 700;}
1397
- .lg-tide-typography-headline-3 {font-size: var(--tide-font-16); font-weight: 700;}
1398
- .lg-tide-typography-title-1 {font-size: var(--tide-font-20); font-weight: 600;}
1399
- .lg-tide-typography-title-2 {font-size: var(--tide-font-18); font-weight: 600;}
1394
+ .lg-tide-typography-display-1 {font-size: var(--tide-font-32); font-weight: 700; text-wrap: balance;}
1395
+ .lg-tide-typography-headline-1 {font-size: var(--tide-font-24); font-weight: 700; text-wrap: balance;}
1396
+ .lg-tide-typography-headline-2 {font-size: var(--tide-font-20); font-weight: 700; text-wrap: balance;}
1397
+ .lg-tide-typography-headline-3 {font-size: var(--tide-font-16); font-weight: 700; text-wrap: balance;}
1398
+ .lg-tide-typography-title-1 {font-size: var(--tide-font-20); font-weight: 600; text-wrap: balance;}
1399
+ .lg-tide-typography-title-2 {font-size: var(--tide-font-18); font-weight: 600; text-wrap: balance;}
1400
1400
  .lg-tide-typography-body-1 {font-size: var(--tide-font-16); font-weight: 400;}
1401
1401
  .lg-tide-typography-body-2 {font-size: var(--tide-font-14); font-weight: 400;}
1402
1402
  .lg-tide-typography-label-1 {font-size: var(--tide-font-16); font-weight: 500;}
@@ -1939,12 +1939,12 @@
1939
1939
  .xl-tide-transparent-400 {background-color: var(--tide-transparent-400);}
1940
1940
 
1941
1941
  /* Typographic roles */
1942
- .xl-tide-typography-display-1 {font-size: var(--tide-font-32); font-weight: 700;}
1943
- .xl-tide-typography-headline-1 {font-size: var(--tide-font-24); font-weight: 700;}
1944
- .xl-tide-typography-headline-2 {font-size: var(--tide-font-20); font-weight: 700;}
1945
- .xl-tide-typography-headline-3 {font-size: var(--tide-font-16); font-weight: 700;}
1946
- .xl-tide-typography-title-1 {font-size: var(--tide-font-20); font-weight: 600;}
1947
- .xl-tide-typography-title-2 {font-size: var(--tide-font-18); font-weight: 600;}
1942
+ .xl-tide-typography-display-1 {font-size: var(--tide-font-32); font-weight: 700; text-wrap: balance;}
1943
+ .xl-tide-typography-headline-1 {font-size: var(--tide-font-24); font-weight: 700; text-wrap: balance;}
1944
+ .xl-tide-typography-headline-2 {font-size: var(--tide-font-20); font-weight: 700; text-wrap: balance;}
1945
+ .xl-tide-typography-headline-3 {font-size: var(--tide-font-16); font-weight: 700; text-wrap: balance;}
1946
+ .xl-tide-typography-title-1 {font-size: var(--tide-font-20); font-weight: 600; text-wrap: balance;}
1947
+ .xl-tide-typography-title-2 {font-size: var(--tide-font-18); font-weight: 600; text-wrap: balance;}
1948
1948
  .xl-tide-typography-body-1 {font-size: var(--tide-font-16); font-weight: 400;}
1949
1949
  .xl-tide-typography-body-2 {font-size: var(--tide-font-14); font-weight: 400;}
1950
1950
  .xl-tide-typography-label-1 {font-size: var(--tide-font-16); font-weight: 500;}
@@ -38,6 +38,9 @@
38
38
  --tide-black: var(--tide-gray-900);
39
39
  --tide-white: var(--tide-gray-100);
40
40
 
41
+ /* CSS Grid */
42
+ --tide-safe-fr: minmax(0, 1fr);
43
+
41
44
  /* Opacity */
42
45
  --tide-disabled: 0.333;
43
46
 
@@ -5,12 +5,9 @@
5
5
  import { SIZE } from '@/types/Size';
6
6
  import { CSS } from '@/types/Styles';
7
7
 
8
- const emit = defineEmits(['toggle']);
9
-
10
8
  type Props = {
11
9
  hasBottomDivider?: boolean;
12
10
  hasTopDivider?: boolean;
13
- isExpanded?: boolean;
14
11
  isOptional?: boolean;
15
12
  label: string;
16
13
  };
@@ -18,22 +15,29 @@
18
15
  const props = withDefaults(defineProps<Props>(), {
19
16
  hasBottomDivider: false,
20
17
  hasTopDivider: false,
21
- isExpanded: false,
22
18
  isOptional: false,
23
- label: '',
24
19
  });
25
20
 
21
+ const isExpanded = defineModel<boolean>({ required: true });
22
+
26
23
  const handleToggleClick = () => {
27
- emit('toggle');
24
+ isExpanded.value = !isExpanded.value;
28
25
  };
29
26
  </script>
30
27
 
31
28
  <template>
32
- <div class="tide-accordion-item">
29
+ <div :class="['tide-accordion-item']">
33
30
  <TideDivider v-if="props.hasTopDivider" />
34
31
 
35
- <div
36
- :class="['tide-accordion-head', CSS.DISPLAY.FLEX, CSS.AXIS1.BETWEEN, CSS.PADDING.Y.HALF, CSS.CURSOR.POINTER]"
32
+ <button
33
+ :class="[
34
+ 'tide-accordion-head',
35
+ CSS.ALIGN.X.LEFT,
36
+ CSS.AXIS1.BETWEEN,
37
+ CSS.DISPLAY.FLEX,
38
+ CSS.PADDING.Y.HALF,
39
+ CSS.WIDTH.FULL,
40
+ ]"
37
41
  @click="handleToggleClick"
38
42
  >
39
43
  <div :class="[CSS.DISPLAY.FLEX, CSS.AXIS2.CENTER, CSS.GAP.HALF, CSS.FONT.ROLE.LABEL_1_SEMIBOLD]">
@@ -51,9 +55,9 @@
51
55
  :icon="isExpanded ? ICON.EXPAND_LESS : ICON.EXPAND_MORE"
52
56
  :size="SIZE.LARGE"
53
57
  />
54
- </div>
58
+ </button>
55
59
 
56
- <div :class="['tide-accordion-body', props.isExpanded ? 'expanded' : 'collapsed', CSS.DISPLAY.GRID]">
60
+ <div :class="['tide-accordion-body', isExpanded ? 'expanded' : 'collapsed', CSS.DISPLAY.GRID]">
57
61
  <div :class="[CSS.OVERFLOW.Y.HIDDEN, CSS.MARGIN.Y.ONE, CSS.FONT.ROLE.BODY_1, CSS.FONT.COLOR.SURFACE.DEFAULT]">
58
62
  <slot />
59
63
  </div>
@@ -64,15 +68,19 @@
64
68
  </template>
65
69
 
66
70
  <style scoped>
71
+ .tide-accordion-item {
72
+ align-self: stretch;
73
+ }
74
+
67
75
  .tide-accordion-body {
68
76
  transition: grid-template-rows var(--tide-animate);
69
77
  }
70
78
 
71
79
  .tide-accordion-body.expanded {
72
- grid-template-rows: 1fr;
80
+ grid-template-rows: minmax(0px, 1fr);
73
81
  }
74
82
 
75
83
  .tide-accordion-body.collapsed {
76
- grid-template-rows: 0fr;
84
+ grid-template-rows: minmax(0px, 0fr);
77
85
  }
78
86
  </style>
@@ -145,7 +145,7 @@
145
145
  grid-template-areas:
146
146
  'icon heading close'
147
147
  '. body .';
148
- grid-template-columns: auto 1fr auto;
148
+ grid-template-columns: auto var(--tide-safe-fr) auto;
149
149
  grid-column-gap: 0.5rem;
150
150
  max-width: 40rem;
151
151
  }
@@ -4,18 +4,15 @@
4
4
  import type { Tab } from '@/types/Tab';
5
5
 
6
6
  type Props = {
7
- activeTab: number;
8
- tabs: Tab[];
7
+ tabs: Tab[] | readonly Tab[];
9
8
  };
10
9
 
11
- const props = withDefaults(defineProps<Props>(), {
12
- activeTab: 0,
13
- });
10
+ defineProps<Props>();
14
11
 
15
- const emit = defineEmits(['change']);
12
+ const currentIndex = defineModel<number>({ required: true });
16
13
 
17
14
  const handleClick = (index: number) => {
18
- emit('change', index);
15
+ currentIndex.value = index;
19
16
  };
20
17
  </script>
21
18
 
@@ -24,33 +21,34 @@
24
21
  :class="[
25
22
  'tide-button-segmented',
26
23
  CSS.BG.SURFACE.VARIANT,
24
+ CSS.BORDER.RADIUS.FULL,
27
25
  CSS.DISPLAY.FLEX,
26
+ CSS.FLEX.SHRINK.OFF,
28
27
  CSS.GAP.QUARTER,
29
- CSS.BORDER.RADIUS.FULL,
28
+ CSS.OVERFLOW.XY.AUTO,
30
29
  CSS.PADDING.FULL.QUARTER,
31
- CSS.OVERFLOW.XY.HIDDEN,
32
- CSS.WIDTH.FULL,
33
30
  ]"
34
31
  >
35
32
  <button
36
33
  :class="[
37
34
  'tide-button-segmented-tab',
38
- index === activeTab
35
+ index === currentIndex
39
36
  ? [CSS.BG.SURFACE.DEFAULT, CSS.FONT.COLOR.SURFACE.DEFAULT, CSS.SHADOW.BOTTOM]
40
37
  : ['inactive', CSS.FONT.COLOR.SURFACE.VARIANT],
41
- CSS.FLEX.GROW.ON,
42
38
  CSS.BORDER.FULL.TWO,
43
39
  CSS.BORDER.RADIUS.FULL,
44
- CSS.PADDING.Y.QUARTER,
45
- CSS.WIDTH.FULL,
40
+ CSS.FLEX.GROW.ON,
46
41
  CSS.FONT.ROLE.BUTTON_1,
42
+ CSS.PADDING.X.HALF,
43
+ CSS.PADDING.Y.QUARTER,
47
44
  CSS.WHITESPACE_WRAP.OFF,
45
+ CSS.WIDTH.FULL,
48
46
  ]"
49
47
  :data-track="tab.dataTrack || undefined"
50
48
  :key="tab.label"
51
49
  @click="handleClick(index)"
52
50
  type="button"
53
- v-for="(tab, index) in props.tabs"
51
+ v-for="(tab, index) in tabs"
54
52
  >
55
53
  <span :class="[CSS.FONT.ROLE.LABEL_2_SEMIBOLD]">
56
54
  {{ tab.label }}
@@ -69,6 +67,7 @@
69
67
  <style scoped>
70
68
  .tide-button-segmented {
71
69
  max-width: 23.3rem;
70
+ align-self: stretch;
72
71
  }
73
72
 
74
73
  .tide-button-segmented-tab {
@@ -2,19 +2,24 @@
2
2
  import { CSS } from '@/types/Styles';
3
3
 
4
4
  type Props = {
5
- isActive: boolean;
6
5
  label: string;
7
6
  };
8
7
 
9
- const props = defineProps<Props>();
8
+ defineProps<Props>();
9
+
10
+ const isActive = defineModel<boolean>({ required: true });
11
+
12
+ const handleClick = () => {
13
+ isActive.value = !isActive.value;
14
+ };
10
15
  </script>
11
16
 
12
17
  <template>
13
18
  <button
14
19
  :class="[
15
20
  'tide-chip-filter',
16
- props.isActive
17
- ? [CSS.BG.SECONDARY, CSS.FONT.COLOR.SECONDARY]
21
+ isActive
22
+ ? ['active', CSS.BG.SECONDARY, CSS.FONT.COLOR.SECONDARY]
18
23
  : [CSS.BG.SURFACE.VARIANT, CSS.FONT.COLOR.SURFACE.DEFAULT],
19
24
  CSS.DISPLAY.FLEX,
20
25
  CSS.AXIS2.CENTER,
@@ -24,14 +29,15 @@
24
29
  CSS.PADDING.X.ONE,
25
30
  CSS.PADDING.Y.HALF,
26
31
  CSS.FONT.ROLE.LABEL_2,
27
- props.isActive ? 'active' : '',
28
32
  ]"
33
+ @click="handleClick"
29
34
  type="button"
30
35
  >
31
36
  <slot />
37
+
32
38
  <div :class="[CSS.DISPLAY.FLEX, CSS.AXIS1.CENTER, CSS.AXIS2.CENTER, CSS.GAP.HALF]">
33
- <span :class="[props.isActive ? '' : 'icon-spacing', CSS.FONT.ROLE.LABEL_1, CSS.WHITESPACE_WRAP.OFF]">
34
- {{ props.label }}
39
+ <span :class="[CSS.FONT.ROLE.LABEL_1, CSS.WHITESPACE_WRAP.OFF]">
40
+ {{ label }}
35
41
  </span>
36
42
  </div>
37
43
  </button>
@@ -107,7 +107,6 @@
107
107
  showError ? CSS.FONT.COLOR.GLOBAL.ERROR : CSS.FONT.COLOR.SURFACE.DEFAULT,
108
108
  disabled ? [CSS.OPACITY.DISABLED, CSS.CURSOR.NOT_ALLOWED] : [CSS.CURSOR.POINTER],
109
109
  ]"
110
- :for="inputId"
111
110
  >
112
111
  <input
113
112
  :checked="isChecked"
@@ -248,7 +248,7 @@
248
248
 
249
249
  .tide-input-select:focus-within .tide-input-border {
250
250
  --tide-input-outline-width: var(--tide-border-width-2);
251
- outline-color: var(--tide-surface-border-high);
251
+ outline-color: var(--tide-border-high);
252
252
  }
253
253
 
254
254
  .tide-input-border {
@@ -222,7 +222,7 @@
222
222
 
223
223
  .tide-input-select:focus-within .tide-input-border {
224
224
  --tide-input-outline-width: var(--tide-border-width-2);
225
- outline-color: var(--tide-surface-border-high);
225
+ outline-color: var(--tide-border-high);
226
226
  }
227
227
 
228
228
  .tide-input-border {
@@ -320,7 +320,7 @@
320
320
 
321
321
  .tide-input-text:focus-within .tide-input-text-field {
322
322
  --tide-input-outline-width: var(--tide-border-width-2);
323
- outline-color: var(--tide-surface-border-high);
323
+ outline-color: var(--tide-border-high);
324
324
  }
325
325
 
326
326
  .tide-input-text input {
@@ -331,6 +331,6 @@
331
331
  --tide-input-outline-width: var(--tide-border-width-1);
332
332
  outline: var(--tide-input-outline-width) solid var(--tide-border);
333
333
  outline-offset: calc(var(--tide-input-outline-width) * -1);
334
- color: var(--tide-surface-foreground);
334
+ color: var(--tide-on-surface);
335
335
  }
336
336
  </style>
@@ -311,7 +311,7 @@
311
311
 
312
312
  .tide-input-text:focus-within .tide-input-text-field {
313
313
  --tide-input-outline-width: var(--tide-border-width-2);
314
- outline-color: var(--tide-surface-border-high);
314
+ outline-color: var(--tide-border-high);
315
315
  }
316
316
 
317
317
  .tide-input-text input {
@@ -322,6 +322,6 @@
322
322
  --tide-input-outline-width: var(--tide-border-width-1);
323
323
  outline: var(--tide-input-outline-width) solid var(--tide-border);
324
324
  outline-offset: calc(var(--tide-input-outline-width) * -1);
325
- color: var(--tide-surface-foreground);
325
+ color: var(--tide-on-surface);
326
326
  }
327
327
  </style>