@thalassic/themes 0.17.1 → 0.19.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thalassic/themes",
3
- "version": "0.17.1",
3
+ "version": "0.19.0",
4
4
  "license": "MIT",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
@@ -0,0 +1,67 @@
1
+ @use '../mixins' as mixins;
2
+
3
+ .tls-confirm {
4
+ --tls-confirm-padding: var(--spacing-4);
5
+ --tls-confirm-max-width: 320px;
6
+
7
+ --tls-confirm-border-radius: var(--radius-lg);
8
+ --tls-confirm-border-width: 1px;
9
+
10
+ --tls-confirm-box-shadow: var(--shadow-md);
11
+ --tls-confirm-background-color: var(--color-surface-container-lowest);
12
+ --tls-confirm-color: var(--color-on-surface);
13
+ --tls-confirm-border-color: var(--color-outline-variant);
14
+
15
+ max-width: var(--tls-confirm-max-width);
16
+
17
+ padding: var(--tls-confirm-padding);
18
+
19
+ display: flex;
20
+ flex-direction: column;
21
+ gap: var(--spacing-4);
22
+
23
+ border: var(--tls-confirm-border-width) solid var(--tls-confirm-border-color);
24
+ border-radius: var(--tls-confirm-border-radius);
25
+
26
+ background-color: var(--tls-confirm-background-color);
27
+ box-shadow: var(--tls-confirm-box-shadow);
28
+
29
+ color: var(--tls-confirm-color);
30
+
31
+ @include mixins.panel-open;
32
+
33
+ &__title {
34
+ margin: 0;
35
+
36
+ font-size: var(--font-size-md);
37
+ font-weight: var(--font-weight-semibold);
38
+ }
39
+
40
+ &__message {
41
+ margin: 0;
42
+
43
+ font-size: var(--font-size-sm);
44
+ color: var(--color-on-surface-variant);
45
+ }
46
+
47
+ &__actions {
48
+ display: flex;
49
+ gap: var(--spacing-2);
50
+
51
+ &--start {
52
+ justify-content: flex-start;
53
+ }
54
+
55
+ &--center {
56
+ justify-content: center;
57
+ }
58
+
59
+ &--end {
60
+ justify-content: flex-end;
61
+ }
62
+
63
+ &--space-between {
64
+ justify-content: space-between;
65
+ }
66
+ }
67
+ }
@@ -26,7 +26,7 @@
26
26
  // Orientation
27
27
  &.tls-divider--horizontal {
28
28
  .tls-divider-line {
29
- border-right-width: 0;
29
+ border-inline-end-width: 0;
30
30
  border-bottom-width: var(--tls-divider-line-size);
31
31
  }
32
32
  }
@@ -35,7 +35,7 @@
35
35
  flex-direction: column;
36
36
 
37
37
  .tls-divider-line {
38
- border-right-width: var(--tls-divider-line-size);
38
+ border-inline-end-width: var(--tls-divider-line-size);
39
39
  border-bottom-width: 0;
40
40
  }
41
41
  }
@@ -84,7 +84,7 @@
84
84
  flex-grow: 1;
85
85
 
86
86
  border-top-width: 0;
87
- border-left-width: 0;
87
+ border-inline-start-width: 0;
88
88
  border-style: var(--tls-divider-line-variant);
89
89
  border-color: var(--tls-divider-line-color);
90
90
  }
@@ -50,7 +50,7 @@
50
50
 
51
51
  appearance: none;
52
52
  border: none;
53
- text-align: left;
53
+ text-align: start;
54
54
  text-decoration: none;
55
55
  cursor: pointer;
56
56
  white-space: nowrap;
@@ -0,0 +1,74 @@
1
+ @use '../mixins' as mixins;
2
+
3
+ .tls-odometer {
4
+ --tls-odometer-easing: var(--motion-ease-out);
5
+
6
+ display: inline-flex;
7
+ align-items: baseline;
8
+
9
+ // Numbers always read left-to-right, even inside an RTL layout, so the digit
10
+ // order is pinned rather than inherited from the surrounding direction.
11
+ direction: ltr;
12
+ font-variant-numeric: tabular-nums;
13
+ line-height: 1;
14
+
15
+ &__value {
16
+ position: absolute;
17
+
18
+ width: 1px;
19
+ height: 1px;
20
+
21
+ margin: -1px;
22
+ padding: 0;
23
+
24
+ overflow: hidden;
25
+
26
+ clip-path: inset(50%);
27
+ white-space: nowrap;
28
+
29
+ border: 0;
30
+ }
31
+
32
+ &__row {
33
+ display: inline-flex;
34
+ align-items: baseline;
35
+ }
36
+
37
+ &__symbol {
38
+ display: inline-flex;
39
+ justify-content: center;
40
+ }
41
+ }
42
+
43
+ .tls-odometer-digit {
44
+ height: 1em;
45
+
46
+ display: inline-block;
47
+
48
+ overflow: hidden;
49
+
50
+ &__strip {
51
+ display: flex;
52
+ flex-direction: column;
53
+
54
+ transform: translateY(calc(var(--tls-odometer-offset) * -1em));
55
+
56
+ // The roll communicates a value change (functional state), so it lives on
57
+ // the `essential` tier and survives reduced motion (resolved by
58
+ // `MotionService`). At the `none` level the transition is dropped and the
59
+ // digit swaps instantly.
60
+ @include mixins.motion(essential) {
61
+ &--animate {
62
+ transition: transform var(--tls-odometer-duration, 600ms) var(--tls-odometer-easing);
63
+ }
64
+ }
65
+ }
66
+
67
+ &__cell {
68
+ height: 1em;
69
+
70
+ display: flex;
71
+ align-items: center;
72
+ justify-content: center;
73
+ }
74
+ }
@@ -30,7 +30,7 @@
30
30
  &__close {
31
31
  position: absolute;
32
32
  top: var(--tls-dialog-close-padding);
33
- right: var(--tls-dialog-close-padding);
33
+ inset-inline-end: var(--tls-dialog-close-padding);
34
34
  z-index: 1;
35
35
 
36
36
  display: flex;
@@ -0,0 +1,103 @@
1
+ .tls-drawer {
2
+ // Named size presets. A custom length string is applied inline as
3
+ // `--tls-drawer-size` by the component (`.tls-drawer--custom`), so it needs no rule.
4
+ &--sm {
5
+ --tls-drawer-size: 320px;
6
+ }
7
+
8
+ &--md {
9
+ --tls-drawer-size: 400px;
10
+ }
11
+
12
+ &--lg {
13
+ --tls-drawer-size: 560px;
14
+ }
15
+
16
+ &--start,
17
+ &--end {
18
+ height: 100dvh;
19
+ width: var(--tls-drawer-size);
20
+ max-width: 100dvw;
21
+ }
22
+
23
+ &--top,
24
+ &--bottom {
25
+ width: 100dvw;
26
+ height: var(--tls-drawer-size);
27
+ max-height: 100dvh;
28
+ }
29
+
30
+ &--start {
31
+ --tls-drawer-offset: translateX(-100%);
32
+ }
33
+
34
+ &--end {
35
+ --tls-drawer-offset: translateX(100%);
36
+ }
37
+
38
+ &--top {
39
+ --tls-drawer-offset: translateY(-100%);
40
+ }
41
+
42
+ &--bottom {
43
+ --tls-drawer-offset: translateY(100%);
44
+ }
45
+
46
+ // Rounds the inner edge only (the two corners facing the viewport). Opt-in; the
47
+ // drawer sits flush by default.
48
+ &--rounded {
49
+ &.tls-drawer--start {
50
+ border-radius: 0 var(--tls-drawer-border-radius) var(--tls-drawer-border-radius) 0;
51
+ }
52
+
53
+ &.tls-drawer--end {
54
+ border-radius: var(--tls-drawer-border-radius) 0 0 var(--tls-drawer-border-radius);
55
+ }
56
+
57
+ &.tls-drawer--top {
58
+ border-radius: 0 0 var(--tls-drawer-border-radius) var(--tls-drawer-border-radius);
59
+ }
60
+
61
+ &.tls-drawer--bottom {
62
+ border-radius: var(--tls-drawer-border-radius) var(--tls-drawer-border-radius) 0 0;
63
+ }
64
+ }
65
+
66
+ // In RTL the logical `start`/`end` edges swap sides, so the slide offset and the
67
+ // rounded inner corners mirror. `top`/`bottom` are unaffected. The position
68
+ // strategy resolves the physical edge separately (see DrawerService).
69
+ :root[dir='rtl'] & {
70
+ &--start {
71
+ --tls-drawer-offset: translateX(100%);
72
+ }
73
+
74
+ &--end {
75
+ --tls-drawer-offset: translateX(-100%);
76
+ }
77
+
78
+ &--rounded {
79
+ &.tls-drawer--start {
80
+ border-radius: var(--tls-drawer-border-radius) 0 0 var(--tls-drawer-border-radius);
81
+ }
82
+
83
+ &.tls-drawer--end {
84
+ border-radius: 0 var(--tls-drawer-border-radius) var(--tls-drawer-border-radius) 0;
85
+ }
86
+ }
87
+ }
88
+
89
+ // Fills the cross axis edge-to-edge; the main axis stretches to the full viewport.
90
+ &--full {
91
+ --tls-drawer-border-radius: 0;
92
+
93
+ &.tls-drawer--start,
94
+ &.tls-drawer--end {
95
+ width: 100dvw;
96
+ }
97
+
98
+ &.tls-drawer--top,
99
+ &.tls-drawer--bottom {
100
+ height: 100dvh;
101
+ }
102
+ }
103
+ }
@@ -0,0 +1,121 @@
1
+ @use '../../mixins' as mixins;
2
+
3
+ @keyframes tls-drawer-slide-in {
4
+ from {
5
+ transform: var(--tls-drawer-offset);
6
+ }
7
+
8
+ to {
9
+ transform: none;
10
+ }
11
+ }
12
+
13
+ @keyframes tls-drawer-slide-out {
14
+ from {
15
+ transform: none;
16
+ }
17
+
18
+ to {
19
+ transform: var(--tls-drawer-offset);
20
+ }
21
+ }
22
+
23
+ .tls-drawer-backdrop {
24
+ --tls-drawer-backdrop: rgb(0 0 0 / 0.4);
25
+
26
+ background-color: var(--tls-drawer-backdrop);
27
+ }
28
+
29
+ .tls-drawer {
30
+ --tls-drawer-background: var(--color-surface-container-lowest);
31
+ --tls-drawer-color: var(--color-on-surface);
32
+ --tls-drawer-border-radius: var(--radius-xl);
33
+ --tls-drawer-shadow: var(--shadow-lg);
34
+ --tls-drawer-padding: var(--spacing-6);
35
+ --tls-drawer-close-size: 16px;
36
+ --tls-drawer-close-padding: var(--spacing-4);
37
+
38
+ position: relative;
39
+
40
+ display: flex;
41
+ flex-direction: column;
42
+
43
+ pointer-events: auto;
44
+
45
+ background-color: var(--tls-drawer-background);
46
+ color: var(--tls-drawer-color);
47
+ box-shadow: var(--tls-drawer-shadow);
48
+
49
+ // The slide communicates the panel's spatial origin, so it is a functional cue
50
+ // on the `essential` tier and survives reduced motion (resolved by `MotionService`).
51
+ // Enter and leave use distinct keyframe names, not one shared keyframe with
52
+ // `reverse`: the container keeps its `--enter` class for the panel's whole
53
+ // lifetime, so swapping to `--leave` must change `animation-name` to force the
54
+ // browser to start a fresh animation (a mere `animation-direction` change does
55
+ // not restart an already-finished animation).
56
+ @include mixins.motion(essential) {
57
+ &--enter {
58
+ animation: tls-drawer-slide-in var(--motion-instant) var(--motion-ease-out) both;
59
+ }
60
+
61
+ &--leave {
62
+ animation: tls-drawer-slide-out var(--motion-instant) var(--motion-ease-in) both;
63
+ }
64
+ }
65
+
66
+ &__close {
67
+ position: absolute;
68
+ top: var(--tls-drawer-close-padding);
69
+ inset-inline-end: var(--tls-drawer-close-padding);
70
+ z-index: 1;
71
+
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: center;
75
+
76
+ width: var(--tls-drawer-close-size);
77
+ height: var(--tls-drawer-close-size);
78
+
79
+ color: var(--color-outline);
80
+ background: transparent;
81
+ border: none;
82
+ cursor: pointer;
83
+
84
+ transition: color var(--motion-fast) var(--motion-ease-in-out);
85
+
86
+ &:hover {
87
+ color: var(--color-on-surface);
88
+ }
89
+
90
+ svg {
91
+ width: 100%;
92
+ height: 100%;
93
+ }
94
+ }
95
+
96
+ &__header {
97
+ padding: var(--tls-drawer-padding) var(--tls-drawer-padding) 0;
98
+ }
99
+
100
+ &__title {
101
+ font-size: var(--font-title-large-size);
102
+ font-weight: var(--font-weight-medium);
103
+ line-height: var(--font-title-large-line-height);
104
+ color: var(--color-on-surface);
105
+ }
106
+
107
+ &__body {
108
+ flex: 1;
109
+ padding: var(--spacing-4) var(--tls-drawer-padding);
110
+ overflow-y: auto;
111
+ }
112
+
113
+ &__footer {
114
+ padding: 0 var(--tls-drawer-padding) var(--tls-drawer-padding);
115
+
116
+ display: flex;
117
+ align-items: center;
118
+ justify-content: flex-end;
119
+ gap: var(--spacing-3);
120
+ }
121
+ }
@@ -0,0 +1,2 @@
1
+ @forward 'drawer';
2
+ @forward 'drawer-side';
@@ -4,6 +4,7 @@
4
4
  @forward 'chip';
5
5
  @forward 'date-time-picker';
6
6
  @forward 'dialog';
7
+ @forward 'drawer';
7
8
  @forward 'loader';
8
9
  @forward 'pagination';
9
10
  @forward 'multi-select';
@@ -18,12 +19,14 @@
18
19
 
19
20
  @forward 'checkbox';
20
21
  @forward 'chip-group';
22
+ @forward 'confirm';
21
23
  @forward 'chip-input';
22
24
  @forward 'divider';
23
25
  @forward 'file-uploader';
24
26
  @forward 'form-item';
25
27
  @forward 'icon';
26
28
  @forward 'menu';
29
+ @forward 'odometer';
27
30
  @forward 'password';
28
31
  @forward 'input-number';
29
32
  @forward 'pin-input';
@@ -56,7 +56,7 @@
56
56
 
57
57
  appearance: none;
58
58
  cursor: pointer;
59
- text-align: left;
59
+ text-align: start;
60
60
 
61
61
  color: var(--tls-multi-select-option-color);
62
62
  background: var(--tls-multi-select-option-background);
@@ -71,7 +71,7 @@
71
71
  .tls-multi-select__clear {
72
72
  position: absolute;
73
73
  top: 50%;
74
- right: calc(var(--tls-form-control-padding-inline) * 2 + var(--tls-multi-select-icon-size));
74
+ inset-inline-end: calc(var(--tls-form-control-padding-inline) * 2 + var(--tls-multi-select-icon-size));
75
75
 
76
76
  display: flex;
77
77
  align-items: center;
@@ -54,7 +54,7 @@
54
54
 
55
55
  appearance: none;
56
56
  cursor: pointer;
57
- text-align: left;
57
+ text-align: start;
58
58
 
59
59
  color: var(--tls-select-option-color);
60
60
  background: var(--tls-select-option-background);
@@ -79,7 +79,7 @@
79
79
  .tls-select__clear {
80
80
  position: absolute;
81
81
  top: 50%;
82
- right: calc(var(--tls-form-control-padding-inline) * 2 + var(--tls-select-icon-size));
82
+ inset-inline-end: calc(var(--tls-form-control-padding-inline) * 2 + var(--tls-select-icon-size));
83
83
 
84
84
  display: flex;
85
85
  align-items: center;
@@ -42,7 +42,7 @@
42
42
 
43
43
  &__divider {
44
44
  top: 0;
45
- left: calc(var(--tls-stepper-index-size) / 2 - (var(--tls-stepper-divider-width) / 2));
45
+ inset-inline-start: calc(var(--tls-stepper-index-size) / 2 - (var(--tls-stepper-divider-width) / 2));
46
46
 
47
47
  width: var(--tls-stepper-divider-width);
48
48
  height: 100%;
@@ -129,6 +129,7 @@
129
129
  // Content
130
130
  .tls-stepper-content {
131
131
  flex-grow: 1;
132
+ overflow: hidden;
132
133
 
133
134
  // Step
134
135
  .tls-step {
@@ -60,14 +60,18 @@
60
60
  // Checked
61
61
  &.tls-switch--checked {
62
62
  --tls-switch-handle-gap: 3px;
63
+ --tls-switch-translate: calc(
64
+ var(--tls-switch-width) - var(--tls-switch-handle-size) -
65
+ (var(--tls-switch-handle-gap) * 2) - (var(--tls-switch-border-width) * 2)
66
+ );
63
67
 
64
68
  .tls-switch-handle {
65
- $translate-x: calc(
66
- var(--tls-switch-width) - var(--tls-switch-handle-size) -
67
- (var(--tls-switch-handle-gap) * 2) - (var(--tls-switch-border-width) * 2)
68
- );
69
+ transform: translateX(var(--tls-switch-translate));
70
+ }
69
71
 
70
- transform: translateX(#{$translate-x});
72
+ // The handle travels toward the trailing edge; mirror it in RTL.
73
+ :root[dir='rtl'] & .tls-switch-handle {
74
+ transform: translateX(calc(-1 * var(--tls-switch-translate)));
71
75
  }
72
76
  }
73
77
 
@@ -42,8 +42,8 @@
42
42
  margin-bottom: -1px;
43
43
 
44
44
  border-width: 0;
45
- border-left-width: var(--tls-tabs-active-border-width);
46
- border-right-width: var(--tls-tabs-active-border-width);
45
+ border-inline-start-width: var(--tls-tabs-active-border-width);
46
+ border-inline-end-width: var(--tls-tabs-active-border-width);
47
47
  border-style: solid;
48
48
 
49
49
  &:hover {
@@ -51,7 +51,7 @@
51
51
  }
52
52
 
53
53
  &:first-child {
54
- border-left-width: 0;
54
+ border-inline-start-width: 0;
55
55
  }
56
56
 
57
57
  &.tls-tabs-header__item--active {
@@ -17,7 +17,7 @@
17
17
 
18
18
  .tls-toggle-group__option:not(:first-child) {
19
19
  border-top: var(--tls-toggle-group-border-width) solid var(--tls-toggle-group-border-color);
20
- border-left: none;
20
+ border-inline-start: none;
21
21
  }
22
22
  }
23
23
 
@@ -54,7 +54,7 @@
54
54
  }
55
55
 
56
56
  &:not(:first-child) {
57
- border-left: var(--tls-toggle-group-border-width) solid var(--tls-toggle-group-border-color);
57
+ border-inline-start: var(--tls-toggle-group-border-width) solid var(--tls-toggle-group-border-color);
58
58
  }
59
59
 
60
60
  &:focus-visible {
@@ -1,3 +1,5 @@
1
+ @use '../../mixins' as mixins;
2
+
1
3
  .tls-tooltip {
2
4
  --tls-tooltip-box-shadow: 0 2px 8px -1px var(--color-shade-30);
3
5
  --tls-tooltip-padding: var(--spacing-3);
@@ -11,4 +13,6 @@
11
13
  background-color: var(--tls-tooltip-color);
12
14
 
13
15
  box-shadow: var(--tls-tooltip-box-shadow);
16
+
17
+ @include mixins.panel-open;
14
18
  }