@shift-css/core 0.5.0 → 0.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.
@@ -28,39 +28,76 @@ dialog[s-modal]:not([open]) {
28
28
  }
29
29
 
30
30
  dialog[s-modal][open] {
31
- animation: s-modal-scale-in var(--s-duration-200) var(--s-ease-out);
31
+ opacity: 1;
32
+ transition: opacity var(--s-duration-200) var(--s-ease-out),
33
+ transform var(--s-duration-200) var(--s-ease-out),
34
+ overlay var(--s-duration-200) var(--s-ease-out) allow-discrete,
35
+ display var(--s-duration-200) var(--s-ease-out) allow-discrete;
36
+ transform: scale(1)translateY(0);
32
37
  }
33
38
 
34
- dialog[s-modal]:focus-visible {
35
- outline: 2px solid var(--s-focus-ring);
36
- outline-offset: 2px;
37
- }
38
-
39
- @keyframes s-modal-scale-in {
40
- from {
39
+ @starting-style {
40
+ dialog[s-modal][open] {
41
41
  opacity: 0;
42
42
  transform: scale(.95)translateY(-10px);
43
43
  }
44
+ }
45
+
46
+ @supports not (transition-behavior: allow-discrete) {
47
+ dialog[s-modal][open] {
48
+ animation: s-modal-scale-in var(--s-duration-200) var(--s-ease-out);
49
+ }
50
+
51
+ @keyframes s-modal-scale-in {
52
+ from {
53
+ opacity: 0;
54
+ transform: scale(.95)translateY(-10px);
55
+ }
44
56
 
45
- to {
46
- opacity: 1;
47
- transform: scale(1)translateY(0);
57
+ to {
58
+ opacity: 1;
59
+ transform: scale(1)translateY(0);
60
+ }
48
61
  }
49
62
  }
50
63
 
64
+ dialog[s-modal]:focus-visible {
65
+ outline: 2px solid var(--s-focus-ring);
66
+ outline-offset: 2px;
67
+ }
68
+
51
69
  dialog[s-modal]::backdrop {
52
70
  backdrop-filter: blur(4px);
53
- animation: s-modal-backdrop-in var(--s-duration-200) var(--s-ease-out);
71
+ opacity: 1;
72
+ transition: opacity var(--s-duration-200) var(--s-ease-out),
73
+ overlay var(--s-duration-200) var(--s-ease-out) allow-discrete,
74
+ display var(--s-duration-200) var(--s-ease-out) allow-discrete;
54
75
  background: oklch(0% 0 0 / .5);
76
+
77
+ @supports (color: oklch(from red l c h)) {
78
+ background: oklch(from var(--s-primary-500) .1 .02 h / .5);
79
+ }
55
80
  }
56
81
 
57
- @keyframes s-modal-backdrop-in {
58
- from {
82
+ @starting-style {
83
+ dialog[s-modal]::backdrop {
59
84
  opacity: 0;
60
85
  }
86
+ }
87
+
88
+ @supports not (transition-behavior: allow-discrete) {
89
+ dialog[s-modal]::backdrop {
90
+ animation: s-modal-backdrop-in var(--s-duration-200) var(--s-ease-out);
91
+ }
92
+
93
+ @keyframes s-modal-backdrop-in {
94
+ from {
95
+ opacity: 0;
96
+ }
61
97
 
62
- to {
63
- opacity: 1;
98
+ to {
99
+ opacity: 1;
100
+ }
64
101
  }
65
102
  }
66
103
 
@@ -91,13 +128,29 @@ dialog[s-modal][s-position="bottom"] {
91
128
  }
92
129
 
93
130
  dialog[s-modal][s-position="left"] {
94
- margin-left: var(--s-space-8);
131
+ border-radius: 0 var(--_modal-radius) var(--_modal-radius) 0;
132
+ margin-left: 0;
95
133
  margin-right: auto;
96
134
  }
97
135
 
136
+ @media (width >= 640px) {
137
+ dialog[s-modal][s-position="left"] {
138
+ margin-left: var(--s-space-8);
139
+ border-radius: var(--_modal-radius);
140
+ }
141
+ }
142
+
98
143
  dialog[s-modal][s-position="right"] {
144
+ border-radius: var(--_modal-radius) 0 0 var(--_modal-radius);
99
145
  margin-left: auto;
100
- margin-right: var(--s-space-8);
146
+ margin-right: 0;
147
+ }
148
+
149
+ @media (width >= 640px) {
150
+ dialog[s-modal][s-position="right"] {
151
+ margin-right: var(--s-space-8);
152
+ border-radius: var(--_modal-radius);
153
+ }
101
154
  }
102
155
 
103
156
  :where([s-modal-header]) {
@@ -140,7 +193,8 @@ dialog[s-modal][s-position="right"] {
140
193
  min-height: 2.75rem;
141
194
  font-size: var(--s-text-xl);
142
195
  color: var(--s-text-secondary);
143
- transition: background-color var(--s-duration-150) var(--s-ease-out), color var(--s-duration-150) var(--s-ease-out);
196
+ transition: background-color var(--s-duration-150) var(--s-ease-out),
197
+ color var(--s-duration-150) var(--s-ease-out);
144
198
  background: none;
145
199
  border: none;
146
200
  justify-content: center;
@@ -164,6 +218,17 @@ dialog[s-modal][s-position="right"] {
164
218
  }
165
219
  }
166
220
 
221
+ @media (prefers-reduced-motion: reduce) {
222
+ dialog[s-modal][open] {
223
+ transition: none;
224
+ transform: none;
225
+ }
226
+
227
+ dialog[s-modal]::backdrop {
228
+ transition: none;
229
+ }
230
+ }
231
+
167
232
  @media (forced-colors: active) {
168
233
  dialog[s-modal] {
169
234
  border: 2px solid canvastext;
@@ -0,0 +1,169 @@
1
+ @supports (appearance: base-select) {
2
+ [s-select], [s-select]::picker(select) {
3
+ appearance: base-select;
4
+ }
5
+
6
+ :where([s-select]) {
7
+ --_select-bg: var(--s-surface-base);
8
+ --_select-border: var(--s-border-default);
9
+ --_select-text: var(--s-text-primary);
10
+ --_select-radius: var(--s-radius-md);
11
+ align-items: center;
12
+ gap: var(--s-space-2);
13
+ min-width: 10rem;
14
+ padding: var(--s-space-2) var(--s-space-3);
15
+ background-color: var(--_select-bg);
16
+ border: 2px solid var(--_select-border);
17
+ border-radius: var(--_select-radius);
18
+ color: var(--_select-text);
19
+ font-size: var(--s-text-sm);
20
+ line-height: var(--s-leading-normal);
21
+ cursor: pointer;
22
+ transition: border-color var(--s-duration-150) var(--s-ease-out),
23
+ box-shadow var(--s-duration-150) var(--s-ease-out);
24
+ display: inline-flex;
25
+
26
+ &:hover:not(:disabled) {
27
+ --_select-border: var(--s-border-strong);
28
+ }
29
+
30
+ &:open {
31
+ --_select-border: var(--s-interactive-primary);
32
+ }
33
+
34
+ &:focus-visible {
35
+ --_select-border: var(--s-interactive-primary);
36
+ outline: 2px solid var(--s-focus-ring);
37
+ outline-offset: 2px;
38
+
39
+ @supports (color: oklch(from red l c h)) {
40
+ outline-color: oklch(from var(--s-interactive-primary) l c h / .3);
41
+ }
42
+ }
43
+
44
+ &:disabled {
45
+ opacity: .5;
46
+ cursor: not-allowed;
47
+ background-color: var(--s-surface-sunken);
48
+ }
49
+ }
50
+
51
+ [s-select]::picker-icon {
52
+ color: var(--s-text-tertiary);
53
+ transition: rotate var(--s-duration-200) var(--s-ease-out);
54
+ }
55
+
56
+ [s-select]:open::picker-icon {
57
+ rotate: 180deg;
58
+ }
59
+
60
+ [s-select]::picker(select) {
61
+ background: var(--s-surface-base);
62
+ border: 2px solid var(--s-border-default);
63
+ border-radius: var(--s-radius-md);
64
+ box-shadow: var(--s-shadow-lg);
65
+ padding: var(--s-space-1);
66
+ inset: auto;
67
+ top: anchor(bottom);
68
+ left: anchor(left);
69
+ min-width: anchor-size(width);
70
+ }
71
+
72
+ [s-select] option {
73
+ align-items: center;
74
+ gap: var(--s-space-2);
75
+ padding: var(--s-space-2) var(--s-space-3);
76
+ border-radius: var(--s-radius-sm);
77
+ color: var(--s-text-primary);
78
+ cursor: pointer;
79
+ transition: background-color var(--s-duration-150) var(--s-ease-out);
80
+ display: flex;
81
+
82
+ &:hover {
83
+ background-color: var(--s-surface-hover);
84
+ }
85
+
86
+ &:checked {
87
+ background-color: var(--s-interactive-primary);
88
+ color: var(--s-text-on-primary);
89
+ }
90
+ }
91
+
92
+ [s-select] option::checkmark {
93
+ opacity: 0;
94
+ order: 1;
95
+ margin-left: auto;
96
+ }
97
+
98
+ [s-select] option:checked::checkmark {
99
+ opacity: 1;
100
+ }
101
+
102
+ [s-select][s-size="sm"] {
103
+ padding: var(--s-space-1) var(--s-space-2);
104
+ font-size: var(--s-text-xs);
105
+ min-width: 8rem;
106
+ }
107
+
108
+ [s-select][s-size="lg"] {
109
+ padding: var(--s-space-3) var(--s-space-4);
110
+ font-size: var(--s-text-base);
111
+ min-width: 12rem;
112
+ }
113
+
114
+ @container surface style(--_surface-depth: 1) {
115
+ :where([s-select]) {
116
+ --_select-bg: var(--s-surface-sunken);
117
+ }
118
+ }
119
+
120
+ @container surface style(--_surface-depth: 2) {
121
+ :where([s-select]) {
122
+ --_select-bg: var(--s-surface-sunken);
123
+ --_select-border: var(--s-border-strong);
124
+ }
125
+ }
126
+
127
+ @container surface style(--_surface-depth: -1) {
128
+ :where([s-select]) {
129
+ --_select-bg: var(--s-surface-raised);
130
+ --_select-border: var(--s-border-muted);
131
+ }
132
+ }
133
+ }
134
+
135
+ @supports not (appearance: base-select) {
136
+ [s-select] {
137
+ appearance: none;
138
+ width: 100%;
139
+ padding: var(--s-space-2) var(--s-space-3);
140
+ padding-right: var(--s-space-10);
141
+ background-color: var(--s-surface-base);
142
+ border: 2px solid var(--s-border-default);
143
+ border-radius: var(--s-radius-md);
144
+ color: var(--s-text-primary);
145
+ font-size: var(--s-text-sm);
146
+ line-height: var(--s-leading-normal);
147
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
148
+ background-repeat: no-repeat;
149
+ background-position: right var(--s-space-3) center;
150
+ transition: border-color var(--s-duration-150) var(--s-ease-out),
151
+ box-shadow var(--s-duration-150) var(--s-ease-out);
152
+ display: block;
153
+
154
+ &:hover:not(:disabled) {
155
+ border-color: var(--s-border-strong);
156
+ }
157
+
158
+ &:focus-visible {
159
+ border-color: var(--s-interactive-primary);
160
+ outline: 2px solid var(--s-focus-ring);
161
+ outline-offset: 2px;
162
+ }
163
+
164
+ &:disabled {
165
+ opacity: .5;
166
+ cursor: not-allowed;
167
+ }
168
+ }
169
+ }
@@ -15,7 +15,8 @@
15
15
  border-radius: var(--_skip-radius);
16
16
  box-shadow: var(--_skip-shadow);
17
17
  white-space: nowrap;
18
- transition: top var(--s-duration-200) var(--s-ease-out), opacity var(--s-duration-200) var(--s-ease-out);
18
+ transition: top var(--s-duration-200) var(--s-ease-out),
19
+ opacity var(--s-duration-200) var(--s-ease-out);
19
20
  opacity: 0;
20
21
  text-decoration: none;
21
22
  display: inline-flex;
@@ -28,7 +29,9 @@
28
29
  [s-skip-link]:focus, [s-skip-link]:focus-visible {
29
30
  top: var(--s-space-4);
30
31
  opacity: 1;
31
- box-shadow: var(--_skip-shadow), 0 0 0 3px white, 0 0 0 5px var(--_skip-bg);
32
+ box-shadow: var(--_skip-shadow),
33
+ 0 0 0 3px white,
34
+ 0 0 0 5px var(--_skip-bg);
32
35
  outline: none;
33
36
  }
34
37
 
@@ -77,7 +80,9 @@
77
80
  }
78
81
 
79
82
  [s-skip-link]:focus, [s-skip-link]:focus-visible {
80
- box-shadow: var(--_skip-shadow), 0 0 0 3px var(--s-neutral-900), 0 0 0 5px var(--_skip-bg);
83
+ box-shadow: var(--_skip-shadow),
84
+ 0 0 0 3px var(--s-neutral-900),
85
+ 0 0 0 5px var(--_skip-bg);
81
86
  }
82
87
  }
83
88
 
@@ -2,14 +2,18 @@
2
2
  --_surface-bg: var(--s-surface-base);
3
3
  --_surface-padding: var(--s-space-4);
4
4
  --_surface-radius: var(--s-radius-lg);
5
+ --_surface-depth: 0;
5
6
  background-color: var(--_surface-bg);
6
7
  padding: var(--_surface-padding);
7
8
  border-radius: var(--_surface-radius);
8
9
  color: var(--s-text-primary);
9
- container-type: inline-size;
10
+ container: surface / inline-size;
10
11
 
11
12
  @supports (color: oklch(from red l c h)) {
12
- color: oklch(from var(--_surface-bg) clamp(.15, calc((.55 - l) * 1000 + .15), .95) 0 0);
13
+ color: oklch(from var(--_surface-bg)
14
+ /* If L < 0.55, use light text (0.95); otherwise dark text (0.15)
15
+ Threshold 0.55 ensures 4.5:1 contrast per WCAG 2.1 AA */
16
+ clamp(.15, calc((.55 - l) * 1000 + .15), .95) 0 0);
13
17
  }
14
18
 
15
19
  @supports (color: contrast-color(red)) {
@@ -19,20 +23,24 @@
19
23
 
20
24
  [s-surface="flat"] {
21
25
  --_surface-bg: var(--s-surface-base);
26
+ --_surface-depth: 0;
22
27
  }
23
28
 
24
29
  [s-surface="sunken"] {
25
30
  --_surface-bg: var(--s-surface-sunken);
31
+ --_surface-depth: -1;
26
32
  box-shadow: var(--s-shadow-inner);
27
33
  }
28
34
 
29
35
  [s-surface="raised"] {
30
36
  --_surface-bg: var(--s-surface-raised);
37
+ --_surface-depth: 1;
31
38
  box-shadow: var(--s-shadow-md);
32
39
  }
33
40
 
34
41
  [s-surface="floating"] {
35
42
  --_surface-bg: var(--s-surface-raised);
43
+ --_surface-depth: 2;
36
44
  box-shadow: var(--s-shadow-xl);
37
45
  }
38
46
 
@@ -42,7 +50,8 @@
42
50
 
43
51
  [s-surface][s-interactive] {
44
52
  cursor: pointer;
45
- transition: transform var(--s-duration-150) var(--s-ease-out), box-shadow var(--s-duration-150) var(--s-ease-out);
53
+ transition: transform var(--s-duration-150) var(--s-ease-out),
54
+ box-shadow var(--s-duration-150) var(--s-ease-out);
46
55
 
47
56
  &:hover {
48
57
  box-shadow: var(--s-shadow-lg);
@@ -86,7 +95,7 @@
86
95
  background-color: #d4edda;
87
96
  background-color: var(--_surface-bg);
88
97
  border-left: 4px solid var(--s-state-success);
89
- color: #1a1a1a;
98
+ color: light-dark(#1a1a1a, #e5e5e5);
90
99
  }
91
100
 
92
101
  [s-surface="warning"] {
@@ -94,7 +103,7 @@
94
103
  background-color: #fff3cd;
95
104
  background-color: var(--_surface-bg);
96
105
  border-left: 4px solid var(--s-state-warning);
97
- color: #1a1a1a;
106
+ color: light-dark(#1a1a1a, #e5e5e5);
98
107
  }
99
108
 
100
109
  [s-surface="danger"] {
@@ -102,7 +111,7 @@
102
111
  background-color: #f8d7da;
103
112
  background-color: var(--_surface-bg);
104
113
  border-left: 4px solid var(--s-state-danger);
105
- color: #1a1a1a;
114
+ color: light-dark(#1a1a1a, #e5e5e5);
106
115
  }
107
116
 
108
117
  @container (width <= 20rem) {
@@ -0,0 +1,159 @@
1
+ :where([s-tooltip]) {
2
+ --_tooltip-bg: var(--s-surface-overlay);
3
+ --_tooltip-text: var(--s-text-inverse);
4
+ --_tooltip-radius: var(--s-radius-md);
5
+ --_tooltip-padding-x: var(--s-space-3);
6
+ --_tooltip-padding-y: var(--s-space-1_5);
7
+ --_tooltip-offset: var(--s-space-2);
8
+ --_tooltip-max-width: 200px;
9
+ --_tooltip-arrow-size: 6px;
10
+ position: relative;
11
+ }
12
+
13
+ :where([s-tooltip]):after {
14
+ content: attr(s-tooltip);
15
+ visibility: hidden;
16
+ opacity: 0;
17
+ z-index: 9999;
18
+ margin-bottom: var(--_tooltip-offset);
19
+ background-color: var(--_tooltip-bg);
20
+ color: var(--_tooltip-text);
21
+ padding: var(--_tooltip-padding-y) var(--_tooltip-padding-x);
22
+ border-radius: var(--_tooltip-radius);
23
+ box-shadow: var(--s-shadow-md);
24
+ position: absolute;
25
+ bottom: 100%;
26
+ left: 50%;
27
+ transform: translateX(-50%)translateY(4px);
28
+
29
+ @supports (color: oklch(from red l c h)) {
30
+ border: 1px solid
31
+ oklch(from var(--_tooltip-bg) max(calc(l - .1), .05) c h);
32
+ }
33
+
34
+ font-size: var(--s-text-xs);
35
+ font-weight: var(--s-font-medium);
36
+ line-height: var(--s-leading-tight);
37
+ text-align: center;
38
+ text-wrap: balance;
39
+ min-width: min(100%,
40
+ var(--_tooltip-max-width));
41
+ max-width: var(--_tooltip-max-width);
42
+ pointer-events: none;
43
+ transition: opacity var(--s-duration-150) var(--s-ease-out),
44
+ visibility var(--s-duration-150) var(--s-ease-out),
45
+ transform var(--s-duration-150) var(--s-ease-out);
46
+ }
47
+
48
+ :where([s-tooltip]):before {
49
+ content: "";
50
+ visibility: hidden;
51
+ opacity: 0;
52
+ z-index: 9999;
53
+ margin-bottom: calc(var(--_tooltip-offset) - var(--_tooltip-arrow-size));
54
+ border-left: var(--_tooltip-arrow-size) solid transparent;
55
+ border-right: var(--_tooltip-arrow-size) solid transparent;
56
+ border-top: var(--_tooltip-arrow-size) solid var(--_tooltip-bg);
57
+ pointer-events: none;
58
+ transition: opacity var(--s-duration-150) var(--s-ease-out),
59
+ visibility var(--s-duration-150) var(--s-ease-out),
60
+ transform var(--s-duration-150) var(--s-ease-out);
61
+ position: absolute;
62
+ bottom: 100%;
63
+ left: 50%;
64
+ transform: translateX(-50%)translateY(4px);
65
+ }
66
+
67
+ [s-tooltip]:hover:after, [s-tooltip]:hover:before, [s-tooltip]:focus-visible:after, [s-tooltip]:focus-visible:before {
68
+ visibility: visible;
69
+ opacity: 1;
70
+ transform: translateX(-50%)translateY(0);
71
+ }
72
+
73
+ [s-tooltip-pos="bottom"]:after {
74
+ margin-bottom: 0;
75
+ margin-top: var(--_tooltip-offset);
76
+ top: 100%;
77
+ bottom: auto;
78
+ transform: translateX(-50%)translateY(-4px);
79
+ }
80
+
81
+ [s-tooltip-pos="bottom"]:before {
82
+ margin-bottom: 0;
83
+ margin-top: calc(var(--_tooltip-offset) - var(--_tooltip-arrow-size));
84
+ border-top: none;
85
+ border-bottom: var(--_tooltip-arrow-size) solid var(--_tooltip-bg);
86
+ top: 100%;
87
+ bottom: auto;
88
+ transform: translateX(-50%)translateY(-4px);
89
+ }
90
+
91
+ [s-tooltip-pos="bottom"]:hover:after, [s-tooltip-pos="bottom"]:hover:before, [s-tooltip-pos="bottom"]:focus-visible:after, [s-tooltip-pos="bottom"]:focus-visible:before {
92
+ transform: translateX(-50%)translateY(0);
93
+ }
94
+
95
+ [s-tooltip-pos="left"]:after {
96
+ margin-bottom: 0;
97
+ margin-right: var(--_tooltip-offset);
98
+ inset: 50% 100% auto auto;
99
+ transform: translateY(-50%)translateX(4px);
100
+ }
101
+
102
+ [s-tooltip-pos="left"]:before {
103
+ margin-bottom: 0;
104
+ margin-right: calc(var(--_tooltip-offset) - var(--_tooltip-arrow-size));
105
+ border-top: var(--_tooltip-arrow-size) solid transparent;
106
+ border-bottom: var(--_tooltip-arrow-size) solid transparent;
107
+ border-left: var(--_tooltip-arrow-size) solid var(--_tooltip-bg);
108
+ border-right: none;
109
+ inset: 50% 100% auto auto;
110
+ transform: translateY(-50%)translateX(4px);
111
+ }
112
+
113
+ [s-tooltip-pos="left"]:hover:after, [s-tooltip-pos="left"]:hover:before, [s-tooltip-pos="left"]:focus-visible:after, [s-tooltip-pos="left"]:focus-visible:before {
114
+ transform: translateY(-50%)translateX(0);
115
+ }
116
+
117
+ [s-tooltip-pos="right"]:after {
118
+ margin-bottom: 0;
119
+ margin-left: var(--_tooltip-offset);
120
+ top: 50%;
121
+ bottom: auto;
122
+ left: 100%;
123
+ transform: translateY(-50%)translateX(-4px);
124
+ }
125
+
126
+ [s-tooltip-pos="right"]:before {
127
+ margin-bottom: 0;
128
+ margin-left: calc(var(--_tooltip-offset) - var(--_tooltip-arrow-size));
129
+ border-top: var(--_tooltip-arrow-size) solid transparent;
130
+ border-bottom: var(--_tooltip-arrow-size) solid transparent;
131
+ border-right: var(--_tooltip-arrow-size) solid var(--_tooltip-bg);
132
+ border-left: none;
133
+ top: 50%;
134
+ bottom: auto;
135
+ left: 100%;
136
+ transform: translateY(-50%)translateX(-4px);
137
+ }
138
+
139
+ [s-tooltip-pos="right"]:hover:after, [s-tooltip-pos="right"]:hover:before, [s-tooltip-pos="right"]:focus-visible:after, [s-tooltip-pos="right"]:focus-visible:before {
140
+ transform: translateY(-50%)translateX(0);
141
+ }
142
+
143
+ @media (prefers-reduced-motion: reduce) {
144
+ [s-tooltip]:after, [s-tooltip]:before {
145
+ transition: none;
146
+ }
147
+ }
148
+
149
+ @media (forced-colors: active) {
150
+ [s-tooltip]:after {
151
+ color: canvastext;
152
+ background-color: canvas;
153
+ border: 1px solid canvastext;
154
+ }
155
+
156
+ [s-tooltip]:before {
157
+ display: none;
158
+ }
159
+ }
package/dist/reset.css CHANGED
@@ -16,7 +16,7 @@ html {
16
16
 
17
17
  -webkit-font-smoothing: antialiased;
18
18
  -moz-osx-font-smoothing: grayscale;
19
- text-rendering: optimizeLegibility;
19
+ text-rendering: optimizelegibility;
20
20
  }
21
21
 
22
22
  body {