@leftium/nimble.css 0.1.0 → 0.2.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 +99 -19
- package/dist/nimble-base.css +10 -132
- package/dist/nimble-base.min.css +1 -1
- package/dist/nimble-core.css +790 -0
- package/dist/nimble-core.min.css +1 -0
- package/dist/nimble-full.css +946 -0
- package/dist/nimble-full.min.css +1 -0
- package/dist/nimble-meter.css +45 -0
- package/dist/nimble-meter.min.css +1 -0
- package/dist/nimble-progress.css +71 -0
- package/dist/nimble-progress.min.css +1 -0
- package/dist/nimble-reset.css +2 -1
- package/dist/nimble-reset.min.css +1 -1
- package/dist/nimble-select.css +43 -0
- package/dist/nimble-select.min.css +1 -0
- package/dist/nimble.css +352 -24
- package/dist/nimble.min.css +1 -1
- package/package.json +10 -2
- package/src/_buttons.scss +71 -1
- package/src/_colors.scss +1 -5
- package/src/_details.scss +62 -2
- package/src/_dialog.scss +7 -1
- package/src/_document.scss +3 -2
- package/src/_forms.scss +126 -3
- package/src/_links.scss +2 -2
- package/src/_media.scss +1 -1
- package/src/_meter.scss +72 -0
- package/src/_progress.scss +88 -0
- package/src/_reset.scss +3 -1
- package/src/_select.scss +64 -0
- package/src/_typography.scss +13 -13
- package/src/nimble-base.scss +1 -2
- package/src/nimble-core.scss +30 -0
- package/src/nimble-meter.scss +8 -0
- package/src/nimble-progress.scss +8 -0
- package/src/nimble-select.scss +8 -0
- package/src/nimble.scss +6 -1
package/src/_buttons.scss
CHANGED
|
@@ -39,6 +39,16 @@
|
|
|
39
39
|
outline: none;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
// ----- Inline (buttons within flow text) -----
|
|
43
|
+
|
|
44
|
+
:where(button, [type="submit"], [type="reset"], [type="button"], [role="button"]).inline {
|
|
45
|
+
--_btn-padding-v: 0.05em;
|
|
46
|
+
--_btn-padding-h: 0.4em;
|
|
47
|
+
margin: 0.1em 0.15em;
|
|
48
|
+
font-size: 0.875em;
|
|
49
|
+
vertical-align: baseline;
|
|
50
|
+
}
|
|
51
|
+
|
|
42
52
|
// ----- Disabled -----
|
|
43
53
|
|
|
44
54
|
:where(button, [type="submit"], [type="reset"], [type="button"], [role="button"]):disabled {
|
|
@@ -53,15 +63,55 @@
|
|
|
53
63
|
|
|
54
64
|
:where([role="group"]) {
|
|
55
65
|
display: inline-flex;
|
|
66
|
+
margin-bottom: var(#{$prefix}spacing);
|
|
56
67
|
}
|
|
57
68
|
|
|
58
69
|
[role="group"] > * {
|
|
59
70
|
border-radius: 0;
|
|
60
71
|
margin: 0;
|
|
72
|
+
position: relative;
|
|
61
73
|
}
|
|
62
74
|
|
|
75
|
+
// Inset divider between adjacent same-type buttons. Different-type
|
|
76
|
+
// neighbours already have distinct backgrounds so no separator needed.
|
|
63
77
|
[role="group"] > * + * {
|
|
64
|
-
|
|
78
|
+
--_divider: ""; // shown by default (same-type needs separation)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
[role="group"] > * + *::before {
|
|
82
|
+
content: var(--_divider);
|
|
83
|
+
position: absolute;
|
|
84
|
+
inset-inline-start: 0;
|
|
85
|
+
top: 20%;
|
|
86
|
+
bottom: 20%;
|
|
87
|
+
width: 1px;
|
|
88
|
+
background: rgb(255 255 255 / 0.3);
|
|
89
|
+
pointer-events: none;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Hide divider between different-type button neighbours.
|
|
93
|
+
// primary ↔ secondary
|
|
94
|
+
[role="group"] > :not(.secondary):not(.outline) + .secondary,
|
|
95
|
+
[role="group"] > .secondary + :not(.secondary):not(.outline) {
|
|
96
|
+
--_divider: none;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// primary ↔ outline
|
|
100
|
+
[role="group"] > :not(.secondary):not(.outline) + .outline,
|
|
101
|
+
[role="group"] > .outline + :not(.secondary):not(.outline) {
|
|
102
|
+
--_divider: none;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// secondary ↔ outline
|
|
106
|
+
[role="group"] > .secondary + .outline,
|
|
107
|
+
[role="group"] > .outline + .secondary {
|
|
108
|
+
--_divider: none;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Hide divider after non-button elements (e.g. search input).
|
|
112
|
+
[role="group"] > input + *,
|
|
113
|
+
[role="group"] > select + * {
|
|
114
|
+
--_divider: none;
|
|
65
115
|
}
|
|
66
116
|
|
|
67
117
|
[role="group"] > :first-child {
|
|
@@ -74,6 +124,26 @@
|
|
|
74
124
|
border-end-end-radius: var(#{$prefix}radius);
|
|
75
125
|
}
|
|
76
126
|
|
|
127
|
+
// ----- Outline button groups -----
|
|
128
|
+
// When ALL children are .outline, collapse borders onto the group
|
|
129
|
+
// container so internal dividers don't double up with per-button borders.
|
|
130
|
+
// :has(> :not(.outline)) excludes mixed groups (e.g. primary + outline).
|
|
131
|
+
|
|
132
|
+
[role="group"]:has(.outline):not(:has(> :not(.outline))) {
|
|
133
|
+
border: 1px solid var(#{$prefix}primary);
|
|
134
|
+
border-radius: var(#{$prefix}radius);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
[role="group"]:has(.outline):not(:has(> :not(.outline))) > .outline {
|
|
138
|
+
border: none;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Outline dividers use primary color (white overlay is invisible
|
|
142
|
+
// against transparent background).
|
|
143
|
+
[role="group"] > .outline + .outline::before {
|
|
144
|
+
background: var(#{$prefix}primary);
|
|
145
|
+
}
|
|
146
|
+
|
|
77
147
|
// ----- Search groups (pill shape) -----
|
|
78
148
|
|
|
79
149
|
[role="search"] [role="group"] > :first-child {
|
package/src/_colors.scss
CHANGED
|
@@ -45,14 +45,10 @@
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
// ----- Text -----
|
|
48
|
-
#{$prefix}text
|
|
48
|
+
#{$prefix}text: #{_light-dark(
|
|
49
49
|
_oklch(0.280, 0.005, $surface-hue),
|
|
50
50
|
_oklch(0.860, 0.005, $surface-hue)
|
|
51
51
|
)};
|
|
52
|
-
#{$prefix}text-2: #{_light-dark(
|
|
53
|
-
_oklch(0.580, 0.005, $surface-hue),
|
|
54
|
-
_oklch(0.650, 0.005, $surface-hue)
|
|
55
|
-
)};
|
|
56
52
|
|
|
57
53
|
// ----- Border -----
|
|
58
54
|
#{$prefix}border: #{_light-dark(
|
package/src/_details.scss
CHANGED
|
@@ -12,18 +12,78 @@
|
|
|
12
12
|
:where(details) {
|
|
13
13
|
border: 1px solid var(#{$prefix}border);
|
|
14
14
|
border-radius: var(#{$prefix}radius);
|
|
15
|
-
padding
|
|
15
|
+
// No vertical padding — summary provides its own via the
|
|
16
|
+
// negative-margin/padding trick for vertical centering.
|
|
17
|
+
padding: 0 1em;
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
:where(summary) {
|
|
19
21
|
cursor: pointer;
|
|
20
22
|
font-weight: 600;
|
|
23
|
+
// Stretch summary across the horizontal padding area, then
|
|
24
|
+
// re-apply vertical + horizontal padding on itself. When
|
|
25
|
+
// collapsed the text is vertically centered with equal padding.
|
|
26
|
+
margin: 0 -1em;
|
|
27
|
+
padding: 0.75em 1em;
|
|
28
|
+
// Custom markers fix iOS Safari's tiny native disclosure triangle.
|
|
29
|
+
// Full-size Unicode triangles inherit font metrics and sit on the
|
|
30
|
+
// baseline like native markers.
|
|
31
|
+
list-style-type: '▶ ';
|
|
21
32
|
}
|
|
22
33
|
|
|
23
34
|
:where(details[open] > summary) {
|
|
24
|
-
|
|
35
|
+
list-style-type: '▼ ';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// When open, restore vertical padding for content spacing.
|
|
39
|
+
:where(details[open]) {
|
|
40
|
+
padding-bottom: 0.75em;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Kill last-child bottom margin so it doesn't stack with
|
|
44
|
+
// details[open] padding-bottom. Descendant selector (not >)
|
|
45
|
+
// reaches inside ::details-content which wraps the content.
|
|
46
|
+
// No :where() — needs specificity to override typography margins.
|
|
47
|
+
details :last-child {
|
|
48
|
+
margin-bottom: 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Summary bottom padding provides the gap to content when open.
|
|
52
|
+
// No extra margin-bottom or ::details-content padding needed.
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Animate content on open/close (progressive enhancement)
|
|
57
|
+
// Outside @layer — ::details-content needs real specificity to override UA styles
|
|
58
|
+
// Gate on ::details-content support (Safari 18.4+, Chrome 131+)
|
|
59
|
+
@supports selector(details::details-content) {
|
|
60
|
+
details::details-content {
|
|
61
|
+
transition: opacity 0.3s ease,
|
|
62
|
+
content-visibility 0.3s ease allow-discrete;
|
|
63
|
+
opacity: 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
details[open]::details-content {
|
|
67
|
+
opacity: 1;
|
|
25
68
|
}
|
|
26
69
|
|
|
70
|
+
// Height animation where interpolate-size is supported (Chrome 129+)
|
|
71
|
+
@supports (interpolate-size: allow-keywords) {
|
|
72
|
+
details {
|
|
73
|
+
interpolate-size: allow-keywords;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
details::details-content {
|
|
77
|
+
transition: height 0.3s ease, opacity 0.3s ease,
|
|
78
|
+
content-visibility 0.3s ease allow-discrete;
|
|
79
|
+
height: 0;
|
|
80
|
+
overflow: clip;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
details[open]::details-content {
|
|
84
|
+
height: auto;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
27
87
|
}
|
|
28
88
|
|
|
29
89
|
}
|
package/src/_dialog.scss
CHANGED
|
@@ -17,8 +17,14 @@
|
|
|
17
17
|
padding: var(#{$prefix}spacing);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
dialog::backdrop {
|
|
21
21
|
background: rgb(0 0 0 / 0.5);
|
|
22
|
+
backdrop-filter: blur(4px);
|
|
23
|
+
animation: nc-backdrop-in 0.2s ease;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@keyframes nc-backdrop-in {
|
|
27
|
+
from { opacity: 0; }
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
}
|
package/src/_document.scss
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
font-family: var(#{$prefix}font-sans);
|
|
13
13
|
font-size: 100%; // = 16px in most browsers
|
|
14
14
|
line-height: 1.5;
|
|
15
|
-
color: var(#{$prefix}text
|
|
15
|
+
color: var(#{$prefix}text);
|
|
16
16
|
background-color: var(#{$prefix}surface-1);
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -30,12 +30,13 @@
|
|
|
30
30
|
|
|
31
31
|
body > * {
|
|
32
32
|
grid-column: 2;
|
|
33
|
+
min-width: 0; // Allow grid children to shrink below intrinsic content width
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
// Selection styling using primary accent
|
|
36
37
|
::selection {
|
|
37
38
|
background-color: var(#{$prefix}primary-focus);
|
|
38
|
-
color: var(#{$prefix}text
|
|
39
|
+
color: var(#{$prefix}text);
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
}
|
package/src/_forms.scss
CHANGED
|
@@ -9,23 +9,26 @@
|
|
|
9
9
|
|
|
10
10
|
// ----- Text inputs, select, textarea -----
|
|
11
11
|
|
|
12
|
-
:where(input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"]),
|
|
12
|
+
:where(input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [type="submit"], [type="button"], [type="reset"]),
|
|
13
13
|
select, textarea) {
|
|
14
14
|
--_input-bg: color-mix(in oklch, var(#{$prefix}surface-1), var(#{$prefix}surface-2) 20%);
|
|
15
15
|
|
|
16
16
|
padding: 0.5em 0.75em;
|
|
17
|
+
min-height: calc(1em * 1.5 + 1em + 2px); // line-height + vertical padding + border
|
|
17
18
|
background-color: var(--_input-bg);
|
|
18
19
|
border: 1px solid var(#{$prefix}border);
|
|
19
20
|
border-radius: var(#{$prefix}radius);
|
|
20
|
-
color: var(#{$prefix}text
|
|
21
|
+
color: var(#{$prefix}text);
|
|
21
22
|
font: inherit;
|
|
23
|
+
font-size: 1rem; // >=16px prevents iOS Safari auto-zoom on focus
|
|
22
24
|
transition: border-color 0.2s, box-shadow 0.2s;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
// Make text inputs and select full-width by default (PicoCSS pattern)
|
|
26
|
-
:where(input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [type="submit"], [type="button"], [type="reset"]),
|
|
28
|
+
:where(input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [type="submit"], [type="button"], [type="reset"], [type="date"], [type="month"], [type="week"], [type="time"], [type="datetime-local"]),
|
|
27
29
|
select, textarea) {
|
|
28
30
|
width: 100%;
|
|
31
|
+
margin-bottom: var(#{$prefix}spacing);
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
// ----- Focus -----
|
|
@@ -36,6 +39,16 @@
|
|
|
36
39
|
outline: none;
|
|
37
40
|
}
|
|
38
41
|
|
|
42
|
+
// When a validation message <small> immediately follows an input,
|
|
43
|
+
// pull it up tight against the field and let it carry the spacing instead.
|
|
44
|
+
:where(input, select, textarea) + :where(small) {
|
|
45
|
+
display: block;
|
|
46
|
+
margin-top: calc(var(#{$prefix}spacing) * -0.75); // pull up under the input
|
|
47
|
+
margin-bottom: var(#{$prefix}spacing);
|
|
48
|
+
font-size: 0.875em;
|
|
49
|
+
color: color-mix(in oklch, var(#{$prefix}text), transparent 40%);
|
|
50
|
+
}
|
|
51
|
+
|
|
39
52
|
// ----- Validation states (aria-invalid) -----
|
|
40
53
|
|
|
41
54
|
:where(input, select, textarea)[aria-invalid="false"] {
|
|
@@ -46,6 +59,15 @@
|
|
|
46
59
|
border-color: var(#{$prefix}invalid);
|
|
47
60
|
}
|
|
48
61
|
|
|
62
|
+
// Color validation messages to match the field state
|
|
63
|
+
:where(input, select, textarea)[aria-invalid="false"] + :where(small) {
|
|
64
|
+
color: var(#{$prefix}valid);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
:where(input, select, textarea)[aria-invalid="true"] + :where(small) {
|
|
68
|
+
color: var(#{$prefix}invalid);
|
|
69
|
+
}
|
|
70
|
+
|
|
49
71
|
// ----- Labels -----
|
|
50
72
|
|
|
51
73
|
:where(label) {
|
|
@@ -63,6 +85,8 @@
|
|
|
63
85
|
border: 1px solid var(#{$prefix}border);
|
|
64
86
|
border-radius: var(#{$prefix}radius);
|
|
65
87
|
padding: var(#{$prefix}spacing);
|
|
88
|
+
min-width: 0; // Override UA min-content default — prevents overflow on narrow viewports
|
|
89
|
+
max-width: 100%;
|
|
66
90
|
}
|
|
67
91
|
|
|
68
92
|
:where(legend) {
|
|
@@ -75,6 +99,22 @@
|
|
|
75
99
|
|
|
76
100
|
:where([type="checkbox"], [type="radio"]) {
|
|
77
101
|
accent-color: var(#{$prefix}primary);
|
|
102
|
+
width: 1.125em;
|
|
103
|
+
height: 1.125em;
|
|
104
|
+
margin: 0; // Remove browser default margin so flex labels align flush left
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
:where(label:has([type="checkbox"], [type="radio"])) {
|
|
108
|
+
display: flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
gap: 0.35em;
|
|
111
|
+
margin-bottom: var(#{$prefix}spacing);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Radio options in a group sit close together; only the last one
|
|
115
|
+
// carries the full field-gap to the next element.
|
|
116
|
+
:where(label:has([type="radio"])) {
|
|
117
|
+
margin-bottom: 0.35em;
|
|
78
118
|
}
|
|
79
119
|
|
|
80
120
|
// ----- Range -----
|
|
@@ -84,10 +124,72 @@
|
|
|
84
124
|
width: 100%;
|
|
85
125
|
}
|
|
86
126
|
|
|
127
|
+
// ----- Datalist-connected inputs -----
|
|
128
|
+
// Keep natural width so the dropdown arrow stays near the text,
|
|
129
|
+
// similar to date/time inputs preserving native widget UX.
|
|
130
|
+
|
|
131
|
+
:where(input[list]) {
|
|
132
|
+
width: auto;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ----- File -----
|
|
136
|
+
|
|
137
|
+
:where([type="file"]) {
|
|
138
|
+
color: var(#{$prefix}text);
|
|
139
|
+
font: inherit;
|
|
140
|
+
cursor: pointer;
|
|
141
|
+
max-width: 100%; // Prevent native file input from overflowing container (iOS Safari)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
:where([type="file"])::file-selector-button {
|
|
145
|
+
padding: 0.5em 1em;
|
|
146
|
+
margin-right: 0.75em;
|
|
147
|
+
margin-inline-end: 0.75em;
|
|
148
|
+
background-color: var(#{$prefix}primary);
|
|
149
|
+
color: var(#{$prefix}primary-contrast);
|
|
150
|
+
border: 1px solid var(#{$prefix}primary);
|
|
151
|
+
border-radius: var(#{$prefix}radius);
|
|
152
|
+
font: inherit;
|
|
153
|
+
cursor: pointer;
|
|
154
|
+
transition: background-color 0.2s, border-color 0.2s;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
:where([type="file"])::file-selector-button:hover {
|
|
158
|
+
background-color: var(#{$prefix}primary-hover);
|
|
159
|
+
border-color: var(#{$prefix}primary-hover);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ----- Date/time inputs -----
|
|
163
|
+
// Natural width so picker icon stays near content (excluded from full-width rule above).
|
|
164
|
+
// appearance: none is applied outside @layer (see below) to fix iOS Safari sizing.
|
|
165
|
+
:where([type="date"], [type="month"], [type="week"], [type="time"], [type="datetime-local"]) {
|
|
166
|
+
min-width: 10em; // Prevent collapse when empty (e.g. time with no value)
|
|
167
|
+
margin-bottom: var(#{$prefix}spacing);
|
|
168
|
+
}
|
|
169
|
+
|
|
87
170
|
// ----- Color -----
|
|
88
171
|
|
|
89
172
|
:where([type="color"]) {
|
|
173
|
+
--_color-size: calc(1em * 1.5 + 1em + 2px); // Match text input height
|
|
174
|
+
|
|
175
|
+
--_color-pad: 0.25em;
|
|
176
|
+
|
|
177
|
+
height: var(--_color-size);
|
|
178
|
+
width: calc((var(--_color-size) - 2 * var(--_color-pad)) * 1.618 + 2 * var(--_color-pad)); // Golden ratio inner swatch
|
|
179
|
+
padding: var(--_color-pad);
|
|
180
|
+
background-color: color-mix(in oklch, var(#{$prefix}surface-1), var(#{$prefix}surface-2) 20%);
|
|
181
|
+
border: 1px solid var(#{$prefix}border);
|
|
182
|
+
border-radius: var(#{$prefix}radius);
|
|
90
183
|
cursor: pointer;
|
|
184
|
+
|
|
185
|
+
&::-webkit-color-swatch-wrapper {
|
|
186
|
+
padding: 0;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
&::-webkit-color-swatch {
|
|
190
|
+
border: none;
|
|
191
|
+
border-radius: calc(var(#{$prefix}radius) * 0.5);
|
|
192
|
+
}
|
|
91
193
|
}
|
|
92
194
|
|
|
93
195
|
// ----- Switch (checkbox with role="switch") -----
|
|
@@ -95,6 +197,12 @@
|
|
|
95
197
|
@if $enable-switch {
|
|
96
198
|
// Minimal switch styling — relies on native checkbox with role="switch"
|
|
97
199
|
// Browsers with :has() support get enhanced label alignment
|
|
200
|
+
:where(label:has([type="checkbox"][role="switch"])) {
|
|
201
|
+
display: inline-flex;
|
|
202
|
+
align-items: center;
|
|
203
|
+
gap: 0.5em;
|
|
204
|
+
}
|
|
205
|
+
|
|
98
206
|
:where([type="checkbox"][role="switch"]) {
|
|
99
207
|
appearance: none;
|
|
100
208
|
width: 2.5em;
|
|
@@ -103,6 +211,8 @@
|
|
|
103
211
|
background-color: var(#{$prefix}border);
|
|
104
212
|
position: relative;
|
|
105
213
|
cursor: pointer;
|
|
214
|
+
flex-shrink: 0;
|
|
215
|
+
margin: 0; // Remove browser default margin so flex labels align flush left
|
|
106
216
|
transition: background-color 0.2s;
|
|
107
217
|
}
|
|
108
218
|
|
|
@@ -128,3 +238,16 @@
|
|
|
128
238
|
}
|
|
129
239
|
|
|
130
240
|
}
|
|
241
|
+
|
|
242
|
+
// iOS Safari ignores author box-model styles on native date/time inputs.
|
|
243
|
+
// appearance: none unlocks sizing control while preserving the native picker
|
|
244
|
+
// (only the decorative icon is removed on iOS; Chrome/desktop keeps its icons).
|
|
245
|
+
// Placed outside @layer with real selectors to beat UA specificity.
|
|
246
|
+
[type="date"],
|
|
247
|
+
[type="month"],
|
|
248
|
+
[type="week"],
|
|
249
|
+
[type="time"],
|
|
250
|
+
[type="datetime-local"] {
|
|
251
|
+
-webkit-appearance: none;
|
|
252
|
+
appearance: none;
|
|
253
|
+
}
|
package/src/_links.scss
CHANGED
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
:where(a:not([role="button"])):visited {
|
|
20
|
-
color: #{string.unquote('color-mix(in oklch, var(#{$prefix}primary) 40%, oklch(0.
|
|
21
|
-
text-decoration-color: #{string.unquote('color-mix(in oklch, var(#{$prefix}primary) 40%, oklch(0.
|
|
20
|
+
color: #{string.unquote('color-mix(in oklch, var(#{$prefix}primary) 40%, oklch(0.38 0.15 310))')};
|
|
21
|
+
text-decoration-color: #{string.unquote('color-mix(in oklch, var(#{$prefix}primary) 40%, oklch(0.38 0.15 310) 30%)')};
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
:where(a:not([role="button"])):hover {
|
package/src/_media.scss
CHANGED
package/src/_meter.scss
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// nimble.css — Meter
|
|
3
|
+
// Optional: styled <meter> with cross-browser semantic state colors
|
|
4
|
+
// ==========================================================================
|
|
5
|
+
|
|
6
|
+
@use 'config' as *;
|
|
7
|
+
|
|
8
|
+
@layer nimble.base {
|
|
9
|
+
|
|
10
|
+
// Same treatment as progress: appearance: none + pseudo-element rebuild.
|
|
11
|
+
// Meter has three semantic states (optimum / suboptimum / sub-sub-optimum)
|
|
12
|
+
// which we map to --nc-valid (green), --nc-primary (default), --nc-invalid (red).
|
|
13
|
+
|
|
14
|
+
:where(meter) {
|
|
15
|
+
-webkit-appearance: none;
|
|
16
|
+
-moz-appearance: none;
|
|
17
|
+
appearance: none;
|
|
18
|
+
width: 100%;
|
|
19
|
+
height: 0.5rem;
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
border: 0;
|
|
22
|
+
border-radius: var(#{$prefix}radius);
|
|
23
|
+
background-color: var(#{$prefix}surface-3);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// WebKit: track (outer bar)
|
|
27
|
+
:where(meter)::-webkit-meter-inner-element {
|
|
28
|
+
// Wrapper element — reset grid layout that some UAs impose
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
:where(meter)::-webkit-meter-bar {
|
|
32
|
+
border-radius: var(#{$prefix}radius);
|
|
33
|
+
background-color: var(#{$prefix}surface-3);
|
|
34
|
+
border: 0;
|
|
35
|
+
height: 0.5rem;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// WebKit: value bars for each semantic state
|
|
39
|
+
:where(meter)::-webkit-meter-optimum-value {
|
|
40
|
+
background-color: var(#{$prefix}valid);
|
|
41
|
+
border-radius: var(#{$prefix}radius);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
:where(meter)::-webkit-meter-suboptimum-value {
|
|
45
|
+
background-color: var(#{$prefix}primary);
|
|
46
|
+
border-radius: var(#{$prefix}radius);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
:where(meter)::-webkit-meter-even-less-good-value {
|
|
50
|
+
background-color: var(#{$prefix}invalid);
|
|
51
|
+
border-radius: var(#{$prefix}radius);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Firefox: single bar pseudo-element + pseudo-classes for state
|
|
55
|
+
:where(meter)::-moz-meter-bar {
|
|
56
|
+
background-color: var(#{$prefix}primary);
|
|
57
|
+
border-radius: var(#{$prefix}radius);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
:where(meter):-moz-meter-optimum::-moz-meter-bar {
|
|
61
|
+
background-color: var(#{$prefix}valid);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
:where(meter):-moz-meter-sub-optimum::-moz-meter-bar {
|
|
65
|
+
background-color: var(#{$prefix}primary);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
:where(meter):-moz-meter-sub-sub-optimum::-moz-meter-bar {
|
|
69
|
+
background-color: var(#{$prefix}invalid);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// nimble.css — Progress (add-on)
|
|
3
|
+
// Standalone <progress> styling for use with nimble-base.
|
|
4
|
+
// Not needed with nimble.css (progress is already included). Use with nimble-core.css.
|
|
5
|
+
// ==========================================================================
|
|
6
|
+
|
|
7
|
+
@use 'config' as *;
|
|
8
|
+
|
|
9
|
+
@layer nimble.base {
|
|
10
|
+
|
|
11
|
+
:where(progress) {
|
|
12
|
+
-webkit-appearance: none;
|
|
13
|
+
appearance: none;
|
|
14
|
+
position: relative;
|
|
15
|
+
width: 100%;
|
|
16
|
+
height: 0.5rem;
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
border: 0;
|
|
19
|
+
border-radius: var(#{$prefix}radius);
|
|
20
|
+
background-color: var(#{$prefix}surface-3);
|
|
21
|
+
color: var(#{$prefix}primary); // Firefox uses color for the bar
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
:where(progress)::-webkit-progress-bar {
|
|
25
|
+
border-radius: var(#{$prefix}radius);
|
|
26
|
+
background-color: var(#{$prefix}surface-3);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
:where(progress)::-webkit-progress-value {
|
|
30
|
+
background-color: var(#{$prefix}primary);
|
|
31
|
+
border-radius: var(#{$prefix}radius);
|
|
32
|
+
transition: inline-size 0.3s ease;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
:where(progress)::-moz-progress-bar {
|
|
36
|
+
background-color: var(#{$prefix}primary);
|
|
37
|
+
border-radius: var(#{$prefix}radius);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Indeterminate: evenly-spaced blue bands travel continuously rightward.
|
|
41
|
+
// Gradient is 200% wide with two identical 10%-wide bands at 15% and 65%.
|
|
42
|
+
// They're 50% apart — exactly one visible width (100/200 = 50% of gradient).
|
|
43
|
+
// Animating position by -200% = one full gradient width → seamless loop.
|
|
44
|
+
:where(progress):not([value]) {
|
|
45
|
+
--nc-progress-track:
|
|
46
|
+
linear-gradient(to right,
|
|
47
|
+
var(#{$prefix}surface-3) 0%,
|
|
48
|
+
var(#{$prefix}primary) 25%,
|
|
49
|
+
var(#{$prefix}primary) 25%,
|
|
50
|
+
var(#{$prefix}surface-3) 50%,
|
|
51
|
+
var(#{$prefix}surface-3) 50%,
|
|
52
|
+
var(#{$prefix}primary) 75%,
|
|
53
|
+
var(#{$prefix}primary) 75%,
|
|
54
|
+
var(#{$prefix}surface-3) 100%);
|
|
55
|
+
--nc-progress-track-size: 200% 100%;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
59
|
+
@supports selector(progress::after) {
|
|
60
|
+
:where(progress):not([value])::after {
|
|
61
|
+
content: "";
|
|
62
|
+
position: absolute;
|
|
63
|
+
inset: 0;
|
|
64
|
+
background: var(--nc-progress-track);
|
|
65
|
+
background-size: var(--nc-progress-track-size);
|
|
66
|
+
animation: nc-progress-indeterminate 12s linear infinite;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
:where(progress):not([value])::-webkit-progress-bar {
|
|
71
|
+
background: var(--nc-progress-track);
|
|
72
|
+
background-size: var(--nc-progress-track-size);
|
|
73
|
+
animation: nc-progress-indeterminate 12s linear infinite;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
:where(progress):not([value])::-moz-progress-bar {
|
|
77
|
+
background: var(--nc-progress-track);
|
|
78
|
+
background-size: var(--nc-progress-track-size);
|
|
79
|
+
animation: nc-progress-indeterminate 12s linear infinite;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@keyframes nc-progress-indeterminate {
|
|
84
|
+
from { background-position: 0% 0%; }
|
|
85
|
+
to { background-position: -200% 0%; }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
}
|
package/src/_reset.scss
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
// --- Document ---
|
|
12
12
|
|
|
13
|
-
:where(
|
|
13
|
+
:where(*:not(progress)),
|
|
14
14
|
:where(*::before),
|
|
15
15
|
:where(*::after) {
|
|
16
16
|
box-sizing: border-box;
|
|
@@ -156,6 +156,7 @@
|
|
|
156
156
|
// Remove delay from tapping on clickable elements
|
|
157
157
|
:where(a, area, button, input, label, select, summary, textarea, [tabindex]) {
|
|
158
158
|
touch-action: manipulation;
|
|
159
|
+
-webkit-tap-highlight-color: transparent;
|
|
159
160
|
}
|
|
160
161
|
|
|
161
162
|
// Change the cursor for busy elements
|
|
@@ -181,3 +182,4 @@
|
|
|
181
182
|
}
|
|
182
183
|
|
|
183
184
|
}
|
|
185
|
+
|