@allxsmith/bestax-bulma 5.62.0 → 5.64.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.
Files changed (89) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/esm/components/EmptyState.js +2 -6
  4. package/dist/esm/components/EmptyState.js.map +1 -1
  5. package/dist/esm/components/ScrollArea.js +7 -7
  6. package/dist/esm/components/ScrollArea.js.map +1 -1
  7. package/dist/esm/components/TableOfContents.js +85 -0
  8. package/dist/esm/components/TableOfContents.js.map +1 -0
  9. package/dist/esm/components/Timeline.js +5 -9
  10. package/dist/esm/components/Timeline.js.map +1 -1
  11. package/dist/esm/components/TreeView.js +3 -7
  12. package/dist/esm/components/TreeView.js.map +1 -1
  13. package/dist/esm/elements/Buttons.js +2 -0
  14. package/dist/esm/elements/Buttons.js.map +1 -1
  15. package/dist/esm/elements/CopyButton.js +132 -0
  16. package/dist/esm/elements/CopyButton.js.map +1 -0
  17. package/dist/esm/elements/DescriptionList.js +1 -5
  18. package/dist/esm/elements/DescriptionList.js.map +1 -1
  19. package/dist/esm/elements/Stat.js +196 -0
  20. package/dist/esm/elements/Stat.js.map +1 -0
  21. package/dist/esm/elements/Stats.js +48 -0
  22. package/dist/esm/elements/Stats.js.map +1 -0
  23. package/dist/esm/elements/statContext.js +10 -0
  24. package/dist/esm/elements/statContext.js.map +1 -0
  25. package/dist/esm/form/Combobox.js +2 -1
  26. package/dist/esm/form/Combobox.js.map +1 -1
  27. package/dist/esm/form/PasswordInput.js +105 -0
  28. package/dist/esm/form/PasswordInput.js.map +1 -0
  29. package/dist/esm/form/PasswordInputBase.js +177 -0
  30. package/dist/esm/form/PasswordInputBase.js.map +1 -0
  31. package/dist/esm/helpers/checkIcon.js +20 -0
  32. package/dist/esm/helpers/checkIcon.js.map +1 -0
  33. package/dist/esm/helpers/isGiven.js +13 -0
  34. package/dist/esm/helpers/isGiven.js.map +1 -0
  35. package/dist/esm/helpers/statusRegion.js +3 -3
  36. package/dist/esm/helpers/useClipboard.js +176 -0
  37. package/dist/esm/helpers/useClipboard.js.map +1 -0
  38. package/dist/esm/helpers/useScrollSpy.js +286 -0
  39. package/dist/esm/helpers/useScrollSpy.js.map +1 -0
  40. package/dist/extras.css +1 -1
  41. package/dist/extras.css.map +1 -1
  42. package/dist/index.cjs +2671 -1544
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/index.esm.js +8 -0
  45. package/dist/index.esm.js.map +1 -1
  46. package/dist/types/components/TableOfContents.d.ts +87 -0
  47. package/dist/types/elements/Buttons.d.ts +1 -0
  48. package/dist/types/elements/CopyButton.d.ts +105 -0
  49. package/dist/types/elements/Stat.d.ts +242 -0
  50. package/dist/types/elements/Stats.d.ts +40 -0
  51. package/dist/types/elements/statContext.d.ts +18 -0
  52. package/dist/types/form/PasswordInput.d.ts +98 -0
  53. package/dist/types/form/PasswordInputBase.d.ts +91 -0
  54. package/dist/types/helpers/checkIcon.d.ts +10 -0
  55. package/dist/types/helpers/isGiven.d.ts +7 -0
  56. package/dist/types/helpers/useClipboard.d.ts +65 -0
  57. package/dist/types/helpers/useScrollSpy.d.ts +61 -0
  58. package/dist/types/index.d.ts +10 -0
  59. package/dist/types-cjs/components/TableOfContents.d.ts +87 -0
  60. package/dist/types-cjs/elements/Buttons.d.ts +1 -0
  61. package/dist/types-cjs/elements/CopyButton.d.ts +105 -0
  62. package/dist/types-cjs/elements/Stat.d.ts +242 -0
  63. package/dist/types-cjs/elements/Stats.d.ts +40 -0
  64. package/dist/types-cjs/elements/statContext.d.ts +18 -0
  65. package/dist/types-cjs/form/PasswordInput.d.ts +98 -0
  66. package/dist/types-cjs/form/PasswordInputBase.d.ts +91 -0
  67. package/dist/types-cjs/helpers/checkIcon.d.ts +10 -0
  68. package/dist/types-cjs/helpers/isGiven.d.ts +7 -0
  69. package/dist/types-cjs/helpers/useClipboard.d.ts +65 -0
  70. package/dist/types-cjs/helpers/useScrollSpy.d.ts +61 -0
  71. package/dist/types-cjs/index.d.ts +10 -0
  72. package/dist/versions/bestax-no-dark-mode.css +1 -1
  73. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  74. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  75. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  76. package/dist/versions/bestax-no-helpers.css +1 -1
  77. package/dist/versions/bestax-no-helpers.css.map +1 -1
  78. package/dist/versions/bestax-prefixed.css +1 -1
  79. package/dist/versions/bestax-prefixed.css.map +1 -1
  80. package/package.json +1 -1
  81. package/src/scss/CLAUDE.md +3 -0
  82. package/src/scss/_input-trigger.scss +76 -0
  83. package/src/scss/components/_index.scss +1 -0
  84. package/src/scss/components/_tableofcontents.scss +42 -0
  85. package/src/scss/elements/_index.scss +1 -0
  86. package/src/scss/elements/_stat.scss +153 -0
  87. package/src/scss/form/_index.scss +1 -0
  88. package/src/scss/form/_passwordinput.scss +112 -0
  89. package/src/scss/form/_picker-popover.scss +24 -63
@@ -16,6 +16,9 @@ of their own — Bulma provides it. A partial exists only for components that ex
16
16
  It loads no Bulma module, since tests compile it with only this folder on the load path
17
17
  - `_selected-row.scss` — `extras-selected-table-cell`, the cells Checkbox's and Radio's
18
18
  selected-row rules share; it reads Bulma's `$colors`, which is why it isn't in `_mixins.scss`
19
+ - `_input-trigger.scss` — `extras-input-trigger`, a button laid over an input's right edge, which
20
+ the date and time pickers' launcher and PasswordInput's toggle share; it reads Bulma's class
21
+ prefix and variables, so it isn't in `_mixins.scss` either
19
22
  - `versions/` — the flavor builds: `bestax-prefixed`, `bestax-no-helpers`, `bestax-no-dark-mode`,
20
23
  `bestax-no-helpers-prefixed`. A new partial is included by all of them automatically (they reuse
21
24
  the same `_index` imports), but must **work** under each — especially the prefixed build.
@@ -0,0 +1,76 @@
1
+ // Bestax Extras - a button inside an input
2
+ // The rule the date and time pickers' launcher and PasswordInput's toggle
3
+ // share, so the two can't drift apart. It reads Bulma's class prefix and
4
+ // variables, so it lives here rather than in `_mixins.scss`, which compiles
5
+ // with no Bulma to load, and it emits nothing until it's included.
6
+
7
+ @use 'bulma/sass/utilities/initial-variables' as iv;
8
+ @use 'bulma/sass/utilities/css-variables' as cv;
9
+ @use 'mixins' as *;
10
+
11
+ // A button over the input's right edge, in Bulma's 2.5em icon slot. Bulma's
12
+ // Control icons are decorative (`pointer-events: none`), so a button there
13
+ // needs rules of its own. Include it on the element that holds the input and
14
+ // the button, which it positions. A content block, when given, lands in that
15
+ // element's own rule, after its `position`: the pickers register the
16
+ // variables they pass in there.
17
+ //
18
+ // `$trigger` is the button's class, without the prefix. `$width` is the slot,
19
+ // which the input keeps as padding so typed text never slides under the
20
+ // button; `$color` and `$hover-color` are the button's, and
21
+ // `$disabled-opacity` a disabled one's. Each is usually a `cv.getVar()`, so
22
+ // every value a theme can change is a registered variable. The color change
23
+ // on hover takes Bulma's duration and easing through `extras-transition`. The
24
+ // button takes the input's `is-small`, `is-medium` or `is-large` font size,
25
+ // so its em-based width tracks the input's.
26
+ @mixin extras-input-trigger(
27
+ $trigger,
28
+ $width,
29
+ $color,
30
+ $hover-color,
31
+ $disabled-opacity
32
+ ) {
33
+ position: relative;
34
+ @content;
35
+
36
+ > .#{iv.$class-prefix}input {
37
+ padding-right: $width;
38
+ }
39
+
40
+ > .#{iv.$class-prefix}#{$trigger} {
41
+ position: absolute;
42
+ top: 0;
43
+ right: 0;
44
+ z-index: 4;
45
+ height: 100%;
46
+ width: $width;
47
+ display: inline-flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ padding: 0;
51
+ border: none;
52
+ background: transparent;
53
+ color: $color;
54
+ cursor: pointer;
55
+ @include extras-transition(color);
56
+
57
+ .#{iv.$class-prefix}icon {
58
+ pointer-events: none;
59
+ }
60
+
61
+ &:hover:not(:disabled) {
62
+ color: $hover-color;
63
+ }
64
+ &:disabled {
65
+ cursor: not-allowed;
66
+ opacity: $disabled-opacity;
67
+ }
68
+ }
69
+
70
+ @each $size in 'small', 'medium', 'large' {
71
+ > .#{iv.$class-prefix}input.#{iv.$class-prefix}is-#{$size}
72
+ ~ .#{iv.$class-prefix}#{$trigger} {
73
+ font-size: cv.getVar('size-#{$size}');
74
+ }
75
+ }
76
+ }
@@ -15,6 +15,7 @@
15
15
  @use 'carousel';
16
16
  @use 'tabs';
17
17
  @use 'menu';
18
+ @use 'tableofcontents';
18
19
  @use 'reveal';
19
20
  @use 'avatar';
20
21
  @use 'avatars';
@@ -0,0 +1,42 @@
1
+ // Bestax Extras - TableOfContents Styles
2
+ // A table of contents is Bulma's menu as it is: `.menu` on its `<nav>`, a
3
+ // `.menu-label` title, `.menu-list` links and `is-active` on the current one,
4
+ // so every `--bulma-menu-*` variable themes it. This adds only the opt-in
5
+ // sticky position, for a column that doesn't stick by itself.
6
+
7
+ @use 'bulma/sass/utilities/initial-variables' as iv;
8
+ @use 'bulma/sass/utilities/css-variables' as cv;
9
+
10
+ // How far below the viewport's top a sticky list stops. Under a fixed
11
+ // navbar, make it the navbar's height plus this.
12
+ $table-of-contents-sticky-top: cv.getVar('block-spacing') !default;
13
+
14
+ .#{iv.$class-prefix}table-of-contents {
15
+ @include cv.register-vars(
16
+ (
17
+ 'table-of-contents-sticky-top': #{$table-of-contents-sticky-top},
18
+ )
19
+ );
20
+ }
21
+
22
+ // Bulma's focus ring, which sits this far outside a link.
23
+ $-focus-ring: calc(#{cv.getVar('focus-width')} + #{cv.getVar('focus-offset')});
24
+
25
+ // It stays in view as the page scrolls, and a list taller than the room left
26
+ // below its top scrolls itself, so its end can still be reached. The room is
27
+ // measured in `dvh`, the viewport as it is now, so a phone's toolbar doesn't
28
+ // cover the list's end, and in `vh` where `dvh` isn't known. Scrolling clips
29
+ // what's outside it, so it keeps room around it for a link's focus ring, at
30
+ // the sides and above the first link and below the last, and gives that room
31
+ // back with a margin, so the links stay where they are.
32
+ .#{iv.$class-prefix}table-of-contents.#{iv.$class-prefix}is-sticky {
33
+ margin-block: calc(-1 * #{$-focus-ring});
34
+ margin-inline: calc(-1 * #{$-focus-ring});
35
+ max-height: calc(100vh - #{cv.getVar('table-of-contents-sticky-top')});
36
+ max-height: calc(100dvh - #{cv.getVar('table-of-contents-sticky-top')});
37
+ overflow-y: auto;
38
+ padding-block: $-focus-ring;
39
+ padding-inline: $-focus-ring;
40
+ position: sticky;
41
+ top: cv.getVar('table-of-contents-sticky-top');
42
+ }
@@ -13,3 +13,4 @@
13
13
  @use 'progress';
14
14
  @use 'ringprogress';
15
15
  @use 'skeleton';
16
+ @use 'stat';
@@ -0,0 +1,153 @@
1
+ // Bestax Extras - Stat Styles
2
+ // A figure with its name, and often a change and a note, as a description
3
+ // list: a `<dt>` for the label and a `<dd>` each for the figure, the change
4
+ // and the note. A Stat is a `<div>` in a `Stats` row's `<dl>`, or a `<dl>` of
5
+ // its own. `Stats` is Bulma's `.grid`, which lays the row out, so all it
6
+ // needs here is the list's margins reset; this sets the type.
7
+ //
8
+ // Each part stacks under the one before, in the order it's written. The
9
+ // figure takes the Stat's color, so a `textColor` on the Stat colors it,
10
+ // while the label, the change and the note set their own. A `color` on the
11
+ // change sets its color to that color's `-on-scheme` variant, which Bulma
12
+ // darkens or lightens until it reads as text on the scheme's background. Forced colors replaces every color with the system's, which
13
+ // drops the tone, and the sign in the text and the arrow, drawn in
14
+ // `currentColor`, remain.
15
+
16
+ @use 'bulma/sass/utilities/initial-variables' as iv;
17
+ @use 'bulma/sass/utilities/css-variables' as cv;
18
+
19
+ $stat-label-color: cv.getVar('text-weak') !default;
20
+ $stat-label-size: cv.getVar('size-7') !default;
21
+ $stat-value-color: cv.getVar('text-strong') !default;
22
+ $stat-value-size: cv.getVar('size-3') !default;
23
+ $stat-value-size-small: cv.getVar('size-4') !default;
24
+ $stat-value-size-medium: cv.getVar('size-2') !default;
25
+ $stat-value-size-large: cv.getVar('size-1') !default;
26
+ $stat-value-weight: cv.getVar('weight-semibold') !default;
27
+ // Bulma's title line height, tight for large figures.
28
+ $stat-value-line-height: 1.125 !default;
29
+ $stat-change-color: cv.getVar('text') !default;
30
+ $stat-change-size: cv.getVar('size-7') !default;
31
+ // Between the arrow and the number.
32
+ $stat-change-gap: 0.25em !default;
33
+ $stat-description-color: cv.getVar('text-weak') !default;
34
+ $stat-description-size: cv.getVar('size-7') !default;
35
+
36
+ .#{iv.$class-prefix}stat {
37
+ @include cv.register-vars(
38
+ (
39
+ 'stat-label-color': #{$stat-label-color},
40
+ 'stat-label-size': #{$stat-label-size},
41
+ 'stat-value-color': #{$stat-value-color},
42
+ 'stat-value-size': #{$stat-value-size},
43
+ 'stat-value-weight': #{$stat-value-weight},
44
+ 'stat-value-line-height': #{$stat-value-line-height},
45
+ 'stat-change-color': #{$stat-change-color},
46
+ 'stat-change-size': #{$stat-change-size},
47
+ 'stat-change-gap': #{$stat-change-gap},
48
+ 'stat-description-color': #{$stat-description-color},
49
+ 'stat-description-size': #{$stat-description-size},
50
+ )
51
+ );
52
+ }
53
+
54
+ @each $size,
55
+ $value
56
+ in (
57
+ 'small': $stat-value-size-small,
58
+ 'medium': $stat-value-size-medium,
59
+ 'large': $stat-value-size-large
60
+ )
61
+ {
62
+ .#{iv.$class-prefix}stat.#{iv.$class-prefix}is-#{$size} {
63
+ @include cv.register-vars(
64
+ (
65
+ 'stat-value-size': #{$value},
66
+ )
67
+ );
68
+ }
69
+ }
70
+
71
+ // ---- The row and the Stat ----------------------------------------------------
72
+
73
+ .#{iv.$class-prefix}stats {
74
+ margin-inline: 0;
75
+ margin-block-start: 0;
76
+ }
77
+
78
+ .#{iv.$class-prefix}stat {
79
+ margin: 0;
80
+ // On the root, so a `textColor` helper's class outranks it and the figure
81
+ // inherits either.
82
+ color: cv.getVar('stat-value-color');
83
+
84
+ // A Stat on its own is a block, as Bulma spaces its blocks.
85
+ &:not(:last-child) {
86
+ margin-bottom: cv.getVar('block-spacing');
87
+ }
88
+ }
89
+
90
+ // In a row the grid's gap spaces the tiles.
91
+ .#{iv.$class-prefix}stats > .#{iv.$class-prefix}stat {
92
+ margin-bottom: 0;
93
+ }
94
+
95
+ // ---- The parts -------------------------------------------------------------------
96
+
97
+ // Each through the root, so it outranks Bulma's `.content dd` indent.
98
+ .#{iv.$class-prefix}stat .#{iv.$class-prefix}stat-label {
99
+ margin: 0;
100
+ color: cv.getVar('stat-label-color');
101
+ font-size: cv.getVar('stat-label-size');
102
+ }
103
+
104
+ .#{iv.$class-prefix}stat .#{iv.$class-prefix}stat-value {
105
+ margin: 0;
106
+ font-size: cv.getVar('stat-value-size');
107
+ font-weight: cv.getVar('stat-value-weight');
108
+ line-height: cv.getVar('stat-value-line-height');
109
+ // Digits of one width, so a figure that updates doesn't shift.
110
+ font-variant-numeric: tabular-nums;
111
+ // A long figure wraps rather than widen its tile.
112
+ overflow-wrap: anywhere;
113
+ }
114
+
115
+ // `loading`'s Skeleton, and a figure's `<dd>` still waiting for its value,
116
+ // are one line of the figure tall, so the tile is as tall as its neighbours
117
+ // and keeps its height when the figure arrives.
118
+ .#{iv.$class-prefix}stat .#{iv.$class-prefix}stat-value:empty,
119
+ .#{iv.$class-prefix}stat
120
+ .#{iv.$class-prefix}stat-value
121
+ > .#{iv.$class-prefix}skeleton-block {
122
+ min-height: 1lh;
123
+ }
124
+
125
+ .#{iv.$class-prefix}stat .#{iv.$class-prefix}stat-change {
126
+ display: flex;
127
+ align-items: center;
128
+ gap: cv.getVar('stat-change-gap');
129
+ margin: 0;
130
+ color: cv.getVar('stat-change-color');
131
+ font-size: cv.getVar('stat-change-size');
132
+ font-variant-numeric: tabular-nums;
133
+
134
+ > svg {
135
+ flex: none;
136
+ }
137
+ }
138
+
139
+ // The change's colors, set on the change itself, so `--bulma-stat-change-color`
140
+ // stays the uncolored change's. A theme moves these tones through Bulma's own
141
+ // `-on-scheme` colors.
142
+ @each $name in 'primary', 'link', 'info', 'success', 'warning', 'danger' {
143
+ .#{iv.$class-prefix}stat
144
+ .#{iv.$class-prefix}stat-change.#{iv.$class-prefix}is-#{$name} {
145
+ color: cv.getVar('#{$name}-on-scheme');
146
+ }
147
+ }
148
+
149
+ .#{iv.$class-prefix}stat .#{iv.$class-prefix}stat-description {
150
+ margin: 0;
151
+ color: cv.getVar('stat-description-color');
152
+ font-size: cv.getVar('stat-description-size');
153
+ }
@@ -24,5 +24,6 @@
24
24
  @use 'dropzone';
25
25
  @use 'colorpicker';
26
26
  @use 'colorinput';
27
+ @use 'passwordinput';
27
28
  @use 'fieldset';
28
29
  @use 'field';
@@ -0,0 +1,112 @@
1
+ // Bestax Extras - PasswordInput Styles
2
+ // A password field with a button inside it that shows what was typed. Bulma's
3
+ // Control icons take no clicks, so the toggle is a real button laid over the
4
+ // input's right edge, with the date pickers' launcher rule, which the two
5
+ // share through the `extras-input-trigger` mixin.
6
+ //
7
+ // The toggle sits on the physical right, as the pickers' launcher and Bulma's
8
+ // right icon do, so in a right-to-left page it's at the start of the field
9
+ // rather than its end. Moving them to the inline end is one change, for all
10
+ // of them together.
11
+
12
+ @use 'bulma/sass/utilities/initial-variables' as iv;
13
+ @use 'bulma/sass/utilities/css-variables' as cv;
14
+ @use '../mixins' as *;
15
+ @use '../input-trigger' as *;
16
+
17
+ // The toggle's room, in em so it tracks the input's size, as Bulma's icon
18
+ // slot does. The words need more room than the eye; a longer translation
19
+ // sets its own.
20
+ $password-input-toggle-width: 2.5em !default;
21
+ $password-input-toggle-text-width: 4.5em !default;
22
+ $password-input-toggle-color: cv.getVar('text') !default;
23
+ $password-input-toggle-hover-color: cv.getVar('text-strong') !default;
24
+ $password-input-toggle-disabled-opacity: 0.5 !default;
25
+
26
+ .#{iv.$class-prefix}password-input-container {
27
+ @include cv.register-vars(
28
+ (
29
+ 'password-input-toggle-width': #{$password-input-toggle-width},
30
+ 'password-input-toggle-text-width': #{$password-input-toggle-text-width},
31
+ 'password-input-toggle-color': #{$password-input-toggle-color},
32
+ 'password-input-toggle-hover-color': #{$password-input-toggle-hover-color},
33
+ 'password-input-toggle-disabled-opacity': #{$password-input-toggle-disabled-opacity},
34
+ )
35
+ );
36
+ }
37
+
38
+ .#{iv.$class-prefix}password-input-container {
39
+ @include extras-input-trigger(
40
+ $trigger: 'password-input-toggle',
41
+ $width: cv.getVar('password-input-toggle-width'),
42
+ $color: cv.getVar('password-input-toggle-color'),
43
+ $hover-color: cv.getVar('password-input-toggle-hover-color'),
44
+ $disabled-opacity: cv.getVar('password-input-toggle-disabled-opacity')
45
+ );
46
+
47
+ // Bulma gives a rounded input its own side padding at two classes, which
48
+ // ties the rule above; at three this wins whichever sheet loads first.
49
+ > .#{iv.$class-prefix}input.#{iv.$class-prefix}is-rounded {
50
+ padding-right: cv.getVar('password-input-toggle-width');
51
+ }
52
+
53
+ &.#{iv.$class-prefix}is-text {
54
+ > .#{iv.$class-prefix}input,
55
+ > .#{iv.$class-prefix}input.#{iv.$class-prefix}is-rounded {
56
+ padding-right: cv.getVar('password-input-toggle-text-width');
57
+ }
58
+
59
+ > .#{iv.$class-prefix}password-input-toggle {
60
+ width: cv.getVar('password-input-toggle-text-width');
61
+ }
62
+ }
63
+
64
+ > .#{iv.$class-prefix}password-input-toggle {
65
+ // The input's own size, which the size modifiers above change, wherever
66
+ // the field sits; a button otherwise takes the text's around it.
67
+ font-family: inherit;
68
+ font-size: cv.getVar('size-normal');
69
+ line-height: 1;
70
+
71
+ &:focus-visible {
72
+ @include extras-focus-outline;
73
+ }
74
+ }
75
+
76
+ // Edge draws its own reveal button in a password field, which would make
77
+ // two.
78
+ > .#{iv.$class-prefix}input::-ms-reveal {
79
+ display: none;
80
+ }
81
+ }
82
+
83
+ // Bulma sizes and colors a left icon from the input beside it
84
+ // (`.input.is-small ~ .icon`). Here the input sits one level down, in the
85
+ // container, so these say the same from the container.
86
+ .#{iv.$class-prefix}control.#{iv.$class-prefix}has-icons-left
87
+ > .#{iv.$class-prefix}password-input-container {
88
+ @each $size in 'small', 'medium', 'large' {
89
+ &:has(> .#{iv.$class-prefix}input.#{iv.$class-prefix}is-#{$size})
90
+ ~ .#{iv.$class-prefix}icon {
91
+ font-size: cv.getVar('size-#{$size}');
92
+ }
93
+ }
94
+
95
+ &:has(> .#{iv.$class-prefix}input:hover) ~ .#{iv.$class-prefix}icon {
96
+ color: cv.getVar('input-icon-hover-color');
97
+ }
98
+
99
+ &:has(> .#{iv.$class-prefix}input:focus) ~ .#{iv.$class-prefix}icon {
100
+ color: cv.getVar('input-icon-focus-color');
101
+ }
102
+ }
103
+
104
+ // In forced colors the toggle's glyph and words take the system's button
105
+ // text, and a disabled one the system's gray, as a native button's do.
106
+ @media (forced-colors: active) {
107
+ .#{iv.$class-prefix}password-input-container
108
+ > .#{iv.$class-prefix}password-input-toggle:disabled {
109
+ color: GrayText;
110
+ opacity: 1;
111
+ }
112
+ }
@@ -1,5 +1,6 @@
1
1
  @use 'bulma/sass/utilities/initial-variables' as iv;
2
2
  @use 'bulma/sass/utilities/css-variables' as cv;
3
+ @use '../input-trigger' as *;
3
4
 
4
5
  $picker-popover-z-index: 30 !default;
5
6
  $picker-popover-background: cv.getVar('scheme-main') !default;
@@ -12,6 +13,7 @@ $picker-popover-animation-duration: 0.15s !default;
12
13
  $picker-trigger-width: 2.5em !default;
13
14
  $picker-trigger-color: cv.getVar('text') !default;
14
15
  $picker-trigger-hover-color: cv.getVar('text-strong') !default;
16
+ $picker-trigger-disabled-opacity: 0.5 !default;
15
17
 
16
18
  .#{iv.$class-prefix}picker-popover {
17
19
  @include cv.register-vars(
@@ -135,73 +137,32 @@ $picker-containers: (
135
137
  // Right-side launcher button. The picker bases render this real <button>
136
138
  // inside their *-container (Bulma's Control icons are decorative —
137
139
  // `pointer-events: none` — so they can't open the popover). It toggles the
138
- // popover and is keyboard-focusable. Sizing mirrors Bulma's 2.5em icon slot
139
- // and tracks the input's size modifier via the sibling selector.
140
+ // popover and is keyboard-focusable. Its rules are the `extras-input-trigger`
141
+ // mixin's, which PasswordInput's toggle shares: Bulma's 2.5em icon slot,
142
+ // tracking the input's size modifier through the sibling selector.
140
143
  $picker-trigger-pairs: (
141
- ('#{iv.$class-prefix}dateinput-container' '#{iv.$class-prefix}dateinput-trigger'),
142
- ('#{iv.$class-prefix}timeinput-container' '#{iv.$class-prefix}timeinput-trigger'),
143
- (
144
- '#{iv.$class-prefix}datetimeinput-container'
145
- '#{iv.$class-prefix}datetimeinput-trigger'
146
- )
144
+ ('dateinput-container' 'dateinput-trigger'),
145
+ ('timeinput-container' 'timeinput-trigger'),
146
+ ('datetimeinput-container' 'datetimeinput-trigger')
147
147
  );
148
148
 
149
149
  @each $container, $trigger in $picker-trigger-pairs {
150
- .#{$container} {
151
- position: relative;
152
- @include cv.register-vars(
153
- (
154
- 'picker-trigger-width': #{$picker-trigger-width},
155
- 'picker-trigger-color': #{$picker-trigger-color},
156
- 'picker-trigger-hover-color': #{$picker-trigger-hover-color},
157
- )
158
- );
159
-
160
- // Reserve room so typed text doesn't slide under the launcher.
161
- > .#{iv.$class-prefix}input {
162
- padding-right: cv.getVar('picker-trigger-width');
163
- }
164
-
165
- > .#{$trigger} {
166
- position: absolute;
167
- top: 0;
168
- right: 0;
169
- z-index: 4;
170
- height: 100%;
171
- width: cv.getVar('picker-trigger-width');
172
- display: inline-flex;
173
- align-items: center;
174
- justify-content: center;
175
- padding: 0;
176
- border: none;
177
- background: transparent;
178
- color: cv.getVar('picker-trigger-color');
179
- cursor: pointer;
180
- transition: color 0.15s ease;
181
-
182
- .#{iv.$class-prefix}icon {
183
- pointer-events: none;
184
- }
185
-
186
- &:hover:not(:disabled) {
187
- color: cv.getVar('picker-trigger-hover-color');
188
- }
189
- &:disabled {
190
- cursor: not-allowed;
191
- opacity: 0.5;
192
- }
193
- }
194
-
195
- // Match the launcher's font-size to the input's size modifier so its
196
- // em-based width tracks the control.
197
- > .#{iv.$class-prefix}input.#{iv.$class-prefix}is-small ~ .#{$trigger} {
198
- font-size: cv.getVar('size-small');
199
- }
200
- > .#{iv.$class-prefix}input.#{iv.$class-prefix}is-medium ~ .#{$trigger} {
201
- font-size: cv.getVar('size-medium');
202
- }
203
- > .#{iv.$class-prefix}input.#{iv.$class-prefix}is-large ~ .#{$trigger} {
204
- font-size: cv.getVar('size-large');
150
+ .#{iv.$class-prefix}#{$container} {
151
+ @include extras-input-trigger(
152
+ $trigger: $trigger,
153
+ $width: cv.getVar('picker-trigger-width'),
154
+ $color: cv.getVar('picker-trigger-color'),
155
+ $hover-color: cv.getVar('picker-trigger-hover-color'),
156
+ $disabled-opacity: cv.getVar('picker-trigger-disabled-opacity')
157
+ ) {
158
+ @include cv.register-vars(
159
+ (
160
+ 'picker-trigger-width': #{$picker-trigger-width},
161
+ 'picker-trigger-color': #{$picker-trigger-color},
162
+ 'picker-trigger-hover-color': #{$picker-trigger-hover-color},
163
+ 'picker-trigger-disabled-opacity': #{$picker-trigger-disabled-opacity},
164
+ )
165
+ );
205
166
  }
206
167
  }
207
168
  }