@vialiq/flux-ui 0.20.0 → 0.21.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.
package/README.md CHANGED
@@ -380,6 +380,28 @@ Works with any JavaScript framework:
380
380
  - ✅ Focus states built-in
381
381
  - ✅ Semantic HTML patterns
382
382
  - ✅ Reduced motion support ready
383
+ - ✅ Responsive `rem` scaling based on root font size
384
+
385
+ ### Responsive Typography & Rem Scaling
386
+ Flux UI strictly uses `rem` units for typography and spacing to ensure accessibility. By default, it assumes a standard browser root font size of `16px`.
387
+
388
+ If your application uses a custom root font size (such as the `62.5%` or `10px` hack), you must configure Flux UI to scale its internal calculations accordingly:
389
+
390
+ ```scss
391
+ // In your application's main SCSS file:
392
+ @use '@vialiq/flux-ui/styles' with (
393
+ $vi-rem-base: 10px
394
+ );
395
+ ```
396
+ This ensures that a component designed to be `16px` tall will correctly output `1.6rem`, rendering exactly 16 pixels at runtime against your custom 10px root.
397
+
398
+ ### CSS Unit Guidelines
399
+ To maintain a robust, scalable, and accessible UI, Flux UI strictly adheres to the following unit rules:
400
+
401
+ - **`rem`**: Used for **Typography**, **Spacing** (margin, padding, gap), and **Interactive Form Control Sizing** (button heights, input widths, etc.). This guarantees that everything defining the core layout grid and text hierarchy scales fluidly when a user changes their browser root font size for accessibility.
402
+ - **`px`**: Reserved exclusively for rigid geometries that must never scale or blur. Used for **Borders** (`1px solid`), **Shadows** (offsets and blurs), small **Optical Adjustments** (e.g. `2px` focus outline offset), and **Visually Hidden Hacks** (e.g. `1px` clipping for screen readers).
403
+ - **`dvh` / `dvw`** (with `vh` / `vw` fallback): Used for **Viewport-Relative Layouts**, such as full-screen modal overlays, drawer max-heights, or sticky banners that must span the entire screen regardless of the parent container size. Dynamic viewport units correctly account for mobile browser UI (like address bars) expanding and contracting.
404
+ - **`%`**: Used for **Container-Relative Fluidity**, such as a button being `width: 100%` of its parent column, or grid layouts.
383
405
 
384
406
  ## Contributing
385
407
 
@@ -8,8 +8,8 @@ $accordion-border-radius: var(--vi-accordion-border-radius, tokens.$border-radiu
8
8
  $accordion-gap: var(--vi-accordion-gap, 0px);
9
9
  $accordion-animation-duration: var(--vi-accordion-animation-duration, 200ms);
10
10
 
11
- $accordion-item-header-padding: var(--vi-accordion-item-header-padding, 14px 16px);
12
- $accordion-item-body-padding: var(--vi-accordion-item-body-padding, 0 16px 16px);
11
+ $accordion-item-header-padding: var(--vi-accordion-item-header-padding, #{tokens.$spacing-sm} #{tokens.$spacing-md});
12
+ $accordion-item-body-padding: var(--vi-accordion-item-body-padding, 0 #{tokens.$spacing-md} #{tokens.$spacing-md});
13
13
  $accordion-item-header-bg: var(--vi-accordion-item-header-bg, transparent);
14
14
  $accordion-item-header-bg-hover: var(--vi-accordion-item-header-bg-hover, tokens.$layer-hover-01);
15
15
  $accordion-item-header-bg-open: var(--vi-accordion-item-header-bg-open, transparent);
@@ -43,8 +43,8 @@ $accordion-item-chevron-color: var(--vi-accordion-item-chevron-color, tokens.$te
43
43
  padding: $accordion-item-header-padding;
44
44
  background-color: $accordion-item-header-bg;
45
45
  color: $accordion-item-label-color;
46
- font-family: tokens.$font-family-base;
47
- font-size: var(--vi-accordion-item-header-font-size, tokens.$font-size-base);
46
+ font-family: var(--vi-accordion-font-family, #{tokens.$font-family-base});
47
+ font-size: var(--vi-accordion-item-header-font-size, #{tokens.$font-size-base});
48
48
  font-weight: $accordion-item-label-font-weight;
49
49
  text-align: left;
50
50
  border: none;
@@ -91,8 +91,8 @@ $accordion-item-chevron-color: var(--vi-accordion-item-chevron-color, tokens.$te
91
91
  margin-inline-start: tokens.$spacing-xs;
92
92
 
93
93
  svg {
94
- width: 16px;
95
- height: 16px;
94
+ width: #{tokens.$spacing-md};
95
+ height: #{tokens.$spacing-md};
96
96
  fill: none;
97
97
  stroke: currentColor;
98
98
  stroke-width: 2;
@@ -112,9 +112,9 @@ $accordion-item-chevron-color: var(--vi-accordion-item-chevron-color, tokens.$te
112
112
 
113
113
  .accordion-panel-inner {
114
114
  padding: $accordion-item-body-padding;
115
- font-family: tokens.$font-family-base;
116
- font-size: tokens.$font-size-sm;
117
- color: tokens.$text-secondary;
115
+ font-family: var(--vi-accordion-font-family, #{tokens.$font-family-base});
116
+ font-size: #{tokens.$font-size-sm};
117
+ color: #{tokens.$text-secondary};
118
118
  box-sizing: border-box;
119
119
  }
120
120
 
@@ -168,8 +168,8 @@ $accordion-item-chevron-color: var(--vi-accordion-item-chevron-color, tokens.$te
168
168
 
169
169
  .accordion--sm,
170
170
  .accordion-item--sm {
171
- --vi-accordion-item-header-padding: 10px 12px;
172
- --vi-accordion-item-body-padding: 0 12px 12px;
171
+ --vi-accordion-item-header-padding: #{tokens.$spacing-xs} #{tokens.$spacing-sm};
172
+ --vi-accordion-item-body-padding: 0 #{tokens.$spacing-sm} #{tokens.$spacing-sm};
173
173
  --vi-accordion-item-header-font-size: #{tokens.$font-size-sm};
174
174
  }
175
175
 
@@ -182,8 +182,8 @@ $accordion-item-chevron-color: var(--vi-accordion-item-chevron-color, tokens.$te
182
182
 
183
183
  .accordion--lg,
184
184
  .accordion-item--lg {
185
- --vi-accordion-item-header-padding: 18px 20px;
186
- --vi-accordion-item-body-padding: 0 20px 20px;
185
+ --vi-accordion-item-header-padding: #{tokens.$spacing-lg} #{tokens.$spacing-xl};
186
+ --vi-accordion-item-body-padding: 0 #{tokens.$spacing-xl} #{tokens.$spacing-xl};
187
187
  --vi-accordion-item-header-font-size: #{tokens.$font-size-lg};
188
188
  }
189
189
 
@@ -15,15 +15,15 @@
15
15
  box-sizing: border-box;
16
16
  width: 100%;
17
17
 
18
- border-radius: var(--vi-alert-border-radius, 6px);
19
- padding: var(--vi-alert-padding, 12px 16px);
20
- gap: var(--vi-alert-gap, 12px);
18
+ border-radius: var(--vi-alert-border-radius, #{tokens.$border-radius-lg});
19
+ padding: var(--vi-alert-padding, #{tokens.$spacing-xs} #{tokens.$spacing-md});
20
+ gap: var(--vi-alert-gap, #{tokens.$spacing-sm});
21
21
  border-width: var(--vi-alert-border-width, 1px);
22
22
  border-style: solid;
23
23
 
24
- font-family: tokens.$font-family-base;
25
- font-size: tokens.$font-size-sm;
26
- line-height: tokens.$line-height-normal;
24
+ font-family: var(--vi-alert-font-family, #{tokens.$font-family-base});
25
+ font-size: #{tokens.$font-size-sm};
26
+ line-height: #{tokens.$line-height-normal};
27
27
  }
28
28
 
29
29
  .alert-icon {
@@ -45,7 +45,7 @@
45
45
 
46
46
  .alert-title {
47
47
  font-weight: tokens.$font-weight-semibold;
48
- margin-bottom: 4px;
48
+ margin-bottom: #{tokens.$spacing-unit};
49
49
  display: block;
50
50
  }
51
51
 
@@ -25,7 +25,7 @@
25
25
  --vi-animation-easing-exit: cubic-bezier(0.4, 0, 1, 1);
26
26
  --vi-animation-easing-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
27
27
 
28
- --vi-animation-expand-max-height: 100vh;
28
+ --vi-animation-expand-max-height: 100dvh;
29
29
  --vi-animation-expand-max-width: 100vw;
30
30
  }
31
31
 
@@ -186,11 +186,11 @@
186
186
  // Expand & Collapse Keyframes
187
187
  @keyframes vi-expand-vertical {
188
188
  from { max-height: 0; opacity: 0; }
189
- to { max-height: var(--vi-animation-expand-max-height, 100vh); opacity: 1; }
189
+ to { max-height: var(--vi-animation-expand-max-height, 100dvh); opacity: 1; }
190
190
  }
191
191
 
192
192
  @keyframes vi-collapse-vertical {
193
- from { max-height: var(--vi-animation-expand-max-height, 100vh); opacity: 1; }
193
+ from { max-height: var(--vi-animation-expand-max-height, 100dvh); opacity: 1; }
194
194
  to { max-height: 0; opacity: 0; }
195
195
  }
196
196
 
@@ -16,19 +16,21 @@
16
16
  white-space: nowrap;
17
17
  box-sizing: border-box;
18
18
 
19
- font-size: var(--vi-badge-font-size, 11px);
19
+ // 20px = standard badge height (not on the spacing scale); kept explicit
20
+ height: var(--vi-badge-height, 20px);
21
+ font-size: var(--vi-badge-font-size, #{tokens.$font-size-xs});
20
22
  font-weight: var(--vi-badge-font-weight, #{tokens.$font-weight-semibold});
21
- padding: var(--vi-badge-padding, 2px 8px);
22
- border-radius: var(--vi-badge-border-radius, 9999px);
23
- gap: var(--vi-badge-gap, 4px);
23
+ padding: var(--vi-badge-padding, 0 #{tokens.$spacing-xs});
24
+ border-radius: var(--vi-badge-border-radius, #{tokens.$border-radius-full});
25
+ gap: var(--vi-badge-gap, #{tokens.$spacing-unit});
24
26
 
25
27
  border: #{tokens.$border-width-thin} solid transparent;
26
28
  }
27
29
 
28
30
  .dot {
29
31
  display: inline-block;
30
- width: var(--vi-badge-dot-size, 8px);
31
- height: var(--vi-badge-dot-size, 8px);
32
+ width: var(--vi-badge-dot-size, #{tokens.$spacing-xs});
33
+ height: var(--vi-badge-dot-size, #{tokens.$spacing-xs});
32
34
  border-radius: 50%;
33
35
  background-color: currentColor;
34
36
  flex-shrink: 0;
@@ -7,12 +7,13 @@
7
7
  */
8
8
 
9
9
  @use '../styles/variables' as tokens;
10
+ @use '../styles/functions' as func;
10
11
 
11
12
  @layer components {
12
13
  .checkbox-wrapper {
13
14
  display: inline-flex;
14
15
  align-items: flex-start;
15
- gap: var(--vi-checkbox-label-gap, 8px);
16
+ gap: var(--vi-checkbox-label-gap, #{tokens.$spacing-xs});
16
17
  cursor: pointer;
17
18
  font-family: #{tokens.$font-family-base};
18
19
  font-size: var(--vi-checkbox-label-font-size, #{tokens.$font-size-base});
@@ -41,10 +42,10 @@
41
42
  display: inline-flex;
42
43
  align-items: center;
43
44
  justify-content: center;
44
- width: var(--vi-checkbox-size, 18px);
45
- height: var(--vi-checkbox-size, 18px);
45
+ width: var(--vi-checkbox-size, #{tokens.$spacing-md});
46
+ height: var(--vi-checkbox-size, #{tokens.$spacing-md});
46
47
  border: #{tokens.$border-width-base} solid var(--vi-checkbox-border-color, #{tokens.$outline});
47
- border-radius: var(--vi-checkbox-border-radius, 3px);
48
+ border-radius: var(--vi-checkbox-border-radius, #{func.to-rem(4px)});
48
49
  background-color: var(--vi-checkbox-background-color, #{tokens.$color-background});
49
50
  transition: border-color 150ms ease, background-color 150ms ease, box-shadow 150ms ease;
50
51
  flex-shrink: 0;
@@ -12,13 +12,13 @@
12
12
  border-style: solid;
13
13
 
14
14
  // Tokens mapped directly from docs
15
- height: var(--vi-chip-height, var(--vi-chip-height-md, 32px));
15
+ height: var(--vi-chip-height, var(--vi-chip-height-md, #{tokens.$spacing-xl}));
16
16
  padding: var(--vi-chip-padding, 0 10px);
17
- border-radius: var(--vi-chip-border-radius, 999px);
17
+ border-radius: var(--vi-chip-border-radius, #{tokens.$border-radius-full});
18
18
  border-width: var(--vi-chip-border-width, 1px);
19
19
  gap: var(--vi-chip-gap, 6px);
20
- font-size: var(--vi-chip-font-size, var(--vi-font-size-sm));
21
- font-weight: var(--vi-chip-font-weight, var(--vi-font-weight-medium));
20
+ font-size: var(--vi-chip-font-size, #{tokens.$font-size-sm});
21
+ font-weight: var(--vi-chip-font-weight, #{tokens.$font-weight-medium});
22
22
  transition: all var(--vi-chip-transition, 100ms ease);
23
23
 
24
24
  // Color tokens to be overridden by vi-chip variant
@@ -22,3 +22,4 @@
22
22
  @forward 'tabs';
23
23
  @forward 'tab';
24
24
  @forward 'tab-panel';
25
+ @forward 'spin';
@@ -14,8 +14,8 @@
14
14
  --vi-label-required-color: var(--vi-color-error, #{tokens.$color-error});
15
15
  // --vi-label-optional-color: var(--vi-text-helper)
16
16
  --vi-label-optional-color: var(--vi-text-helper, #{tokens.$text-helper});
17
- // --vi-label-gap: 4px
18
- --vi-label-gap: 4px;
17
+ // --vi-label-gap: $spacing-unit (4px)
18
+ --vi-label-gap: #{tokens.$spacing-unit};
19
19
  }
20
20
 
21
21
  .vi-label {
@@ -25,7 +25,7 @@
25
25
  font-size: var(--vi-label-font-size);
26
26
  font-weight: var(--vi-label-font-weight);
27
27
  color: var(--vi-label-color);
28
- line-height: 1.5;
28
+ line-height: #{tokens.$line-height-normal};
29
29
  margin: 0;
30
30
 
31
31
  &.size-sm {
@@ -25,14 +25,15 @@
25
25
  margin: auto;
26
26
  width: 100%;
27
27
  max-width: tokens.$modal-max-width-md;
28
- max-height: 90vh; // Fallback max-height
28
+ max-height: 90vh;
29
+ max-height: 90dvh;
29
30
 
30
31
  z-index: tokens.$modal-z-index;
31
32
 
32
- font-family: tokens.$font-family-base;
33
- font-size: tokens.$font-size-base;
34
- line-height: tokens.$line-height-normal;
35
- color: tokens.$text-primary;
33
+ font-family: var(--vi-modal-font-family, #{tokens.$font-family-base});
34
+ font-size: var(--vi-modal-font-size, #{tokens.$font-size-base});
35
+ line-height: var(--vi-modal-line-height, #{tokens.$line-height-normal});
36
+ color: #{tokens.$text-primary};
36
37
 
37
38
  &[open] {
38
39
  display: flex;
@@ -230,6 +231,7 @@
230
231
  width: 100vw !important;
231
232
  width: 100dvw !important;
232
233
  max-height: 100vh !important;
234
+ max-height: 100dvh !important;
233
235
  height: 100vh !important;
234
236
  height: 100dvh !important;
235
237
  border-radius: 0 !important;
@@ -34,7 +34,7 @@
34
34
 
35
35
  .radio-group-items {
36
36
  display: flex;
37
- gap: var(--vi-radio-group-gap, 8px);
37
+ gap: var(--vi-radio-group-gap, #{tokens.$spacing-xs});
38
38
 
39
39
  &[orientation="vertical"] {
40
40
  flex-direction: column;
@@ -76,7 +76,7 @@
76
76
  .radio-wrapper {
77
77
  display: inline-flex;
78
78
  align-items: center;
79
- gap: var(--vi-radio-label-gap, 8px);
79
+ gap: var(--vi-radio-label-gap, #{tokens.$spacing-xs});
80
80
  cursor: pointer;
81
81
  font-family: #{tokens.$font-family-base};
82
82
  font-size: var(--vi-radio-label-font-size, #{tokens.$font-size-base});
@@ -104,8 +104,8 @@
104
104
  display: inline-flex;
105
105
  align-items: center;
106
106
  justify-content: center;
107
- width: var(--vi-radio-size, 18px);
108
- height: var(--vi-radio-size, 18px);
107
+ width: var(--vi-radio-size, #{tokens.$spacing-md});
108
+ height: var(--vi-radio-size, #{tokens.$spacing-md});
109
109
  border: #{tokens.$border-width-base} solid var(--vi-radio-border-color, #{tokens.$outline});
110
110
  border-radius: 50%;
111
111
  background-color: var(--vi-radio-background-color, #{tokens.$color-background});
@@ -115,8 +115,9 @@
115
115
 
116
116
  .radio-dot {
117
117
  box-sizing: border-box;
118
- width: var(--vi-radio-dot-size, 8px);
119
- height: var(--vi-radio-dot-size, 8px);
118
+ // 8px dot is half of the 16px ($spacing-md) circle; this ratio is intentional
119
+ width: var(--vi-radio-dot-size, calc(#{tokens.$spacing-md} / 2));
120
+ height: var(--vi-radio-dot-size, calc(#{tokens.$spacing-md} / 2));
120
121
  border-radius: 50%;
121
122
  background-color: var(--vi-radio-dot-color, #{tokens.$color-primary});
122
123
  transform: scale(0);
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  @use '../styles/variables' as tokens;
9
+ @use '../styles/functions' as func;
9
10
 
10
11
  @layer components {
11
12
  // -------------------------------------------------------------------------
@@ -38,14 +39,14 @@
38
39
  justify-content: space-between;
39
40
  box-sizing: border-box;
40
41
  width: 100%;
41
- min-height: var(--vi-select-sizing-min-height, 40px);
42
- padding: var(--vi-select-spacing-padding-block, #{tokens.$spacing-xs})
43
- var(--vi-select-spacing-padding-inline, #{tokens.$spacing-sm});
42
+ min-height: var(--vi-select-sizing-min-height, #{tokens.$spacing-xl});
43
+ padding: var(--vi-select-spacing-padding-block, #{tokens.$spacing-unit})
44
+ var(--vi-select-spacing-padding-inline, #{func.to-rem(11px)});
44
45
  background-color: var(--vi-select-background-color, #{tokens.$color-background});
45
46
  border: var(--vi-select-border-width, #{tokens.$border-width-thin}) solid var(--vi-select-border-color, #{tokens.$border-03});
46
- border-radius: var(--vi-select-shape-border-radius, #{tokens.$border-radius-lg});
47
+ border-radius: var(--vi-select-shape-border-radius, #{func.to-rem(6px)});
47
48
  font-family: inherit;
48
- font-size: var(--vi-font-size-base, #{tokens.$font-size-base});
49
+ font-size: var(--vi-font-size-base, #{func.to-rem(14px)});
49
50
  color: var(--vi-select-text-color, #{tokens.$color-foreground});
50
51
  transition: border-color 150ms ease, box-shadow 150ms ease;
51
52
  cursor: pointer;
@@ -1,4 +1,5 @@
1
1
  @use '../styles/variables' as tokens;
2
+ @use '../styles/functions' as func;
2
3
 
3
4
  @layer components {
4
5
  // ── Wrapper ──────────────────────────────────────────────────────────────────
@@ -10,7 +11,7 @@
10
11
  .switch-wrapper {
11
12
  display: inline-flex;
12
13
  align-items: flex-start;
13
- gap: var(--vi-switch-label-gap, 8px);
14
+ gap: var(--vi-switch-label-gap, #{tokens.$spacing-xs});
14
15
  cursor: pointer;
15
16
  font-family: #{tokens.$font-family-base};
16
17
  font-size: var(--vi-switch-label-font-size, #{tokens.$font-size-base});
@@ -52,15 +53,15 @@
52
53
  .switch-track {
53
54
  box-sizing: border-box;
54
55
  position: relative;
55
- width: var(--vi-switch-track-width, 44px);
56
- height: var(--vi-switch-track-height, 24px);
56
+ width: var(--vi-switch-track-width, func.to-rem(44px));
57
+ height: var(--vi-switch-track-height, func.to-rem(22px));
57
58
  background-color: var(--vi-switch-track-color-off, #{tokens.$border-03});
58
- border-radius: var(--vi-border-radius-full, 9999px);
59
+ border-radius: var(--vi-border-radius-full, #{tokens.$border-radius-full});
59
60
  transition: background-color var(--vi-switch-transition-duration, 150ms) ease;
60
61
  flex-shrink: 0;
61
62
  // Align track centre with first-line cap-height
62
63
  margin-top: calc(
63
- (1em * #{tokens.$line-height-normal} - var(--vi-switch-track-height, 24px)) / 2
64
+ (1em * #{tokens.$line-height-normal} - var(--vi-switch-track-height, func.to-rem(24px))) / 2
64
65
  );
65
66
  }
66
67
 
@@ -69,10 +70,10 @@
69
70
  .switch-thumb {
70
71
  position: absolute;
71
72
  top: 50%;
72
- left: var(--vi-switch-thumb-offset, 2px);
73
+ left: var(--vi-switch-thumb-offset, func.to-rem(2px));
73
74
  transform: translateY(-50%);
74
- width: var(--vi-switch-thumb-size, 18px);
75
- height: var(--vi-switch-thumb-size, 18px);
75
+ width: var(--vi-switch-thumb-size, func.to-rem(18px));
76
+ height: var(--vi-switch-thumb-size, func.to-rem(18px));
76
77
  background-color: var(--vi-switch-thumb-color, #{tokens.$text-primary-inverse});
77
78
  border-radius: 50%;
78
79
  box-shadow: var(--vi-switch-thumb-shadow, 0 1px 3px rgba(0, 0, 0, 0.2));
@@ -86,7 +87,7 @@
86
87
 
87
88
  .switch-thumb {
88
89
  left: calc(
89
- 100% - var(--vi-switch-thumb-size, 18px) - var(--vi-switch-thumb-offset, 2px)
90
+ 100% - var(--vi-switch-thumb-size, func.to-rem(18px)) - var(--vi-switch-thumb-offset, func.to-rem(2px))
90
91
  );
91
92
  }
92
93
  }
@@ -107,11 +108,11 @@
107
108
  opacity: var(--vi-switch-disabled-opacity, 0.5);
108
109
 
109
110
  .switch-track {
110
- background-color: #{tokens.$border-03};
111
+ background-color: var(--vi-switch-track-color-disabled, #{tokens.$border-03});
111
112
  }
112
113
 
113
114
  .switch-input:checked ~ .switch-track {
114
- background-color: #{tokens.$text-disabled};
115
+ background-color: var(--vi-switch-track-color-on-disabled, #{tokens.$text-disabled});
115
116
  }
116
117
  }
117
118
 
@@ -1,4 +1,5 @@
1
1
  @use '@vialiq/flux-ui/styles/variables' as tokens;
2
+ @use '../styles/functions' as func;
2
3
 
3
4
  @layer components {
4
5
 
@@ -12,7 +13,7 @@
12
13
  &:focus-visible {
13
14
  outline: 2px solid var(--vi-tabs-indicator-color, #{tokens.$color-primary});
14
15
  outline-offset: 2px;
15
- border-radius: 2px;
16
+ border-radius: #{func.to-rem(2px)};
16
17
  }
17
18
  }
18
19
 
@@ -1,4 +1,5 @@
1
1
  @use '@vialiq/flux-ui/styles/variables' as tokens;
2
+ @use '../styles/functions' as func;
2
3
 
3
4
  @layer components {
4
5
 
@@ -22,11 +23,11 @@
22
23
  display: inline-flex;
23
24
  align-items: center;
24
25
  justify-content: center;
25
- gap: var(--vi-tab-icon-gap, 6px);
26
+ gap: var(--vi-tab-icon-gap, #{tokens.$spacing-xs});
26
27
  padding: var(--vi-tab-padding, 0 20px);
27
28
  min-width: var(--vi-tab-min-width, 90px);
28
29
  max-width: var(--vi-tab-max-width, 240px);
29
- min-height: var(--vi-tab-height, 44px);
30
+ min-height: var(--vi-tab-height, 40px);
30
31
  width: 100%;
31
32
  height: 100%;
32
33
  position: relative;
@@ -40,7 +41,7 @@
40
41
 
41
42
  // Typography — clear nav-link feel, not body text
42
43
  font-family: inherit;
43
- font-size: var(--vi-tab-font-size, 13.5px);
44
+ font-size: var(--vi-tab-font-size, #{tokens.$font-size-base});
44
45
  font-weight: var(--vi-tab-font-weight, 500);
45
46
  letter-spacing: 0.015em;
46
47
  color: var(--vi-tab-color, #{tokens.$text-secondary});
@@ -55,7 +56,7 @@
55
56
  content: '';
56
57
  position: absolute;
57
58
  inset: 4px;
58
- border-radius: 8px;
59
+ border-radius: #{func.to-rem(8px)};
59
60
  background: currentColor;
60
61
  opacity: 0;
61
62
  transform: scale(0.85);
@@ -114,7 +115,7 @@
114
115
  display: inline-flex;
115
116
  align-items: center;
116
117
  flex-shrink: 0;
117
- font-size: var(--vi-tab-icon-size, 15px);
118
+ font-size: var(--vi-tab-icon-size, #{func.to-rem(15px)});
118
119
  opacity: 0.6;
119
120
  position: relative;
120
121
  z-index: 1;
@@ -147,8 +148,8 @@
147
148
  min-width: var(--vi-tab-close-size, 18px);
148
149
  height: var(--vi-tab-close-size, 18px);
149
150
  padding: var(--vi-tab-badge-padding, 0 5px);
150
- border-radius: 9px;
151
- font-size: 10px;
151
+ border-radius: #{func.to-rem(9px)};
152
+ font-size: #{func.to-rem(10px)};
152
153
  font-weight: 700;
153
154
  line-height: 1;
154
155
  letter-spacing: 0;
@@ -1,4 +1,5 @@
1
1
  @use '@vialiq/flux-ui/styles/variables' as tokens;
2
+ @use '../styles/functions' as func;
2
3
 
3
4
  @layer components {
4
5
 
@@ -102,7 +103,7 @@
102
103
  }
103
104
 
104
105
  &:focus-visible {
105
- border-radius: 4px; // Square focus ring for accessibility
106
+ border-radius: #{func.to-rem(4px)}; // Square focus ring for accessibility
106
107
  outline: 2px solid var(--vi-tabs-focus-ring, #{tokens.$color-primary});
107
108
  outline-offset: 2px;
108
109
  }
@@ -163,7 +164,7 @@
163
164
  height: var(--vi-tabs-indicator-thickness, 2px);
164
165
  width: 0;
165
166
  background: var(--vi-tabs-indicator-color, #{tokens.$color-primary});
166
- border-radius: 2px 2px 0 0;
167
+ border-radius: #{func.to-rem(2px)} #{func.to-rem(2px)} 0 0;
167
168
  opacity: 0;
168
169
  pointer-events: none;
169
170
  z-index: 2;
@@ -201,7 +202,7 @@
201
202
  bottom: -1px;
202
203
  height: 2px;
203
204
  background: var(--vi-tabs-primary-color, #{tokens.$color-primary});
204
- border-radius: 2px 2px 0 0;
205
+ border-radius: #{func.to-rem(2px)} #{func.to-rem(2px)} 0 0;
205
206
  box-shadow: 0 0 0 0 transparent; // no glow on line variant — keep clean
206
207
  }
207
208
  }
@@ -218,7 +219,7 @@
218
219
  .vi-tabs__tablist {
219
220
  background: var(--vi-tabs-pill-bg, #{tokens.$color-grey-100});
220
221
  border: 1px solid var(--vi-tabs-border-color, #{tokens.$color-border});
221
- border-radius: 10px;
222
+ border-radius: #{func.to-rem(10px)};
222
223
  padding: var(--vi-tabs-spacing-xs, 4px);
223
224
  gap: var(--vi-tabs-gap-xs, 2px);
224
225
  // Inset shadow creates a "recessed tray" feel
@@ -229,7 +230,7 @@
229
230
  .vi-tabs__cursor {
230
231
  display: block;
231
232
  inset: 4px auto; // matches tablist padding
232
- border-radius: 7px;
233
+ border-radius: #{func.to-rem(7px)};
233
234
  background: var(--vi-tabs-surface-primary, #{tokens.$layer-01});
234
235
  // Multi-layer shadow for floating card feel
235
236
  box-shadow:
@@ -261,7 +262,7 @@
261
262
  bottom: -1px;
262
263
  height: 2px;
263
264
  background: var(--vi-tabs-primary-color, #{tokens.$color-primary});
264
- border-radius: 2px 2px 0 0;
265
+ border-radius: #{func.to-rem(2px)} #{func.to-rem(2px)} 0 0;
265
266
  }
266
267
  }
267
268
 
@@ -286,7 +287,7 @@
286
287
  .vi-tabs__cursor {
287
288
  $surface-color: var(--vi-tabs-surface-primary, #{tokens.$layer-01});
288
289
  display: block;
289
- border-radius: 8px 8px 0 0;
290
+ border-radius: #{func.to-rem(8px)} #{func.to-rem(8px)} 0 0;
290
291
  background: $surface-color;
291
292
  border: 1px solid var(--vi-tabs-border-color, #{tokens.$color-border});
292
293
  border-bottom-color: $surface-color; // Merges with content below
@@ -306,7 +307,7 @@
306
307
 
307
308
  .vi-tabs--enclosed {
308
309
  border: 1px solid var(--vi-tabs-border-color, #{tokens.$color-border});
309
- border-radius: 10px;
310
+ border-radius: #{func.to-rem(10px)};
310
311
  overflow: clip; // Enclosed: clip cursor inside rounded border box
311
312
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
312
313
 
@@ -367,7 +368,7 @@
367
368
  left: 4px !important;
368
369
  right: 4px;
369
370
  width: calc(100% - 8px) !important; // Override JS width — fills sidebar
370
- border-radius: 8px;
371
+ border-radius: #{func.to-rem(8px)};
371
372
  background: var(--vi-tabs-surface-primary, #{tokens.$layer-01});
372
373
  box-shadow:
373
374
  0 1px 3px rgba(0, 0, 0, 0.08),
@@ -382,7 +383,7 @@
382
383
  right: 0;
383
384
  width: 3px !important;
384
385
  height: 0;
385
- border-radius: 3px 0 0 3px;
386
+ border-radius: #{func.to-rem(3px)} 0 0 #{func.to-rem(3px)};
386
387
  background: var(--vi-tabs-primary-color, #{tokens.$color-primary});
387
388
  box-shadow: 0 0 6px color-mix(in srgb, #{tokens.$color-primary} 40%, transparent);
388
389
  }
@@ -395,7 +396,7 @@
395
396
 
396
397
  &.vi-tabs--line ::slotted(vi-tab[active]) {
397
398
  background: var(--vi-tabs-surface-primary, #{tokens.$layer-01});
398
- border-radius: 8px;
399
+ border-radius: #{func.to-rem(8px)};
399
400
  }
400
401
  }
401
402
 
@@ -482,10 +483,10 @@
482
483
  background: transparent;
483
484
  cursor: pointer;
484
485
  font-family: inherit;
485
- font-size: 13px;
486
+ font-size: #{func.to-rem(13px)};
486
487
  font-weight: 500;
487
488
  color: var(--vi-tabs-text-secondary, #{tokens.$text-secondary});
488
- border-radius: 6px 6px 0 0;
489
+ border-radius: #{func.to-rem(6px)} #{func.to-rem(6px)} 0 0;
489
490
  transition: color 150ms ease, background-color 150ms ease;
490
491
 
491
492
  &:hover {
@@ -516,7 +517,7 @@
516
517
  min-width: 180px;
517
518
  background: var(--vi-tabs-surface-primary, #{tokens.$layer-01});
518
519
  border: 1px solid var(--vi-tabs-border-color, #{tokens.$color-border});
519
- border-radius: 8px;
520
+ border-radius: #{func.to-rem(8px)};
520
521
  box-shadow:
521
522
  0 4px 6px -1px rgba(0, 0, 0, 0.10),
522
523
  0 2px 4px -1px rgba(0, 0, 0, 0.06),
@@ -538,10 +539,10 @@
538
539
  width: 100%;
539
540
  padding: var(--vi-tabs-spacing-md-lg, 8px 12px);
540
541
  border: none;
541
- border-radius: 6px;
542
+ border-radius: #{func.to-rem(6px)};
542
543
  background: transparent;
543
544
  font-family: inherit;
544
- font-size: 13.5px;
545
+ font-size: #{func.to-rem(13.5px)};
545
546
  font-weight: 500;
546
547
  color: var(--vi-tabs-text-secondary, #{tokens.$text-secondary});
547
548
  cursor: pointer;