@thalassic/themes 22.16.1 → 22.17.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 (35) hide show
  1. package/package.json +1 -1
  2. package/themes/thalassic/components/_odometer.scss +1 -14
  3. package/themes/thalassic/components/_table.scss +29 -2
  4. package/themes/thalassic/components/_virtual-scroll.scss +11 -0
  5. package/themes/thalassic/components/autocomplete/_autocomplete-panel.scss +21 -0
  6. package/themes/thalassic/components/calendar/_agenda.scss +3 -2
  7. package/themes/thalassic/components/calendar/_calendar.scss +27 -0
  8. package/themes/thalassic/components/calendar/_compact.scss +21 -0
  9. package/themes/thalassic/components/calendar/_lines.scss +23 -0
  10. package/themes/thalassic/components/calendar/_month-view.scss +132 -6
  11. package/themes/thalassic/components/calendar/_time-grid.scss +6 -5
  12. package/themes/thalassic/components/dialog/_dialog.scss +43 -0
  13. package/themes/thalassic/components/drawer/_drawer-side.scss +65 -0
  14. package/themes/thalassic/components/drawer/_drawer.scss +16 -0
  15. package/themes/thalassic/components/index.scss +3 -0
  16. package/themes/thalassic/components/multi-select/_multi-select-panel.scss +21 -0
  17. package/themes/thalassic/components/pagination/_pagination.scss +1 -1
  18. package/themes/thalassic/components/progress/_index.scss +3 -0
  19. package/themes/thalassic/components/progress/_progress-color.scss +5 -0
  20. package/themes/thalassic/components/progress/_progress-size.scss +13 -0
  21. package/themes/thalassic/components/progress/_progress.scss +38 -0
  22. package/themes/thalassic/components/rating/_index.scss +3 -0
  23. package/themes/thalassic/components/rating/_rating-color.scss +43 -0
  24. package/themes/thalassic/components/rating/_rating-size.scss +13 -0
  25. package/themes/thalassic/components/rating/_rating.scss +144 -0
  26. package/themes/thalassic/components/select/_select-panel.scss +21 -0
  27. package/themes/thalassic/components/stepper/_index.scss +1 -0
  28. package/themes/thalassic/components/stepper/_stepper-color.scss +34 -152
  29. package/themes/thalassic/components/stepper/_stepper-label-position.scss +41 -0
  30. package/themes/thalassic/components/stepper/_stepper-orientation.scss +13 -1
  31. package/themes/thalassic/components/stepper/_stepper.scss +37 -11
  32. package/themes/thalassic/components/toast/_toast.scss +4 -3
  33. package/themes/thalassic/mixins/_index.scss +2 -0
  34. package/themes/thalassic/mixins/_pop.scss +26 -0
  35. package/themes/thalassic/mixins/_visually-hidden.scss +19 -0
@@ -23,6 +23,27 @@
23
23
  list-style: none;
24
24
 
25
25
  @include mixins.panel-open;
26
+
27
+ &--virtual {
28
+ // The virtual-scroll viewport inside is the scroll container; the panel only clips
29
+ // to its rounded corners.
30
+ overflow: hidden;
31
+
32
+ // Windowing positions every row at a fixed offset, so each row must occupy exactly
33
+ // the item size the viewport publishes — a taller custom option template is clipped
34
+ // rather than allowed to drift the rows out of place.
35
+ .tls-multi-select__option {
36
+ height: var(--tls-virtual-scroll-item-size);
37
+
38
+ box-sizing: border-box;
39
+
40
+ overflow: hidden;
41
+ }
42
+
43
+ .tls-multi-select__option-button {
44
+ height: 100%;
45
+ }
46
+ }
26
47
  }
27
48
 
28
49
  .tls-multi-select__option {
@@ -4,7 +4,7 @@
4
4
  --tls-pagination-gap: 16px;
5
5
  --tls-pagination-color: var(--color-secondary);
6
6
  --tls-pagination-radius: 4px;
7
- --tls-pagination-hover-outline: 1px solid var(--color-lines);
7
+ --tls-pagination-hover-outline: 1px solid var(--color-outline-variant);
8
8
 
9
9
  --tls-pagination-item-border-color: var(--color-outline-variant);
10
10
 
@@ -0,0 +1,3 @@
1
+ @forward 'progress';
2
+ @forward 'progress-color';
3
+ @forward 'progress-size';
@@ -0,0 +1,5 @@
1
+ @use '../../mixins' as mixins;
2
+
3
+ .tls-progress {
4
+ @include mixins.color-variants('tls-progress');
5
+ }
@@ -0,0 +1,13 @@
1
+ .tls-progress {
2
+ &.tls-progress--sm {
3
+ --tls-progress-height: 4px;
4
+ }
5
+
6
+ &.tls-progress--md {
7
+ --tls-progress-height: 8px;
8
+ }
9
+
10
+ &.tls-progress--lg {
11
+ --tls-progress-height: 12px;
12
+ }
13
+ }
@@ -0,0 +1,38 @@
1
+ @use '../../mixins' as mixins;
2
+
3
+ .tls-progress {
4
+ --tls-progress-track-color: var(--color-surface-variant);
5
+
6
+ // A track piece: the single full-width bar in continuous mode, one pill per
7
+ // step in segmented mode. Fully rounded ends at every height.
8
+ .tls-progress-segment {
9
+ height: var(--tls-progress-height);
10
+
11
+ flex: 1 1 0;
12
+
13
+ border-radius: var(--radius-xl);
14
+
15
+ background-color: var(--tls-progress-track-color);
16
+
17
+ overflow: hidden;
18
+
19
+ @include mixins.motion {
20
+ transition: flex-grow var(--motion-fast) var(--motion-ease-out);
21
+ }
22
+ }
23
+
24
+ // The filled share of a segment, clipped by the segment's rounding. Anchored
25
+ // to inline-start so the bar grows from the leading edge in both layout
26
+ // directions.
27
+ .tls-progress-fill {
28
+ height: 100%;
29
+
30
+ border-radius: inherit;
31
+
32
+ background-color: var(--tls-progress-color);
33
+
34
+ @include mixins.motion {
35
+ transition: inline-size var(--motion-fast) var(--motion-ease-out);
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,3 @@
1
+ @forward 'rating';
2
+ @forward 'rating-size';
3
+ @forward 'rating-color';
@@ -0,0 +1,43 @@
1
+ @use 'sass:map';
2
+
3
+ @use '../../../../palettes' as common-palettes;
4
+
5
+ .tls-rating {
6
+ &.tls-rating--primary {
7
+ --tls-rating-fill-color: var(--color-primary);
8
+ }
9
+
10
+ &.tls-rating--secondary {
11
+ --tls-rating-fill-color: var(--color-secondary);
12
+ }
13
+
14
+ &.tls-rating--tertiary {
15
+ --tls-rating-fill-color: var(--color-tertiary);
16
+ }
17
+
18
+ &.tls-rating--success {
19
+ --tls-rating-fill-color: var(--color-success);
20
+ }
21
+
22
+ &.tls-rating--info {
23
+ --tls-rating-fill-color: var(--color-info);
24
+ }
25
+
26
+ &.tls-rating--warning {
27
+ --tls-rating-fill-color: var(--color-warning);
28
+ }
29
+
30
+ &.tls-rating--danger {
31
+ --tls-rating-fill-color: var(--color-danger);
32
+ }
33
+
34
+ // Classic star gold, straight from the yellow palette rather than the
35
+ // `warning` semantic (whose light-mode value is a dark olive, not gold).
36
+ &.tls-rating--golden {
37
+ --tls-rating-fill-color: #{map.get(common-palettes.$yellow, 70)};
38
+
39
+ :root.tls-dark & {
40
+ --tls-rating-fill-color: #{map.get(common-palettes.$yellow, 80)};
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,13 @@
1
+ .tls-rating {
2
+ &.tls-rating--sm {
3
+ --tls-rating-star-size: 16px;
4
+ }
5
+
6
+ &.tls-rating--md {
7
+ --tls-rating-star-size: 20px;
8
+ }
9
+
10
+ &.tls-rating--lg {
11
+ --tls-rating-star-size: 24px;
12
+ }
13
+ }
@@ -0,0 +1,144 @@
1
+ @use '../../mixins' as mixins;
2
+
3
+ .tls-rating {
4
+ --tls-rating-star-size: 20px;
5
+ --tls-rating-hover-scale: 1.15;
6
+ --tls-rating-pop-scale: 1.25;
7
+
8
+ // Fallback only — the component always emits a `--<color>` modifier, and the
9
+ // default `golden` value lives in the color partial alongside the others.
10
+ --tls-rating-fill-color: var(--color-primary);
11
+ --tls-rating-empty-color: var(--color-surface-variant);
12
+ // Ghost rendering of the hover preview's delta: the fill color, mostly transparent.
13
+ --tls-rating-preview-color: color-mix(in srgb, var(--tls-rating-fill-color) 45%, transparent);
14
+
15
+ .tls-rating-star {
16
+ position: relative;
17
+
18
+ display: inline-flex;
19
+ }
20
+
21
+ .tls-rating-icons {
22
+ position: relative;
23
+
24
+ display: inline-flex;
25
+
26
+ border-radius: var(--radius-sm);
27
+
28
+ color: var(--tls-rating-empty-color);
29
+
30
+ @include mixins.motion {
31
+ transition: transform var(--motion-fast) var(--motion-ease-spring);
32
+ }
33
+ }
34
+
35
+ // The star box: a fixed square holding either the built-in icon or a
36
+ // consumer template, whose content is centered and sized to the star.
37
+ .tls-rating-icon {
38
+ width: var(--tls-rating-star-size);
39
+ height: var(--tls-rating-star-size);
40
+
41
+ display: inline-flex;
42
+ flex-shrink: 0;
43
+ align-items: center;
44
+ justify-content: center;
45
+
46
+ font-size: var(--tls-rating-star-size);
47
+ line-height: 1;
48
+
49
+ .tls-icon {
50
+ width: 100%;
51
+ height: 100%;
52
+ }
53
+ }
54
+
55
+ // The filled layer sits over the outline star, clipped to the displayed
56
+ // value's share of the box. Anchored to inline-start so the visible part is
57
+ // the leading side and the clipped part the trailing side in both layout
58
+ // directions; the inner icon keeps the star's full size so clipping narrows
59
+ // the window, not the drawing.
60
+ .tls-rating-fill {
61
+ position: absolute;
62
+ inset-block: 0;
63
+ inset-inline-start: 0;
64
+
65
+ overflow: hidden;
66
+ color: var(--tls-rating-fill-color);
67
+
68
+ &--ghost {
69
+ color: var(--tls-rating-preview-color);
70
+ }
71
+ }
72
+
73
+ // The radios are the real targets: invisible, laid over their slice of the
74
+ // star and stretched across half the surrounding gap on each side, so the row
75
+ // is one continuous hit surface with no dead zones between stars.
76
+ .tls-rating-input {
77
+ position: absolute;
78
+ inset-block: 0;
79
+ inset-inline: calc(var(--tls-rating-gap) / -2);
80
+
81
+ margin: 0;
82
+
83
+ appearance: none;
84
+
85
+ opacity: 0;
86
+
87
+ cursor: pointer;
88
+
89
+ &--start {
90
+ inset-inline-end: 50%;
91
+ }
92
+
93
+ &--end {
94
+ inset-inline-start: 50%;
95
+ }
96
+
97
+ // Tap-target expansion on the block axis only, mirroring the touch-target
98
+ // mixin's gating. The mixin's symmetric overflow cannot apply here: growing
99
+ // the inline axis would overlap the adjacent option's hit area and steal its
100
+ // edge taps, so the inline extent stays the option's own slice.
101
+ @media (pointer: coarse) {
102
+ :root:not([data-touch-targets='off']) & {
103
+ inset-block: min(
104
+ 0px,
105
+ calc((var(--tls-rating-star-size) - var(--control-touch-target)) / 2)
106
+ );
107
+ }
108
+ }
109
+ }
110
+
111
+ .tls-rating-star:has(.tls-rating-input:focus-visible) .tls-rating-icons {
112
+ @include mixins.focus-ring;
113
+ }
114
+
115
+ .tls-rating-star--pop .tls-rating-icons {
116
+ @include mixins.pop(var(--tls-rating-pop-scale));
117
+ }
118
+
119
+ // Grows the star under the pointer. The scale itself is ungated so the state
120
+ // still reads at every motion level; only the easing into it is (see the
121
+ // icons rule above).
122
+ &:not(.tls-rating--disabled):not(.tls-rating--readonly) .tls-rating-star:hover .tls-rating-icons {
123
+ transform: scale(var(--tls-rating-hover-scale));
124
+ }
125
+
126
+ // Form control
127
+ &.tls-rating--disabled {
128
+ .tls-rating-input {
129
+ cursor: not-allowed;
130
+ }
131
+
132
+ .tls-rating-icons {
133
+ filter: brightness(0.9);
134
+ }
135
+ }
136
+
137
+ &.tls-rating--readonly .tls-rating-input {
138
+ cursor: default;
139
+ }
140
+
141
+ &:not(.tls-rating--disabled).tls-rating--show-error {
142
+ --tls-rating-fill-color: var(--color-danger);
143
+ }
144
+ }
@@ -23,6 +23,27 @@
23
23
  list-style: none;
24
24
 
25
25
  @include mixins.panel-open;
26
+
27
+ &--virtual {
28
+ // The virtual-scroll viewport inside is the scroll container; the panel only clips
29
+ // to its rounded corners.
30
+ overflow: hidden;
31
+
32
+ // Windowing positions every row at a fixed offset, so each row must occupy exactly
33
+ // the item size the viewport publishes — a taller custom option template is clipped
34
+ // rather than allowed to drift the rows out of place.
35
+ .tls-select__option {
36
+ height: var(--tls-virtual-scroll-item-size);
37
+
38
+ box-sizing: border-box;
39
+
40
+ overflow: hidden;
41
+ }
42
+
43
+ .tls-select__option-button {
44
+ height: 100%;
45
+ }
46
+ }
26
47
  }
27
48
 
28
49
  .tls-select__option {
@@ -1,3 +1,4 @@
1
1
  @forward 'stepper';
2
2
  @forward 'stepper-color';
3
+ @forward 'stepper-label-position';
3
4
  @forward 'stepper-orientation';
@@ -1,3 +1,5 @@
1
+ @use '../../mixins/color-variants' as color-variants;
2
+
1
3
  .tls-stepper {
2
4
  @mixin _disabled-reset {
3
5
  --tls-stepper-label-color: var(--color-outline);
@@ -8,159 +10,39 @@
8
10
  }
9
11
 
10
12
  .tls-stepper-header {
11
- // Item
13
+ // Item — the states of one hue share a specificity level, so within each
14
+ // hue block order encodes precedence: active < completed < invalid <
15
+ // disabled, the later state overriding the earlier ones when combined.
12
16
  &__item {
13
- // Primary
14
- &.tls-stepper-header--primary {
15
- // Active
16
- &.tls-stepper-header__item--active {
17
- --tls-stepper-label-color: var(--color-primary);
18
- --tls-stepper-index-border-color: var(--color-primary);
19
- }
20
-
21
- // Completed
22
- &.tls-stepper-header__item--completed {
23
- --tls-stepper-index-on-color: var(--color-on-primary);
24
- --tls-stepper-index-background-color: var(--color-primary);
25
- --tls-stepper-index-border-color: var(--color-primary);
26
- --tls-stepper-divider-color: var(--color-primary);
27
- }
28
-
29
- // Disabled overrides color states
30
- &.tls-stepper-header__item--disabled {
31
- @include _disabled-reset;
32
- }
33
- }
34
-
35
- // Secondary
36
- &.tls-stepper-header--secondary {
37
- // Active
38
- &.tls-stepper-header__item--active {
39
- --tls-stepper-label-color: var(--color-secondary);
40
- --tls-stepper-index-border-color: var(--color-secondary);
41
- }
42
-
43
- // Completed
44
- &.tls-stepper-header__item--completed {
45
- --tls-stepper-index-on-color: var(--color-on-secondary);
46
- --tls-stepper-index-background-color: var(--color-secondary);
47
- --tls-stepper-index-border-color: var(--color-secondary);
48
- --tls-stepper-divider-color: var(--color-secondary);
49
- }
50
-
51
- // Disabled overrides color states
52
- &.tls-stepper-header__item--disabled {
53
- @include _disabled-reset;
54
- }
55
- }
56
-
57
- // Tertiary
58
- &.tls-stepper-header--tertiary {
59
- // Active
60
- &.tls-stepper-header__item--active {
61
- --tls-stepper-label-color: var(--color-tertiary);
62
- --tls-stepper-index-border-color: var(--color-tertiary);
63
- }
64
-
65
- // Completed
66
- &.tls-stepper-header__item--completed {
67
- --tls-stepper-index-on-color: var(--color-on-tertiary);
68
- --tls-stepper-index-background-color: var(--color-tertiary);
69
- --tls-stepper-index-border-color: var(--color-tertiary);
70
- --tls-stepper-divider-color: var(--color-tertiary);
71
- }
72
-
73
- // Disabled overrides color states
74
- &.tls-stepper-header__item--disabled {
75
- @include _disabled-reset;
76
- }
77
- }
78
-
79
- // Success
80
- &.tls-stepper-header--success {
81
- // Active
82
- &.tls-stepper-header__item--active {
83
- --tls-stepper-label-color: var(--color-success);
84
- --tls-stepper-index-border-color: var(--color-success);
85
- }
86
-
87
- // Completed
88
- &.tls-stepper-header__item--completed {
89
- --tls-stepper-index-on-color: var(--color-on-success);
90
- --tls-stepper-index-background-color: var(--color-success);
91
- --tls-stepper-index-border-color: var(--color-success);
92
- --tls-stepper-divider-color: var(--color-success);
93
- }
94
-
95
- // Disabled overrides color states
96
- &.tls-stepper-header__item--disabled {
97
- @include _disabled-reset;
98
- }
99
- }
100
-
101
- // Info
102
- &.tls-stepper-header--info {
103
- // Active
104
- &.tls-stepper-header__item--active {
105
- --tls-stepper-label-color: var(--color-info);
106
- --tls-stepper-index-border-color: var(--color-info);
107
- }
108
-
109
- // Completed
110
- &.tls-stepper-header__item--completed {
111
- --tls-stepper-index-on-color: var(--color-on-info);
112
- --tls-stepper-index-background-color: var(--color-info);
113
- --tls-stepper-index-border-color: var(--color-info);
114
- --tls-stepper-divider-color: var(--color-info);
115
- }
116
-
117
- // Disabled overrides color states
118
- &.tls-stepper-header__item--disabled {
119
- @include _disabled-reset;
120
- }
121
- }
122
-
123
- // Warning
124
- &.tls-stepper-header--warning {
125
- // Active
126
- &.tls-stepper-header__item--active {
127
- --tls-stepper-label-color: var(--color-warning);
128
- --tls-stepper-index-border-color: var(--color-warning);
129
- }
130
-
131
- // Completed
132
- &.tls-stepper-header__item--completed {
133
- --tls-stepper-index-on-color: var(--color-on-warning);
134
- --tls-stepper-index-background-color: var(--color-warning);
135
- --tls-stepper-index-border-color: var(--color-warning);
136
- --tls-stepper-divider-color: var(--color-warning);
137
- }
138
-
139
- // Disabled overrides color states
140
- &.tls-stepper-header__item--disabled {
141
- @include _disabled-reset;
142
- }
143
- }
144
-
145
- // Danger
146
- &.tls-stepper-header--danger {
147
- // Active
148
- &.tls-stepper-header__item--active {
149
- --tls-stepper-label-color: var(--color-danger);
150
- --tls-stepper-index-border-color: var(--color-danger);
151
- }
152
-
153
- // Completed
154
- &.tls-stepper-header__item--completed {
155
- --tls-stepper-index-on-color: var(--color-on-danger);
156
- --tls-stepper-index-background-color: var(--color-danger);
157
- --tls-stepper-index-border-color: var(--color-danger);
158
- --tls-stepper-divider-color: var(--color-danger);
159
- }
160
-
161
- // Disabled overrides color states
162
- &.tls-stepper-header__item--disabled {
163
- @include _disabled-reset;
17
+ @each $color in color-variants.$colors {
18
+ &.tls-stepper-header__item--#{$color} {
19
+ // Active
20
+ &.tls-stepper-header__item--active {
21
+ --tls-stepper-label-color: var(--color-#{$color});
22
+ --tls-stepper-index-border-color: var(--color-#{$color});
23
+ }
24
+
25
+ // Completed
26
+ &.tls-stepper-header__item--completed {
27
+ --tls-stepper-index-on-color: var(--color-on-#{$color});
28
+ --tls-stepper-index-background-color: var(--color-#{$color});
29
+ --tls-stepper-index-border-color: var(--color-#{$color});
30
+ --tls-stepper-divider-color: var(--color-#{$color});
31
+ }
32
+
33
+ // Invalid always the danger hue, regardless of the step's own
34
+ // color, so validation state reads over decoration.
35
+ &.tls-stepper-header__item--invalid {
36
+ --tls-stepper-label-color: var(--color-danger);
37
+ --tls-stepper-index-on-color: var(--color-danger);
38
+ --tls-stepper-index-background-color: var(--color-surface);
39
+ --tls-stepper-index-border-color: var(--color-danger);
40
+ }
41
+
42
+ // Disabled
43
+ &.tls-stepper-header__item--disabled {
44
+ @include _disabled-reset;
45
+ }
164
46
  }
165
47
  }
166
48
  }
@@ -0,0 +1,41 @@
1
+ .tls-stepper {
2
+ // Bottom labels — a horizontal-only layout: every step takes an equal
3
+ // column with its index centered and text underneath, and each connector
4
+ // runs from a step's index to the next column's, so the rail reads
5
+ // symmetrically edge to edge. A vertical stepper keeps the end placement.
6
+ &.tls-stepper--horizontal.tls-stepper--label-bottom {
7
+ .tls-stepper-header {
8
+ &__item {
9
+ width: auto;
10
+
11
+ flex: 1 1 0;
12
+
13
+ &:last-child {
14
+ width: auto;
15
+
16
+ flex: 1 1 0;
17
+ }
18
+
19
+ .tls-stepper-header-button {
20
+ width: 100%;
21
+
22
+ align-items: center;
23
+
24
+ text-align: center;
25
+ }
26
+ }
27
+
28
+ &__divider {
29
+ // Runs from this column's index to the next one's: the inline insets
30
+ // resolve against the item's width, and the columns are equal, so
31
+ // half a width beyond the box lands exactly on the neighbouring
32
+ // column's center. The index radius plus a small gap keeps the run
33
+ // clear of both circles.
34
+ inset-inline-start: calc(50% + var(--tls-stepper-index-size) / 2 + var(--spacing-1));
35
+ inset-inline-end: calc(-50% + var(--tls-stepper-index-size) / 2 + var(--spacing-1));
36
+
37
+ width: auto;
38
+ }
39
+ }
40
+ }
41
+ }
@@ -5,8 +5,13 @@
5
5
  &__item {
6
6
  width: 100%;
7
7
 
8
+ // The last step needs no room for a trailing divider: it keeps its
9
+ // natural width, and never shrinks below it — otherwise the flexbox
10
+ // would squeeze it to min-content and wrap its label.
8
11
  &:last-child {
9
12
  width: auto;
13
+
14
+ flex-shrink: 0;
10
15
  }
11
16
  }
12
17
 
@@ -19,11 +24,13 @@
19
24
  }
20
25
  }
21
26
 
22
- // Vertical
27
+ // Vertical — header and content sit side by side, overriding the base
28
+ // column layout that stacks a horizontal header above the content.
23
29
  &.tls-stepper--vertical {
24
30
  height: 100%;
25
31
 
26
32
  display: flex;
33
+ flex-direction: row;
27
34
 
28
35
  .tls-stepper-header {
29
36
  flex-direction: column;
@@ -31,8 +38,13 @@
31
38
  &__item {
32
39
  height: 100%;
33
40
 
41
+ // Keeps a visible run of divider between step buttons when the
42
+ // container does not stretch the header.
43
+ min-height: 64px;
44
+
34
45
  &:last-child {
35
46
  height: auto;
47
+ min-height: 0;
36
48
  }
37
49
 
38
50
  .tls-stepper-header-button {