@allxsmith/bestax-bulma 5.54.0 → 5.55.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/dist/bestax.css +1 -1
- package/dist/bestax.css.map +1 -1
- package/dist/esm/components/Command.js +22 -22
- package/dist/esm/components/Command.js.map +1 -1
- package/dist/esm/components/DataTable.js +215 -0
- package/dist/esm/components/DataTable.js.map +1 -0
- package/dist/esm/components/useDataTable.js +482 -0
- package/dist/esm/components/useDataTable.js.map +1 -0
- package/dist/esm/elements/ColorSwatch.js +49 -0
- package/dist/esm/elements/ColorSwatch.js.map +1 -0
- package/dist/esm/elements/RingProgress.js +3 -3
- package/dist/esm/elements/Td.js +4 -2
- package/dist/esm/elements/Td.js.map +1 -1
- package/dist/esm/elements/Th.js +13 -5
- package/dist/esm/elements/Th.js.map +1 -1
- package/dist/esm/elements/Tr.js.map +1 -1
- package/dist/esm/form/ColorPicker.js +540 -0
- package/dist/esm/form/ColorPicker.js.map +1 -0
- package/dist/esm/form/Combobox.js +18 -18
- package/dist/esm/form/Combobox.js.map +1 -1
- package/dist/esm/form/Dropzone.js +524 -0
- package/dist/esm/form/Dropzone.js.map +1 -0
- package/dist/esm/form/File.js.map +1 -1
- package/dist/esm/form/_colorInternals/colorMath.js +292 -0
- package/dist/esm/form/_colorInternals/colorMath.js.map +1 -0
- package/dist/esm/form/_colorInternals/pickerState.js +160 -0
- package/dist/esm/form/_colorInternals/pickerState.js.map +1 -0
- package/dist/esm/helpers/statusRegion.js +3 -3
- package/dist/esm/helpers/statusRegion.js.map +1 -1
- package/dist/esm/helpers/useFocusTrap.js +2 -2
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +2986 -796
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +5 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/types/components/DataTable.d.ts +120 -0
- package/dist/types/components/useDataTable.d.ts +445 -0
- package/dist/types/elements/ColorSwatch.d.ts +54 -0
- package/dist/types/elements/Td.d.ts +9 -1
- package/dist/types/elements/Th.d.ts +14 -2
- package/dist/types/elements/Tr.d.ts +10 -1
- package/dist/types/form/ColorPicker.d.ts +266 -0
- package/dist/types/form/Dropzone.d.ts +138 -0
- package/dist/types/form/File.d.ts +2 -0
- package/dist/types/form/_colorInternals/colorMath.d.ts +63 -0
- package/dist/types/form/_colorInternals/pickerState.d.ts +62 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types-cjs/components/DataTable.d.ts +120 -0
- package/dist/types-cjs/components/useDataTable.d.ts +445 -0
- package/dist/types-cjs/elements/ColorSwatch.d.ts +54 -0
- package/dist/types-cjs/elements/Td.d.ts +9 -1
- package/dist/types-cjs/elements/Th.d.ts +14 -2
- package/dist/types-cjs/elements/Tr.d.ts +10 -1
- package/dist/types-cjs/form/ColorPicker.d.ts +266 -0
- package/dist/types-cjs/form/Dropzone.d.ts +138 -0
- package/dist/types-cjs/form/File.d.ts +2 -0
- package/dist/types-cjs/form/_colorInternals/colorMath.d.ts +63 -0
- package/dist/types-cjs/form/_colorInternals/pickerState.d.ts +62 -0
- package/dist/types-cjs/index.d.ts +4 -0
- package/dist/versions/bestax-no-dark-mode.css +1 -1
- package/dist/versions/bestax-no-dark-mode.css.map +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
- package/dist/versions/bestax-no-helpers.css +1 -1
- package/dist/versions/bestax-no-helpers.css.map +1 -1
- package/dist/versions/bestax-prefixed.css +1 -1
- package/dist/versions/bestax-prefixed.css.map +1 -1
- package/package.json +1 -1
- package/src/scss/components/_datatable.scss +152 -0
- package/src/scss/components/_index.scss +1 -0
- package/src/scss/elements/_colorswatch.scss +100 -0
- package/src/scss/elements/_index.scss +1 -0
- package/src/scss/form/_checkbox.scss +53 -0
- package/src/scss/form/_colorpicker.scss +354 -0
- package/src/scss/form/_dropzone.scss +233 -0
- package/src/scss/form/_file.scss +29 -1
- package/src/scss/form/_index.scss +2 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// Bestax Extras - DataTable Styles
|
|
2
|
+
// DataTable renders Bulma's own table, checkboxes and pager, which Bulma and
|
|
3
|
+
// the Checkbox partial style. This adds what Bulma has no class for: the
|
|
4
|
+
// toolbar above the table, the button a sortable header holds, and the
|
|
5
|
+
// indicator that shows which way it sorts.
|
|
6
|
+
//
|
|
7
|
+
// The sort button is styled on its own class rather than inside
|
|
8
|
+
// `.data-table`, so a table built from `useDataTable`'s props, with no
|
|
9
|
+
// DataTable around it, gets the same button. Its variables are declared on
|
|
10
|
+
// the button for the same reason.
|
|
11
|
+
|
|
12
|
+
@use 'bulma/sass/utilities/initial-variables' as iv;
|
|
13
|
+
@use 'bulma/sass/utilities/css-variables' as cv;
|
|
14
|
+
@use '../mixins' as *;
|
|
15
|
+
|
|
16
|
+
// Between the toolbar's items, and under the toolbar.
|
|
17
|
+
$data-table-gap: 0.75rem !default;
|
|
18
|
+
// Between a header's text and its indicator.
|
|
19
|
+
$data-table-sort-gap: 0.375em !default;
|
|
20
|
+
$data-table-sort-indicator-size: 0.75em !default;
|
|
21
|
+
// How strongly an unsorted column shows that it sorts.
|
|
22
|
+
$data-table-sort-unsorted-opacity: 0.35 !default;
|
|
23
|
+
|
|
24
|
+
// The indicator's shapes, used as masks so they're painted in the text's
|
|
25
|
+
// color, or a system color in forced colors. Private, since they're shapes
|
|
26
|
+
// rather than themable values; the fill only marks what each mask keeps.
|
|
27
|
+
// An unsorted column shows both triangles, a sorted one the one pointing
|
|
28
|
+
// the way it sorts, up for ascending as the APG example draws it.
|
|
29
|
+
$-unsorted: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 1.5 12.5 7h-9zM8 14.5 3.5 9h9z'/%3E%3C/svg%3E");
|
|
30
|
+
$-ascending: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 3.5 13.5 11h-11z'/%3E%3C/svg%3E");
|
|
31
|
+
$-descending: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 12.5 2.5 5h11z'/%3E%3C/svg%3E");
|
|
32
|
+
|
|
33
|
+
.#{iv.$class-prefix}data-table {
|
|
34
|
+
@include cv.register-vars(
|
|
35
|
+
(
|
|
36
|
+
'data-table-gap': #{$data-table-gap},
|
|
37
|
+
)
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.#{iv.$class-prefix}data-table-sort {
|
|
42
|
+
@include cv.register-vars(
|
|
43
|
+
(
|
|
44
|
+
'data-table-sort-gap': #{$data-table-sort-gap},
|
|
45
|
+
'data-table-sort-indicator-size': #{$data-table-sort-indicator-size},
|
|
46
|
+
'data-table-sort-unsorted-opacity': #{$data-table-sort-unsorted-opacity},
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// A block, spaced as Bulma spaces its table and its other blocks.
|
|
52
|
+
.#{iv.$class-prefix}data-table:not(:last-child) {
|
|
53
|
+
margin-block-end: cv.getVar('block-spacing');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// The caption names the table from the start of the line, over the header
|
|
57
|
+
// cells it names, rather than centered over them as browsers place it.
|
|
58
|
+
.#{iv.$class-prefix}data-table .#{iv.$class-prefix}table > caption {
|
|
59
|
+
padding-block-end: cv.getVar('data-table-gap');
|
|
60
|
+
text-align: start;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// The toolbar: the search field at the start, anything else at the end, and
|
|
64
|
+
// the two stacked when the line runs out of room.
|
|
65
|
+
.#{iv.$class-prefix}data-table-toolbar {
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-wrap: wrap;
|
|
68
|
+
align-items: flex-end;
|
|
69
|
+
gap: cv.getVar('data-table-gap');
|
|
70
|
+
margin-block-end: cv.getVar('data-table-gap');
|
|
71
|
+
|
|
72
|
+
> .#{iv.$class-prefix}field {
|
|
73
|
+
margin-block-end: 0;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.#{iv.$class-prefix}data-table-actions {
|
|
78
|
+
display: flex;
|
|
79
|
+
flex-wrap: wrap;
|
|
80
|
+
align-items: center;
|
|
81
|
+
gap: cv.getVar('data-table-gap');
|
|
82
|
+
margin-inline-start: auto;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// A sortable header's button reads as the header's own text, with the
|
|
86
|
+
// indicator after it.
|
|
87
|
+
.#{iv.$class-prefix}data-table-sort {
|
|
88
|
+
@include extras-button-reset;
|
|
89
|
+
display: inline-flex;
|
|
90
|
+
align-items: center;
|
|
91
|
+
gap: cv.getVar('data-table-sort-gap');
|
|
92
|
+
font-weight: inherit;
|
|
93
|
+
line-height: inherit;
|
|
94
|
+
text-align: inherit;
|
|
95
|
+
|
|
96
|
+
&::after {
|
|
97
|
+
content: '';
|
|
98
|
+
flex-shrink: 0;
|
|
99
|
+
width: cv.getVar('data-table-sort-indicator-size');
|
|
100
|
+
height: cv.getVar('data-table-sort-indicator-size');
|
|
101
|
+
background-color: currentColor;
|
|
102
|
+
opacity: cv.getVar('data-table-sort-unsorted-opacity');
|
|
103
|
+
-webkit-mask-image: $-unsorted;
|
|
104
|
+
-webkit-mask-size: contain;
|
|
105
|
+
-webkit-mask-repeat: no-repeat;
|
|
106
|
+
-webkit-mask-position: center;
|
|
107
|
+
mask-image: $-unsorted;
|
|
108
|
+
mask-size: contain;
|
|
109
|
+
mask-repeat: no-repeat;
|
|
110
|
+
mask-position: center;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
&:hover::after {
|
|
114
|
+
opacity: 1;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
&:focus-visible {
|
|
118
|
+
@include extras-focus-outline;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// The sorted header says which way in `aria-sort`, so the indicator reads it
|
|
123
|
+
// from there, and markup built from `useDataTable`'s props shows it too.
|
|
124
|
+
th[aria-sort='ascending'] > .#{iv.$class-prefix}data-table-sort::after {
|
|
125
|
+
opacity: 1;
|
|
126
|
+
-webkit-mask-image: $-ascending;
|
|
127
|
+
mask-image: $-ascending;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
th[aria-sort='descending'] > .#{iv.$class-prefix}data-table-sort::after {
|
|
131
|
+
opacity: 1;
|
|
132
|
+
-webkit-mask-image: $-descending;
|
|
133
|
+
mask-image: $-descending;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Forced colors replaces a background color that isn't a system one, which
|
|
137
|
+
// would take the indicator's paint away. The mask is left alone, so the
|
|
138
|
+
// shape stays.
|
|
139
|
+
@media (forced-colors: active) {
|
|
140
|
+
.#{iv.$class-prefix}data-table-sort {
|
|
141
|
+
// A faint indicator would fall short of the contrast forced colors is
|
|
142
|
+
// for. The two shapes, one triangle or both, still tell the states apart.
|
|
143
|
+
&::after {
|
|
144
|
+
background-color: ButtonText;
|
|
145
|
+
opacity: 1;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
&:focus-visible {
|
|
149
|
+
outline-color: Highlight;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Bestax Extras - ColorSwatch Styles
|
|
2
|
+
// A color shown as a small chip. Bulma has no swatch.
|
|
3
|
+
//
|
|
4
|
+
// The component sets the color as `--color-swatch-color`, which is painted
|
|
5
|
+
// as a gradient over a checkerboard, so a see-through color shows the
|
|
6
|
+
// checks through it. Forced colors would turn both into the page's
|
|
7
|
+
// background, so the swatch opts out of it and takes an edge in the
|
|
8
|
+
// system's text color instead.
|
|
9
|
+
|
|
10
|
+
@use 'bulma/sass/utilities/initial-variables' as iv;
|
|
11
|
+
@use 'bulma/sass/utilities/css-variables' as cv;
|
|
12
|
+
|
|
13
|
+
$color-swatch-size: 1.5rem !default;
|
|
14
|
+
$color-swatch-size-small: 1rem !default;
|
|
15
|
+
$color-swatch-size-medium: 2rem !default;
|
|
16
|
+
$color-swatch-size-large: 3rem !default;
|
|
17
|
+
$color-swatch-radius: cv.getVar('radius') !default;
|
|
18
|
+
// A faint edge in the text color, so a white swatch shows on a white page
|
|
19
|
+
// and a black one on a dark page.
|
|
20
|
+
$color-swatch-edge-color: hsla(
|
|
21
|
+
cv.getVar('text-h'),
|
|
22
|
+
cv.getVar('text-s'),
|
|
23
|
+
cv.getVar('text-l'),
|
|
24
|
+
0.2
|
|
25
|
+
) !default;
|
|
26
|
+
// The checkerboard behind a see-through color, from scheme colors so it
|
|
27
|
+
// follows dark mode.
|
|
28
|
+
$color-swatch-checker-color: cv.getVar('border') !default;
|
|
29
|
+
$color-swatch-checker-background: cv.getVar('scheme-main') !default;
|
|
30
|
+
$color-swatch-checker-size: 0.5rem !default;
|
|
31
|
+
|
|
32
|
+
.#{iv.$class-prefix}color-swatch {
|
|
33
|
+
@include cv.register-vars(
|
|
34
|
+
(
|
|
35
|
+
'color-swatch-size': #{$color-swatch-size},
|
|
36
|
+
'color-swatch-radius': #{$color-swatch-radius},
|
|
37
|
+
'color-swatch-edge-color': #{$color-swatch-edge-color},
|
|
38
|
+
'color-swatch-checker-color': #{$color-swatch-checker-color},
|
|
39
|
+
'color-swatch-checker-background': #{$color-swatch-checker-background},
|
|
40
|
+
'color-swatch-checker-size': #{$color-swatch-checker-size},
|
|
41
|
+
)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@each $size,
|
|
46
|
+
$value
|
|
47
|
+
in (
|
|
48
|
+
'small': $color-swatch-size-small,
|
|
49
|
+
'medium': $color-swatch-size-medium,
|
|
50
|
+
'large': $color-swatch-size-large
|
|
51
|
+
)
|
|
52
|
+
{
|
|
53
|
+
.#{iv.$class-prefix}color-swatch.#{iv.$class-prefix}is-#{$size} {
|
|
54
|
+
@include cv.register-vars(
|
|
55
|
+
(
|
|
56
|
+
'color-swatch-size': #{$value},
|
|
57
|
+
)
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.#{iv.$class-prefix}color-swatch {
|
|
63
|
+
display: inline-flex;
|
|
64
|
+
flex-shrink: 0;
|
|
65
|
+
align-items: center;
|
|
66
|
+
justify-content: center;
|
|
67
|
+
inline-size: cv.getVar('color-swatch-size');
|
|
68
|
+
block-size: cv.getVar('color-swatch-size');
|
|
69
|
+
border-radius: cv.getVar('color-swatch-radius');
|
|
70
|
+
vertical-align: middle;
|
|
71
|
+
// The color over the checkerboard: a tile of four squares, two of each.
|
|
72
|
+
background:
|
|
73
|
+
linear-gradient(var(--color-swatch-color), var(--color-swatch-color)),
|
|
74
|
+
repeating-conic-gradient(
|
|
75
|
+
cv.getVar('color-swatch-checker-color') 0% 25%,
|
|
76
|
+
cv.getVar('color-swatch-checker-background') 0% 50%
|
|
77
|
+
)
|
|
78
|
+
0 0 / calc(#{cv.getVar('color-swatch-checker-size')} * 2)
|
|
79
|
+
calc(#{cv.getVar('color-swatch-checker-size')} * 2);
|
|
80
|
+
box-shadow: inset 0 0 0 1px cv.getVar('color-swatch-edge-color');
|
|
81
|
+
// A swatch is its color, so forced colors leaves it alone.
|
|
82
|
+
forced-color-adjust: none;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.#{iv.$class-prefix}color-swatch.#{iv.$class-prefix}is-rounded {
|
|
86
|
+
border-radius: cv.getVar('radius-rounded');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// What's drawn on the swatch, such as an icon, sits in its middle.
|
|
90
|
+
.#{iv.$class-prefix}color-swatch > span {
|
|
91
|
+
display: inline-flex;
|
|
92
|
+
line-height: 1;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@media (forced-colors: active) {
|
|
96
|
+
// Kept apart from the page by the system's text color.
|
|
97
|
+
.#{iv.$class-prefix}color-swatch {
|
|
98
|
+
box-shadow: inset 0 0 0 1px CanvasText;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
// Custom-styled checkbox with colors, sizes, and visual states
|
|
3
3
|
// Follows Bulma v1 CSS variable convention (see _dialog.scss)
|
|
4
4
|
|
|
5
|
+
@use "sass:list";
|
|
5
6
|
@use "bulma/sass/utilities/initial-variables" as iv;
|
|
6
7
|
@use "bulma/sass/utilities/css-variables" as cv;
|
|
8
|
+
@use "bulma/sass/utilities/derived-variables" as dv;
|
|
7
9
|
@use "bulma/sass/utilities/mixins" as mx;
|
|
8
10
|
|
|
9
11
|
// Bulma's horizontal field: `.field-label` takes one part of the row and
|
|
@@ -182,6 +184,57 @@ $-check-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'
|
|
|
182
184
|
}
|
|
183
185
|
}
|
|
184
186
|
|
|
187
|
+
// On Bulma's selected table row (`Tr isSelected`, or a cell with
|
|
188
|
+
// `is-selected`), the row's fill is the same color a checked box fills and
|
|
189
|
+
// borders with, so the box would vanish into it and leave its tick floating.
|
|
190
|
+
// There the box takes the row's text color, and its tick and dash the row's
|
|
191
|
+
// fill, so it reads as the row's text does. An unchecked box's border takes
|
|
192
|
+
// the text color too. This outranks the color variants on purpose: any color
|
|
193
|
+
// on that fill is a guess, and the row's own pair is the one Bulma made to
|
|
194
|
+
// read.
|
|
195
|
+
//
|
|
196
|
+
// Only a Checkbox placed straight in one of those cells sits on the row's
|
|
197
|
+
// fill, so the rule names each step down to it rather than any checkbox
|
|
198
|
+
// below the row. One inside a menu, a card or a table nested in the cell sits
|
|
199
|
+
// on that surface's own background, and keeps its own colors there.
|
|
200
|
+
//
|
|
201
|
+
// A cell with a color of its own (`Td color="white"`) paints its own
|
|
202
|
+
// background over the row's, and so does every cell of a row with a color
|
|
203
|
+
// (`Tr color="white" isSelected`), which hands its color to its cells. Both
|
|
204
|
+
// are left out, and a box there keeps its usual look. Bulma colors those cells with custom properties alone, which a
|
|
205
|
+
// selector can't read, so the cells are named by class, one for each color
|
|
206
|
+
// Bulma makes them from: its `$colors` map, which its table's
|
|
207
|
+
// `$table-colors` is built from, custom colors included. A selected cell is
|
|
208
|
+
// the row's fill whatever its color, as Bulma paints it.
|
|
209
|
+
$-colored-cells: ();
|
|
210
|
+
@each $name, $color in dv.$colors {
|
|
211
|
+
$-colored-cells: list.append(
|
|
212
|
+
$-colored-cells,
|
|
213
|
+
".#{iv.$class-prefix}is-#{$name}",
|
|
214
|
+
$separator: comma
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.#{iv.$class-prefix}table {
|
|
219
|
+
tr.#{iv.$class-prefix}is-selected:not(#{$-colored-cells})
|
|
220
|
+
> td:not(#{$-colored-cells}),
|
|
221
|
+
tr.#{iv.$class-prefix}is-selected:not(#{$-colored-cells})
|
|
222
|
+
> th:not(#{$-colored-cells}),
|
|
223
|
+
td.#{iv.$class-prefix}is-selected,
|
|
224
|
+
th.#{iv.$class-prefix}is-selected {
|
|
225
|
+
> .#{iv.$class-prefix}styled-checkbox {
|
|
226
|
+
@include cv.register-vars(
|
|
227
|
+
(
|
|
228
|
+
"checkbox-border-color": #{cv.getVar("table-row-active-color")},
|
|
229
|
+
"checkbox-active-color": #{cv.getVar("table-row-active-color")},
|
|
230
|
+
"checkbox-indeterminate-color": #{cv.getVar("table-row-active-color")},
|
|
231
|
+
"checkbox-check-color": #{cv.getVar("table-row-active-background-color")},
|
|
232
|
+
)
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
185
238
|
// Size variants
|
|
186
239
|
.#{iv.$class-prefix}styled-checkbox.#{iv.$class-prefix}is-small {
|
|
187
240
|
font-size: cv.getVar("size-small");
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
// Bestax Extras - ColorPicker Styles
|
|
2
|
+
// A panel for choosing a color: a saturation and brightness square, a hue
|
|
3
|
+
// slider, an alpha slider, the value as text, and swatches. Bulma has no
|
|
4
|
+
// color picker.
|
|
5
|
+
//
|
|
6
|
+
// The square and the sliders are drawn here, and the native range inputs
|
|
7
|
+
// that operate them are visually hidden inside their thumbs. The component
|
|
8
|
+
// sets the hue as `--color-picker-hue`, the color's channels as
|
|
9
|
+
// `--color-picker-rgb`, and the thumbs' places as `--color-area-x`,
|
|
10
|
+
// `--color-area-y` and `--color-slider-position`. Forced colors would wipe
|
|
11
|
+
// the gradients, so everything that shows a color opts out of it and takes
|
|
12
|
+
// an edge in the system's text color instead.
|
|
13
|
+
|
|
14
|
+
@use 'bulma/sass/utilities/initial-variables' as iv;
|
|
15
|
+
@use 'bulma/sass/utilities/css-variables' as cv;
|
|
16
|
+
@use '../mixins' as *;
|
|
17
|
+
|
|
18
|
+
// The square and the hue track are the color model itself, so they're
|
|
19
|
+
// fixed, not themed.
|
|
20
|
+
$-black: hsl(0, 0%, 0%);
|
|
21
|
+
$-white: hsl(0, 0%, 100%);
|
|
22
|
+
$-hue-stops: hsl(0, 100%, 50%), hsl(60, 100%, 50%), hsl(120, 100%, 50%), hsl(180, 100%, 50%), hsl(240, 100%, 50%), hsl(300, 100%, 50%), hsl(360, 100%, 50%);
|
|
23
|
+
// The check on a chosen swatch, black or white, whichever reads better, in
|
|
24
|
+
// a ring of the other, so it shows whatever is under it.
|
|
25
|
+
$-ink-dark: hsl(0, 0%, 0%);
|
|
26
|
+
$-ink-light: hsl(0, 0%, 100%);
|
|
27
|
+
|
|
28
|
+
$color-picker-width: 16rem !default;
|
|
29
|
+
$color-picker-gap: 0.75rem !default;
|
|
30
|
+
$color-picker-area-height: 10rem !default;
|
|
31
|
+
$color-picker-area-radius: cv.getVar('radius') !default;
|
|
32
|
+
// The sliders' height is what a press lands on; the track is drawn thinner
|
|
33
|
+
// inside it.
|
|
34
|
+
$color-picker-slider-height: 1.5rem !default;
|
|
35
|
+
$color-picker-track-height: 0.75rem !default;
|
|
36
|
+
$color-picker-track-radius: cv.getVar('radius-rounded') !default;
|
|
37
|
+
$color-picker-thumb-size: 1.25rem !default;
|
|
38
|
+
$color-picker-thumb-border-width: 3px !default;
|
|
39
|
+
$color-picker-thumb-color: hsl(0, 0%, 100%) !default;
|
|
40
|
+
// A dark ring each side of the white one, so a thumb shows on any color.
|
|
41
|
+
$color-picker-thumb-shadow: 0 0 0 1px hsla(0, 0%, 0%, 0.45), inset 0 0 0 1px hsla(0, 0%, 0%, 0.45) !default;
|
|
42
|
+
$color-picker-edge-color: hsla(
|
|
43
|
+
cv.getVar('text-h'),
|
|
44
|
+
cv.getVar('text-s'),
|
|
45
|
+
cv.getVar('text-l'),
|
|
46
|
+
0.2
|
|
47
|
+
) !default;
|
|
48
|
+
$color-picker-checker-color: cv.getVar('border') !default;
|
|
49
|
+
$color-picker-checker-background: cv.getVar('scheme-main') !default;
|
|
50
|
+
$color-picker-checker-size: 0.375rem !default;
|
|
51
|
+
$color-picker-swatch-size: 1.5rem !default;
|
|
52
|
+
$color-picker-swatch-gap: 0.25rem !default;
|
|
53
|
+
$color-picker-swatch-radius: cv.getVar('radius') !default;
|
|
54
|
+
$color-picker-swatch-ring-color: cv.getVar('text-strong') !default;
|
|
55
|
+
$color-picker-preview-size: 1.875rem !default;
|
|
56
|
+
$color-picker-disabled-opacity: 0.5 !default;
|
|
57
|
+
|
|
58
|
+
.#{iv.$class-prefix}color-picker {
|
|
59
|
+
@include cv.register-vars(
|
|
60
|
+
(
|
|
61
|
+
'color-picker-width': #{$color-picker-width},
|
|
62
|
+
'color-picker-gap': #{$color-picker-gap},
|
|
63
|
+
'color-picker-area-height': #{$color-picker-area-height},
|
|
64
|
+
'color-picker-area-radius': #{$color-picker-area-radius},
|
|
65
|
+
'color-picker-slider-height': #{$color-picker-slider-height},
|
|
66
|
+
'color-picker-track-height': #{$color-picker-track-height},
|
|
67
|
+
'color-picker-track-radius': #{$color-picker-track-radius},
|
|
68
|
+
'color-picker-thumb-size': #{$color-picker-thumb-size},
|
|
69
|
+
'color-picker-thumb-border-width': #{$color-picker-thumb-border-width},
|
|
70
|
+
'color-picker-thumb-color': #{$color-picker-thumb-color},
|
|
71
|
+
'color-picker-thumb-shadow': #{$color-picker-thumb-shadow},
|
|
72
|
+
'color-picker-edge-color': #{$color-picker-edge-color},
|
|
73
|
+
'color-picker-checker-color': #{$color-picker-checker-color},
|
|
74
|
+
'color-picker-checker-background': #{$color-picker-checker-background},
|
|
75
|
+
'color-picker-checker-size': #{$color-picker-checker-size},
|
|
76
|
+
'color-picker-swatch-size': #{$color-picker-swatch-size},
|
|
77
|
+
'color-picker-swatch-gap': #{$color-picker-swatch-gap},
|
|
78
|
+
'color-picker-swatch-radius': #{$color-picker-swatch-radius},
|
|
79
|
+
'color-picker-swatch-ring-color': #{$color-picker-swatch-ring-color},
|
|
80
|
+
'color-picker-preview-size': #{$color-picker-preview-size},
|
|
81
|
+
'color-picker-disabled-opacity': #{$color-picker-disabled-opacity},
|
|
82
|
+
)
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ---- The panel -------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
.#{iv.$class-prefix}color-picker {
|
|
89
|
+
display: flex;
|
|
90
|
+
flex-direction: column;
|
|
91
|
+
gap: cv.getVar('color-picker-gap');
|
|
92
|
+
inline-size: cv.getVar('color-picker-width');
|
|
93
|
+
max-inline-size: 100%;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ---- The square ------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
.#{iv.$class-prefix}color-area {
|
|
99
|
+
position: relative;
|
|
100
|
+
block-size: cv.getVar('color-picker-area-height');
|
|
101
|
+
border-radius: cv.getVar('color-picker-area-radius');
|
|
102
|
+
// White to the hue across, black up from the bottom: saturation by
|
|
103
|
+
// brightness at this hue.
|
|
104
|
+
background:
|
|
105
|
+
linear-gradient(to top, #{$-black}, transparent),
|
|
106
|
+
linear-gradient(
|
|
107
|
+
to right,
|
|
108
|
+
#{$-white},
|
|
109
|
+
hsl(var(--color-picker-hue, 0) 100% 50%)
|
|
110
|
+
);
|
|
111
|
+
box-shadow: inset 0 0 0 1px cv.getVar('color-picker-edge-color');
|
|
112
|
+
cursor: crosshair;
|
|
113
|
+
// A drag moves the thumb rather than scrolling the page.
|
|
114
|
+
touch-action: none;
|
|
115
|
+
user-select: none;
|
|
116
|
+
forced-color-adjust: none;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Saturation runs from the inline start, so right to left it grows leftward.
|
|
120
|
+
.#{iv.$class-prefix}color-area:dir(rtl) {
|
|
121
|
+
background:
|
|
122
|
+
linear-gradient(to top, #{$-black}, transparent),
|
|
123
|
+
linear-gradient(
|
|
124
|
+
to left,
|
|
125
|
+
#{$-white},
|
|
126
|
+
hsl(var(--color-picker-hue, 0) 100% 50%)
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ---- The sliders -----------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
.#{iv.$class-prefix}color-slider {
|
|
133
|
+
position: relative;
|
|
134
|
+
block-size: cv.getVar('color-picker-slider-height');
|
|
135
|
+
cursor: pointer;
|
|
136
|
+
touch-action: none;
|
|
137
|
+
user-select: none;
|
|
138
|
+
forced-color-adjust: none;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.#{iv.$class-prefix}color-slider-track {
|
|
142
|
+
position: absolute;
|
|
143
|
+
inset-inline: 0;
|
|
144
|
+
inset-block-start: 50%;
|
|
145
|
+
block-size: cv.getVar('color-picker-track-height');
|
|
146
|
+
margin-block-start: calc(#{cv.getVar('color-picker-track-height')} / -2);
|
|
147
|
+
border-radius: cv.getVar('color-picker-track-radius');
|
|
148
|
+
box-shadow: inset 0 0 0 1px cv.getVar('color-picker-edge-color');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.#{iv.$class-prefix}color-slider.#{iv.$class-prefix}is-hue
|
|
152
|
+
.#{iv.$class-prefix}color-slider-track {
|
|
153
|
+
background: linear-gradient(to right, $-hue-stops);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.#{iv.$class-prefix}color-slider.#{iv.$class-prefix}is-hue
|
|
157
|
+
.#{iv.$class-prefix}color-slider-track:dir(rtl) {
|
|
158
|
+
background: linear-gradient(to left, $-hue-stops);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// From see-through to the solid color, over a checkerboard.
|
|
162
|
+
.#{iv.$class-prefix}color-slider.#{iv.$class-prefix}is-alpha
|
|
163
|
+
.#{iv.$class-prefix}color-slider-track {
|
|
164
|
+
background:
|
|
165
|
+
linear-gradient(
|
|
166
|
+
to right,
|
|
167
|
+
rgb(var(--color-picker-rgb, 0 0 0) / 0),
|
|
168
|
+
rgb(var(--color-picker-rgb, 0 0 0))
|
|
169
|
+
),
|
|
170
|
+
repeating-conic-gradient(
|
|
171
|
+
cv.getVar('color-picker-checker-color') 0% 25%,
|
|
172
|
+
cv.getVar('color-picker-checker-background') 0% 50%
|
|
173
|
+
)
|
|
174
|
+
0 0 / calc(#{cv.getVar('color-picker-checker-size')} * 2)
|
|
175
|
+
calc(#{cv.getVar('color-picker-checker-size')} * 2);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.#{iv.$class-prefix}color-slider.#{iv.$class-prefix}is-alpha
|
|
179
|
+
.#{iv.$class-prefix}color-slider-track:dir(rtl) {
|
|
180
|
+
background:
|
|
181
|
+
linear-gradient(
|
|
182
|
+
to left,
|
|
183
|
+
rgb(var(--color-picker-rgb, 0 0 0) / 0),
|
|
184
|
+
rgb(var(--color-picker-rgb, 0 0 0))
|
|
185
|
+
),
|
|
186
|
+
repeating-conic-gradient(
|
|
187
|
+
cv.getVar('color-picker-checker-color') 0% 25%,
|
|
188
|
+
cv.getVar('color-picker-checker-background') 0% 50%
|
|
189
|
+
)
|
|
190
|
+
0 0 / calc(#{cv.getVar('color-picker-checker-size')} * 2)
|
|
191
|
+
calc(#{cv.getVar('color-picker-checker-size')} * 2);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ---- Thumbs ----------------------------------------------------------------------
|
|
195
|
+
|
|
196
|
+
// A ring that shows the color under it; its centre is the value.
|
|
197
|
+
.#{iv.$class-prefix}color-area-thumb,
|
|
198
|
+
.#{iv.$class-prefix}color-slider-thumb {
|
|
199
|
+
position: absolute;
|
|
200
|
+
inline-size: cv.getVar('color-picker-thumb-size');
|
|
201
|
+
block-size: cv.getVar('color-picker-thumb-size');
|
|
202
|
+
margin-inline-start: calc(#{cv.getVar('color-picker-thumb-size')} / -2);
|
|
203
|
+
margin-block-start: calc(#{cv.getVar('color-picker-thumb-size')} / -2);
|
|
204
|
+
border: cv.getVar('color-picker-thumb-border-width') solid
|
|
205
|
+
cv.getVar('color-picker-thumb-color');
|
|
206
|
+
border-radius: 50%;
|
|
207
|
+
box-shadow: cv.getVar('color-picker-thumb-shadow');
|
|
208
|
+
pointer-events: none;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.#{iv.$class-prefix}color-area-thumb {
|
|
212
|
+
inset-inline-start: var(--color-area-x, 0%);
|
|
213
|
+
inset-block-start: var(--color-area-y, 100%);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.#{iv.$class-prefix}color-slider-thumb {
|
|
217
|
+
inset-inline-start: var(--color-slider-position, 0%);
|
|
218
|
+
inset-block-start: 50%;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// The inputs that operate them, there for the keyboard and assistive tech.
|
|
222
|
+
.#{iv.$class-prefix}color-area-input,
|
|
223
|
+
.#{iv.$class-prefix}color-slider-input {
|
|
224
|
+
@include extras-sr-only;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.#{iv.$class-prefix}color-area-thumb:has(:focus-visible),
|
|
228
|
+
.#{iv.$class-prefix}color-slider-thumb:has(:focus-visible) {
|
|
229
|
+
@include extras-focus-outline;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ---- The value -------------------------------------------------------------------
|
|
233
|
+
|
|
234
|
+
.#{iv.$class-prefix}color-picker-value {
|
|
235
|
+
display: flex;
|
|
236
|
+
align-items: center;
|
|
237
|
+
gap: 0.5rem;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.#{iv.$class-prefix}color-picker-value
|
|
241
|
+
> .#{iv.$class-prefix}color-picker-preview {
|
|
242
|
+
inline-size: cv.getVar('color-picker-preview-size');
|
|
243
|
+
block-size: cv.getVar('color-picker-preview-size');
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.#{iv.$class-prefix}color-picker-value > .#{iv.$class-prefix}input {
|
|
247
|
+
flex: 1 1 auto;
|
|
248
|
+
min-inline-size: 0;
|
|
249
|
+
font-variant-numeric: tabular-nums;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// ---- Swatches --------------------------------------------------------------------
|
|
253
|
+
|
|
254
|
+
.#{iv.$class-prefix}color-picker-swatches {
|
|
255
|
+
display: flex;
|
|
256
|
+
flex-wrap: wrap;
|
|
257
|
+
gap: cv.getVar('color-picker-swatch-gap');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// The button rings the swatch when it's chosen, so the choice shows as an
|
|
261
|
+
// edge and a check as well as a color.
|
|
262
|
+
.#{iv.$class-prefix}color-picker-swatch {
|
|
263
|
+
@include extras-button-reset;
|
|
264
|
+
display: inline-flex;
|
|
265
|
+
padding: 2px;
|
|
266
|
+
border: 2px solid transparent;
|
|
267
|
+
border-radius: calc(#{cv.getVar('color-picker-swatch-radius')} + 4px);
|
|
268
|
+
line-height: 0;
|
|
269
|
+
|
|
270
|
+
&:focus-visible {
|
|
271
|
+
@include extras-focus-outline;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.#{iv.$class-prefix}color-swatch {
|
|
275
|
+
inline-size: cv.getVar('color-picker-swatch-size');
|
|
276
|
+
block-size: cv.getVar('color-picker-swatch-size');
|
|
277
|
+
border-radius: cv.getVar('color-picker-swatch-radius');
|
|
278
|
+
color: $-ink-light;
|
|
279
|
+
font-size: calc(#{cv.getVar('color-picker-swatch-size')} * 0.75);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.#{iv.$class-prefix}color-picker-check-halo {
|
|
283
|
+
stroke: $-ink-dark;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
&.#{iv.$class-prefix}is-dark-ink {
|
|
287
|
+
.#{iv.$class-prefix}color-swatch {
|
|
288
|
+
color: $-ink-dark;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.#{iv.$class-prefix}color-picker-check-halo {
|
|
292
|
+
stroke: $-ink-light;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// A see-through swatch shows the checkerboard under it, which is drawn in
|
|
297
|
+
// the scheme's colors, so the check takes the scheme's text color in a ring
|
|
298
|
+
// of its background, and follows dark mode.
|
|
299
|
+
&.#{iv.$class-prefix}is-see-through {
|
|
300
|
+
.#{iv.$class-prefix}color-swatch {
|
|
301
|
+
color: cv.getVar('text-strong');
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.#{iv.$class-prefix}color-picker-check-halo {
|
|
305
|
+
stroke: cv.getVar('scheme-main');
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
&.#{iv.$class-prefix}is-checked {
|
|
310
|
+
border-color: cv.getVar('color-picker-swatch-ring-color');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
&:disabled {
|
|
314
|
+
cursor: not-allowed;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// ---- Disabled --------------------------------------------------------------------
|
|
319
|
+
|
|
320
|
+
.#{iv.$class-prefix}color-picker.#{iv.$class-prefix}is-disabled,
|
|
321
|
+
.#{iv.$class-prefix}color-area.#{iv.$class-prefix}is-disabled,
|
|
322
|
+
.#{iv.$class-prefix}color-slider.#{iv.$class-prefix}is-disabled {
|
|
323
|
+
cursor: not-allowed;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.#{iv.$class-prefix}color-area.#{iv.$class-prefix}is-disabled,
|
|
327
|
+
.#{iv.$class-prefix}color-slider.#{iv.$class-prefix}is-disabled,
|
|
328
|
+
.#{iv.$class-prefix}color-picker-swatches[aria-disabled='true'] {
|
|
329
|
+
opacity: cv.getVar('color-picker-disabled-opacity');
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// ---- Forced colors ---------------------------------------------------------------
|
|
333
|
+
|
|
334
|
+
@media (forced-colors: active) {
|
|
335
|
+
// The colors stay, edged in the system's text color.
|
|
336
|
+
.#{iv.$class-prefix}color-area,
|
|
337
|
+
.#{iv.$class-prefix}color-slider-track {
|
|
338
|
+
box-shadow: inset 0 0 0 1px CanvasText;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.#{iv.$class-prefix}color-area-thumb:has(:focus-visible),
|
|
342
|
+
.#{iv.$class-prefix}color-slider-thumb:has(:focus-visible) {
|
|
343
|
+
outline-color: Highlight;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// An unchosen swatch's border would otherwise show like the chosen one's.
|
|
347
|
+
.#{iv.$class-prefix}color-picker-swatch {
|
|
348
|
+
border-color: Canvas;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.#{iv.$class-prefix}color-picker-swatch.#{iv.$class-prefix}is-checked {
|
|
352
|
+
border-color: Highlight;
|
|
353
|
+
}
|
|
354
|
+
}
|