@thalassic/themes 22.6.0 → 22.7.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 +1 -1
- package/themes/thalassic/components/badge/_badge.scss +4 -0
- package/themes/thalassic/components/image-compare/_image-compare-orientation.scss +47 -0
- package/themes/thalassic/components/image-compare/_image-compare.scss +115 -0
- package/themes/thalassic/components/image-compare/_index.scss +2 -0
- package/themes/thalassic/components/index.scss +2 -0
- package/themes/thalassic/components/splitter/_index.scss +2 -0
- package/themes/thalassic/components/splitter/_splitter-orientation.scss +61 -0
- package/themes/thalassic/components/splitter/_splitter.scss +96 -0
- package/themes/thalassic/components/tabs/_tabs-orientation.scss +11 -0
- package/themes/thalassic/components/tabs/_tabs.scss +14 -0
package/package.json
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
.tls-image-compare {
|
|
2
|
+
// Horizontal: the divider is vertical and wipes along the inline axis. The
|
|
3
|
+
// inline slide mirrors in RTL, where the layout-start edge sits on the
|
|
4
|
+
// opposite physical side.
|
|
5
|
+
&--horizontal {
|
|
6
|
+
// The whole component is grabbable — a pointer-down anywhere drags the
|
|
7
|
+
// divider — so the resize cursor lives on the host, not just the handle.
|
|
8
|
+
cursor: ew-resize;
|
|
9
|
+
|
|
10
|
+
> .tls-image-compare__handle {
|
|
11
|
+
inset-block: 0;
|
|
12
|
+
|
|
13
|
+
transform: translateX(-50%);
|
|
14
|
+
|
|
15
|
+
:root[dir='rtl'] & {
|
|
16
|
+
transform: translateX(50%);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Vertical divider line down the centre of the handle.
|
|
20
|
+
&::before {
|
|
21
|
+
inset-block: 0;
|
|
22
|
+
inset-inline-start: calc(50% - var(--tls-image-compare-line-thickness) / 2);
|
|
23
|
+
|
|
24
|
+
width: var(--tls-image-compare-line-thickness);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Vertical: the divider is horizontal and wipes along the block axis.
|
|
30
|
+
&--vertical {
|
|
31
|
+
cursor: ns-resize;
|
|
32
|
+
|
|
33
|
+
> .tls-image-compare__handle {
|
|
34
|
+
inset-inline: 0;
|
|
35
|
+
|
|
36
|
+
transform: translateY(-50%);
|
|
37
|
+
|
|
38
|
+
// Horizontal divider line across the centre of the handle.
|
|
39
|
+
&::before {
|
|
40
|
+
inset-inline: 0;
|
|
41
|
+
inset-block-start: calc(50% - var(--tls-image-compare-line-thickness) / 2);
|
|
42
|
+
|
|
43
|
+
height: var(--tls-image-compare-line-thickness);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
@use '../../mixins' as mixins;
|
|
2
|
+
|
|
3
|
+
.tls-image-compare {
|
|
4
|
+
// Divider line running the full length of the component.
|
|
5
|
+
--tls-image-compare-line-color: var(--color-surface);
|
|
6
|
+
--tls-image-compare-line-thickness: 2px;
|
|
7
|
+
|
|
8
|
+
// Circular grab handle centred on the divider.
|
|
9
|
+
--tls-image-compare-handle-size: var(--spacing-8);
|
|
10
|
+
--tls-image-compare-handle-color: var(--color-surface);
|
|
11
|
+
--tls-image-compare-handle-border: var(--tls-image-compare-line-thickness);
|
|
12
|
+
|
|
13
|
+
position: relative;
|
|
14
|
+
|
|
15
|
+
width: 100%;
|
|
16
|
+
|
|
17
|
+
display: block;
|
|
18
|
+
|
|
19
|
+
overflow: hidden;
|
|
20
|
+
|
|
21
|
+
// A pointer-down anywhere drags the divider, so suppress native pan/zoom
|
|
22
|
+
// gestures across the whole component (not just the handle) — otherwise a
|
|
23
|
+
// touch drag over the image scrolls the page and cancels the pointer.
|
|
24
|
+
touch-action: none;
|
|
25
|
+
|
|
26
|
+
&--dragging {
|
|
27
|
+
user-select: none;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&__layer {
|
|
31
|
+
// Projected media never captures the pointer or gets dragged as an image.
|
|
32
|
+
> * {
|
|
33
|
+
display: block;
|
|
34
|
+
|
|
35
|
+
user-select: none;
|
|
36
|
+
-webkit-user-drag: none;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// The `after` layer sits in normal flow: its media's natural aspect ratio
|
|
41
|
+
// gives the whole component its height.
|
|
42
|
+
&__after {
|
|
43
|
+
> * {
|
|
44
|
+
width: 100%;
|
|
45
|
+
height: auto;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// The `before` layer overlays the `after` layer at the same box and is clipped
|
|
50
|
+
// to the divider band; its media is stretched to cover that box so the two
|
|
51
|
+
// images register pixel-for-pixel.
|
|
52
|
+
&__before {
|
|
53
|
+
position: absolute;
|
|
54
|
+
inset: 0;
|
|
55
|
+
|
|
56
|
+
> * {
|
|
57
|
+
width: 100%;
|
|
58
|
+
height: 100%;
|
|
59
|
+
|
|
60
|
+
object-fit: cover;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
&__handle {
|
|
65
|
+
position: absolute;
|
|
66
|
+
z-index: 1;
|
|
67
|
+
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: center;
|
|
71
|
+
|
|
72
|
+
background-color: transparent;
|
|
73
|
+
|
|
74
|
+
&:focus-visible {
|
|
75
|
+
outline: none;
|
|
76
|
+
|
|
77
|
+
.tls-image-compare__grip {
|
|
78
|
+
border-color: var(--color-primary);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
&:hover {
|
|
83
|
+
.tls-image-compare__grip {
|
|
84
|
+
border-color: var(--color-primary);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Divider line. Axis-specific sizing/insets live in the orientation partial.
|
|
89
|
+
&::before {
|
|
90
|
+
content: '';
|
|
91
|
+
|
|
92
|
+
position: absolute;
|
|
93
|
+
|
|
94
|
+
background-color: var(--tls-image-compare-line-color);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
&__grip {
|
|
99
|
+
// Lifts the handle above the divider line in paint order.
|
|
100
|
+
position: relative;
|
|
101
|
+
|
|
102
|
+
width: var(--tls-image-compare-handle-size);
|
|
103
|
+
height: var(--tls-image-compare-handle-size);
|
|
104
|
+
|
|
105
|
+
border: var(--tls-image-compare-handle-border) solid transparent;
|
|
106
|
+
border-radius: 50%;
|
|
107
|
+
|
|
108
|
+
background-color: var(--tls-image-compare-handle-color);
|
|
109
|
+
box-shadow: var(--shadow-sm);
|
|
110
|
+
|
|
111
|
+
@include mixins.motion(essential) {
|
|
112
|
+
transition: border-color var(--motion-fast);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
@forward 'file-input';
|
|
29
29
|
@forward 'form-item';
|
|
30
30
|
@forward 'icon';
|
|
31
|
+
@forward 'image-compare';
|
|
31
32
|
@forward 'menu';
|
|
32
33
|
@forward 'odometer';
|
|
33
34
|
@forward 'password';
|
|
@@ -36,5 +37,6 @@
|
|
|
36
37
|
@forward 'popover';
|
|
37
38
|
@forward 'radio-button';
|
|
38
39
|
@forward 'skeleton';
|
|
40
|
+
@forward 'splitter';
|
|
39
41
|
@forward 'table';
|
|
40
42
|
@forward 'toggle-group';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
.tls-splitter {
|
|
2
|
+
// Horizontal: panels sit side by side, separated by vertical gutters. The
|
|
3
|
+
// direct-child selector stops these rules from leaking into a nested splitter
|
|
4
|
+
// of the opposite orientation.
|
|
5
|
+
&--horizontal {
|
|
6
|
+
flex-direction: row;
|
|
7
|
+
|
|
8
|
+
> .tls-splitter-gutter {
|
|
9
|
+
inset-block: 0;
|
|
10
|
+
|
|
11
|
+
width: var(--tls-splitter-gutter-size);
|
|
12
|
+
|
|
13
|
+
cursor: col-resize;
|
|
14
|
+
|
|
15
|
+
// Centre the gutter on the seam. The inline slide mirrors in RTL, where
|
|
16
|
+
// the logical start edge sits on the opposite physical side.
|
|
17
|
+
transform: translateX(-50%);
|
|
18
|
+
|
|
19
|
+
--tls-splitter-handle-inline: var(--tls-splitter-handle-thickness);
|
|
20
|
+
--tls-splitter-handle-block: var(--tls-splitter-handle-length);
|
|
21
|
+
|
|
22
|
+
:root[dir='rtl'] & {
|
|
23
|
+
transform: translateX(50%);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Vertical seam line down the centre of the gutter.
|
|
27
|
+
&::before {
|
|
28
|
+
inset-block: 0;
|
|
29
|
+
inset-inline-start: calc(50% - var(--tls-splitter-line-thickness) / 2);
|
|
30
|
+
|
|
31
|
+
width: var(--tls-splitter-line-thickness);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Vertical: panels stack, separated by horizontal gutters.
|
|
37
|
+
&--vertical {
|
|
38
|
+
flex-direction: column;
|
|
39
|
+
|
|
40
|
+
> .tls-splitter-gutter {
|
|
41
|
+
inset-inline: 0;
|
|
42
|
+
|
|
43
|
+
height: var(--tls-splitter-gutter-size);
|
|
44
|
+
|
|
45
|
+
cursor: row-resize;
|
|
46
|
+
|
|
47
|
+
transform: translateY(-50%);
|
|
48
|
+
|
|
49
|
+
--tls-splitter-handle-inline: var(--tls-splitter-handle-length);
|
|
50
|
+
--tls-splitter-handle-block: var(--tls-splitter-handle-thickness);
|
|
51
|
+
|
|
52
|
+
// Horizontal seam line across the centre of the gutter.
|
|
53
|
+
&::before {
|
|
54
|
+
inset-inline: 0;
|
|
55
|
+
inset-block-start: calc(50% - var(--tls-splitter-line-thickness) / 2);
|
|
56
|
+
|
|
57
|
+
height: var(--tls-splitter-line-thickness);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
@use '../../mixins' as mixins;
|
|
2
|
+
|
|
3
|
+
.tls-splitter {
|
|
4
|
+
// Draggable hit area straddling the seam; larger than the visible line/handle.
|
|
5
|
+
--tls-splitter-gutter-size: var(--spacing-4);
|
|
6
|
+
|
|
7
|
+
// Thin seam line running the full length of the gutter.
|
|
8
|
+
--tls-splitter-line-color: var(--color-outline-variant);
|
|
9
|
+
--tls-splitter-line-thickness: 1px;
|
|
10
|
+
|
|
11
|
+
// Grab handle centred on the seam.
|
|
12
|
+
--tls-splitter-handle-color: var(--color-outline);
|
|
13
|
+
--tls-splitter-handle-hover-color: var(--color-primary);
|
|
14
|
+
--tls-splitter-handle-thickness: 4px;
|
|
15
|
+
--tls-splitter-handle-length: var(--spacing-8);
|
|
16
|
+
--tls-splitter-handle-radius: var(--radius-sm);
|
|
17
|
+
|
|
18
|
+
// Handle box, resolved per orientation on the gutter (see the orientation
|
|
19
|
+
// partial) and inherited by the handle. Defaults suit a horizontal splitter.
|
|
20
|
+
--tls-splitter-handle-inline: var(--tls-splitter-handle-thickness);
|
|
21
|
+
--tls-splitter-handle-block: var(--tls-splitter-handle-length);
|
|
22
|
+
|
|
23
|
+
position: relative;
|
|
24
|
+
|
|
25
|
+
width: 100%;
|
|
26
|
+
height: 100%;
|
|
27
|
+
|
|
28
|
+
display: flex;
|
|
29
|
+
|
|
30
|
+
overflow: hidden;
|
|
31
|
+
|
|
32
|
+
&--resizing {
|
|
33
|
+
user-select: none;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.tls-splitter-panel {
|
|
37
|
+
position: relative;
|
|
38
|
+
|
|
39
|
+
min-width: 0;
|
|
40
|
+
min-height: 0;
|
|
41
|
+
|
|
42
|
+
overflow: auto;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.tls-splitter-gutter {
|
|
46
|
+
position: absolute;
|
|
47
|
+
z-index: 1;
|
|
48
|
+
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
|
|
53
|
+
background-color: transparent;
|
|
54
|
+
|
|
55
|
+
touch-action: none;
|
|
56
|
+
|
|
57
|
+
&:focus-visible {
|
|
58
|
+
outline: none;
|
|
59
|
+
|
|
60
|
+
.tls-splitter-gutter__handle {
|
|
61
|
+
background-color: var(--tls-splitter-handle-hover-color);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
&:hover {
|
|
66
|
+
.tls-splitter-gutter__handle {
|
|
67
|
+
background-color: var(--tls-splitter-handle-hover-color);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Seam line. Axis-specific sizing/insets live in the orientation partial.
|
|
72
|
+
&::before {
|
|
73
|
+
content: '';
|
|
74
|
+
|
|
75
|
+
position: absolute;
|
|
76
|
+
|
|
77
|
+
background-color: var(--tls-splitter-line-color);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
&__handle {
|
|
81
|
+
// Lifts the handle above the seam line in paint order.
|
|
82
|
+
position: relative;
|
|
83
|
+
|
|
84
|
+
width: var(--tls-splitter-handle-inline);
|
|
85
|
+
height: var(--tls-splitter-handle-block);
|
|
86
|
+
|
|
87
|
+
border-radius: var(--tls-splitter-handle-radius);
|
|
88
|
+
|
|
89
|
+
background-color: var(--tls-splitter-handle-color);
|
|
90
|
+
|
|
91
|
+
@include mixins.motion(essential) {
|
|
92
|
+
transition: background-color var(--motion-fast);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
.tls-tabs {
|
|
2
|
+
// Horizontal
|
|
3
|
+
&.tls-tabs--horizontal {
|
|
4
|
+
.tls-tabs-header {
|
|
5
|
+
overflow-x: auto;
|
|
6
|
+
overflow-y: hidden;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
2
10
|
// Vertical
|
|
3
11
|
&.tls-tabs--vertical {
|
|
4
12
|
display: flex;
|
|
@@ -7,6 +15,9 @@
|
|
|
7
15
|
.tls-tabs-header {
|
|
8
16
|
flex-direction: column;
|
|
9
17
|
|
|
18
|
+
overflow-x: hidden;
|
|
19
|
+
overflow-y: auto;
|
|
20
|
+
|
|
10
21
|
border-color: var(--tls-tabs-border-color);
|
|
11
22
|
}
|
|
12
23
|
|
|
@@ -24,7 +24,19 @@
|
|
|
24
24
|
|
|
25
25
|
border-color: var(--tls-tabs-border-color);
|
|
26
26
|
|
|
27
|
+
// Tabs that exceed the header's extent scroll instead of shrinking
|
|
28
|
+
// (e.g. a horizontal strip on a narrow viewport). The scrollbar is
|
|
29
|
+
// hidden so it never covers the active-tab indicator line, while
|
|
30
|
+
// wheel/touch/keyboard scrolling stays available.
|
|
31
|
+
scrollbar-width: none;
|
|
32
|
+
|
|
33
|
+
&::-webkit-scrollbar {
|
|
34
|
+
display: none;
|
|
35
|
+
}
|
|
36
|
+
|
|
27
37
|
&__item {
|
|
38
|
+
flex-shrink: 0;
|
|
39
|
+
|
|
28
40
|
display: flex;
|
|
29
41
|
|
|
30
42
|
color: var(--tls-tabs-label-color);
|
|
@@ -53,6 +65,8 @@
|
|
|
53
65
|
}
|
|
54
66
|
|
|
55
67
|
&-button {
|
|
68
|
+
width: 100%;
|
|
69
|
+
|
|
56
70
|
padding: var(--spacing-3) var(--spacing-6);
|
|
57
71
|
|
|
58
72
|
// TODO: use mixin
|