@allxsmith/bestax-bulma 2.6.2 → 3.0.2

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 (139) hide show
  1. package/README.md +2 -2
  2. package/dist/bestax.css +3 -0
  3. package/dist/bestax.css.map +1 -0
  4. package/dist/bestax.js +1 -0
  5. package/dist/extras.css +3 -0
  6. package/dist/extras.css.map +1 -0
  7. package/dist/extras.js +1 -0
  8. package/dist/index.cjs.js +6214 -647
  9. package/dist/index.cjs.js.map +1 -1
  10. package/dist/index.esm.js +6154 -649
  11. package/dist/index.esm.js.map +1 -1
  12. package/dist/types/components/Card.d.ts +1 -1
  13. package/dist/types/components/Carousel.d.ts +34 -0
  14. package/dist/types/components/Collapse.d.ts +17 -0
  15. package/dist/types/components/Dialog.d.ts +47 -0
  16. package/dist/types/components/Loading.d.ts +18 -0
  17. package/dist/types/components/Navbar.d.ts +10 -0
  18. package/dist/types/components/Panel.d.ts +2 -4
  19. package/dist/types/components/Sidebar.d.ts +37 -0
  20. package/dist/types/components/Steps.d.ts +45 -0
  21. package/dist/types/components/Tabs.d.ts +42 -6
  22. package/dist/types/components/Toast.d.ts +46 -0
  23. package/dist/types/components/Tooltip.d.ts +22 -0
  24. package/dist/types/elements/Button.d.ts +1 -1
  25. package/dist/types/elements/Code.d.ts +9 -0
  26. package/dist/types/elements/Divider.d.ts +7 -0
  27. package/dist/types/elements/Emphasis.d.ts +9 -0
  28. package/dist/types/elements/Figure.d.ts +17 -0
  29. package/dist/types/elements/Icon.d.ts +2 -1
  30. package/dist/types/elements/Link.d.ts +10 -0
  31. package/dist/types/elements/LinkButton.d.ts +8 -0
  32. package/dist/types/elements/ListItem.d.ts +9 -0
  33. package/dist/types/elements/Notification.d.ts +31 -0
  34. package/dist/types/elements/OrderedList.d.ts +9 -0
  35. package/dist/types/elements/Paragraph.d.ts +9 -0
  36. package/dist/types/elements/Pre.d.ts +9 -0
  37. package/dist/types/elements/Span.d.ts +9 -0
  38. package/dist/types/elements/Strong.d.ts +9 -0
  39. package/dist/types/elements/UnorderedList.d.ts +9 -0
  40. package/dist/types/form/Autocomplete.d.ts +42 -0
  41. package/dist/types/form/Checkbox.d.ts +7 -2
  42. package/dist/types/form/Checkboxes.d.ts +6 -1
  43. package/dist/types/form/DateInput.d.ts +26 -0
  44. package/dist/types/form/DateInputBase.d.ts +42 -0
  45. package/dist/types/form/DateTimeInput.d.ts +26 -0
  46. package/dist/types/form/DateTimeInputBase.d.ts +50 -0
  47. package/dist/types/form/Field.d.ts +2 -1
  48. package/dist/types/form/File.d.ts +3 -2
  49. package/dist/types/form/FormContext.d.ts +22 -0
  50. package/dist/types/form/Input.d.ts +22 -11
  51. package/dist/types/form/InputBase.d.ts +16 -0
  52. package/dist/types/form/Numberinput.d.ts +30 -0
  53. package/dist/types/form/Radio.d.ts +7 -2
  54. package/dist/types/form/Radios.d.ts +6 -1
  55. package/dist/types/form/Rate.d.ts +38 -0
  56. package/dist/types/form/Select.d.ts +18 -11
  57. package/dist/types/form/SelectBase.d.ts +19 -0
  58. package/dist/types/form/Slider.d.ts +49 -0
  59. package/dist/types/form/Switch.d.ts +17 -0
  60. package/dist/types/form/Taginput.d.ts +54 -0
  61. package/dist/types/form/TextArea.d.ts +13 -14
  62. package/dist/types/form/TextAreaBase.d.ts +19 -0
  63. package/dist/types/form/TimeInput.d.ts +26 -0
  64. package/dist/types/form/TimeInputBase.d.ts +44 -0
  65. package/dist/types/form/_pickerInternals/Calendar.d.ts +26 -0
  66. package/dist/types/form/_pickerInternals/PickerPopover.d.ts +20 -0
  67. package/dist/types/form/_pickerInternals/TimeWheels.d.ts +29 -0
  68. package/dist/types/form/_pickerInternals/audioTick.d.ts +3 -0
  69. package/dist/types/form/_pickerInternals/dateUtils.d.ts +39 -0
  70. package/dist/types/form/_pickerInternals/formatters.d.ts +13 -0
  71. package/dist/types/form/_pickerInternals/haptics.d.ts +1 -0
  72. package/dist/types/form/_pickerInternals/pickerTypes.d.ts +31 -0
  73. package/dist/types/form/_pickerInternals/segmentMap.d.ts +20 -0
  74. package/dist/types/form/_pickerInternals/useFocusTrap.d.ts +7 -0
  75. package/dist/types/form/_pickerInternals/useNativeMobilePicker.d.ts +10 -0
  76. package/dist/types/form/_pickerInternals/useSegmentedEntry.d.ts +45 -0
  77. package/dist/types/form/fieldProps.d.ts +12 -0
  78. package/dist/types/helpers/bulmaClassHelpers.d.ts +35 -0
  79. package/dist/types/helpers/useBulmaClasses.d.ts +16 -83
  80. package/dist/types/helpers/useColorClasses.d.ts +8 -0
  81. package/dist/types/helpers/useFlexboxClasses.d.ts +12 -0
  82. package/dist/types/helpers/useOtherClasses.d.ts +15 -0
  83. package/dist/types/helpers/useSpacingClasses.d.ts +18 -0
  84. package/dist/types/helpers/useTypographyClasses.d.ts +19 -0
  85. package/dist/types/helpers/useVisibilityClasses.d.ts +10 -0
  86. package/dist/types/index.d.ts +53 -3
  87. package/dist/versions/bestax-bulma-prefixed.css +3 -0
  88. package/dist/versions/bestax-bulma-prefixed.css.map +1 -0
  89. package/dist/versions/bestax-bulma-prefixed.js +1 -0
  90. package/dist/versions/bestax-no-dark-mode.css +3 -0
  91. package/dist/versions/bestax-no-dark-mode.css.map +1 -0
  92. package/dist/versions/bestax-no-dark-mode.js +1 -0
  93. package/dist/versions/bestax-no-helpers-prefixed.css +3 -0
  94. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -0
  95. package/dist/versions/bestax-no-helpers-prefixed.js +1 -0
  96. package/dist/versions/bestax-no-helpers.css +3 -0
  97. package/dist/versions/bestax-no-helpers.css.map +1 -0
  98. package/dist/versions/bestax-no-helpers.js +1 -0
  99. package/dist/versions/bestax-prefixed.css +3 -0
  100. package/dist/versions/bestax-prefixed.css.map +1 -0
  101. package/dist/versions/bestax-prefixed.js +1 -0
  102. package/package.json +109 -35
  103. package/src/scss/_mixins.scss +215 -0
  104. package/src/scss/_variables.scss +94 -0
  105. package/src/scss/bestax.scss +18 -0
  106. package/src/scss/components/_carousel.scss +580 -0
  107. package/src/scss/components/_collapse.scss +126 -0
  108. package/src/scss/components/_dialog.scss +134 -0
  109. package/src/scss/components/_index.scss +13 -0
  110. package/src/scss/components/_loading.scss +231 -0
  111. package/src/scss/components/_sidebar.scss +347 -0
  112. package/src/scss/components/_steps.scss +459 -0
  113. package/src/scss/components/_tabs.scss +147 -0
  114. package/src/scss/components/_toast.scss +244 -0
  115. package/src/scss/components/_tooltip.scss +250 -0
  116. package/src/scss/elements/_index.scss +5 -0
  117. package/src/scss/elements/_linkbutton.scss +77 -0
  118. package/src/scss/extras.scss +24 -0
  119. package/src/scss/form/_autocomplete.scss +261 -0
  120. package/src/scss/form/_checkbox.scss +217 -0
  121. package/src/scss/form/_dateinput.scss +292 -0
  122. package/src/scss/form/_datetimeinput.scss +191 -0
  123. package/src/scss/form/_index.scss +16 -0
  124. package/src/scss/form/_numberinput.scss +176 -0
  125. package/src/scss/form/_picker-popover.scss +185 -0
  126. package/src/scss/form/_radio.scss +196 -0
  127. package/src/scss/form/_rate.scss +307 -0
  128. package/src/scss/form/_slider.scss +630 -0
  129. package/src/scss/form/_switch.scss +314 -0
  130. package/src/scss/form/_taginput.scss +356 -0
  131. package/src/scss/form/_timeinput.scss +374 -0
  132. package/src/scss/helpers/_cursor.scss +5 -0
  133. package/src/scss/helpers/_index.scss +2 -0
  134. package/src/scss/helpers/_sizing.scss +5 -0
  135. package/src/scss/versions/bestax-bulma-prefixed.scss +15 -0
  136. package/src/scss/versions/bestax-no-dark-mode.scss +32 -0
  137. package/src/scss/versions/bestax-no-helpers-prefixed.scss +22 -0
  138. package/src/scss/versions/bestax-no-helpers.scss +23 -0
  139. package/src/scss/versions/bestax-prefixed.scss +15 -0
@@ -0,0 +1,185 @@
1
+ @use 'bulma/sass/utilities/initial-variables' as iv;
2
+ @use 'bulma/sass/utilities/css-variables' as cv;
3
+
4
+ $picker-popover-z-index: 30 !default;
5
+ $picker-popover-background: cv.getVar('scheme-main') !default;
6
+ $picker-popover-radius: cv.getVar('radius-large') !default;
7
+ $picker-popover-shadow: 0 8px 24px hsla(0, 0%, 0%, 0.18) !default;
8
+ $picker-popover-border-color: cv.getVar('border') !default;
9
+ $picker-popover-padding: 0.75rem !default;
10
+ $picker-popover-offset: 4px !default;
11
+ $picker-popover-animation-duration: 0.15s !default;
12
+ $picker-trigger-width: 2.5em !default;
13
+ $picker-trigger-color: cv.getVar('text') !default;
14
+ $picker-trigger-hover-color: cv.getVar('text-strong') !default;
15
+
16
+ .#{iv.$class-prefix}picker-popover {
17
+ @include cv.register-vars(
18
+ (
19
+ 'picker-popover-z-index': #{$picker-popover-z-index},
20
+ 'picker-popover-background': #{$picker-popover-background},
21
+ 'picker-popover-radius': #{$picker-popover-radius},
22
+ 'picker-popover-shadow': #{$picker-popover-shadow},
23
+ 'picker-popover-border-color': #{$picker-popover-border-color},
24
+ 'picker-popover-padding': #{$picker-popover-padding},
25
+ 'picker-popover-offset': #{$picker-popover-offset},
26
+ 'picker-popover-animation-duration': #{$picker-popover-animation-duration},
27
+ )
28
+ );
29
+ }
30
+
31
+ .#{iv.$class-prefix}picker-popover {
32
+ position: absolute;
33
+ z-index: cv.getVar('picker-popover-z-index');
34
+ background-color: cv.getVar('picker-popover-background');
35
+ border: 1px solid cv.getVar('picker-popover-border-color');
36
+ border-radius: cv.getVar('picker-popover-radius');
37
+ box-shadow: cv.getVar('picker-popover-shadow');
38
+ padding: cv.getVar('picker-popover-padding');
39
+ outline: none;
40
+ animation: picker-popover-fade-in
41
+ cv.getVar('picker-popover-animation-duration') ease;
42
+
43
+ &.#{iv.$class-prefix}is-bottom-left {
44
+ top: calc(100% + cv.getVar('picker-popover-offset'));
45
+ left: 0;
46
+ }
47
+ &.#{iv.$class-prefix}is-bottom-right {
48
+ top: calc(100% + cv.getVar('picker-popover-offset'));
49
+ right: 0;
50
+ }
51
+ &.#{iv.$class-prefix}is-top-left {
52
+ bottom: calc(100% + cv.getVar('picker-popover-offset'));
53
+ left: 0;
54
+ }
55
+ &.#{iv.$class-prefix}is-top-right {
56
+ bottom: calc(100% + cv.getVar('picker-popover-offset'));
57
+ right: 0;
58
+ }
59
+ &.#{iv.$class-prefix}is-portal {
60
+ position: fixed;
61
+ }
62
+ }
63
+
64
+ @keyframes picker-popover-fade-in {
65
+ from {
66
+ opacity: 0;
67
+ transform: translateY(-2px);
68
+ }
69
+ to {
70
+ opacity: 1;
71
+ transform: translateY(0);
72
+ }
73
+ }
74
+
75
+ @media (prefers-reduced-motion: reduce) {
76
+ .#{iv.$class-prefix}picker-popover {
77
+ animation: none;
78
+ }
79
+ }
80
+
81
+ // Bulma sizes the Control's icon via `.input.is-small ~ .icon { font-size }`
82
+ // — a sibling selector. The picker bases wrap their input in a *-container
83
+ // div, so the input is no longer a direct sibling of the icon and that
84
+ // cascade is broken: the icon stays at the default font-size, leaving it
85
+ // vertically off-center inside a sized control. Restore the cascade by
86
+ // matching the icon as a sibling of the picker container instead.
87
+ $picker-containers: (
88
+ '#{iv.$class-prefix}dateinput-container',
89
+ '#{iv.$class-prefix}timeinput-container',
90
+ '#{iv.$class-prefix}datetimeinput-container'
91
+ );
92
+ @each $container in $picker-containers {
93
+ .#{iv.$class-prefix}control.#{iv.$class-prefix}is-small
94
+ .#{$container}
95
+ ~ .#{iv.$class-prefix}icon {
96
+ font-size: cv.getVar('size-small');
97
+ }
98
+ .#{iv.$class-prefix}control.#{iv.$class-prefix}is-medium
99
+ .#{$container}
100
+ ~ .#{iv.$class-prefix}icon {
101
+ font-size: cv.getVar('size-medium');
102
+ }
103
+ .#{iv.$class-prefix}control.#{iv.$class-prefix}is-large
104
+ .#{$container}
105
+ ~ .#{iv.$class-prefix}icon {
106
+ font-size: cv.getVar('size-large');
107
+ }
108
+ }
109
+
110
+ // Right-side launcher button. The picker bases render this real <button>
111
+ // inside their *-container (Bulma's Control icons are decorative —
112
+ // `pointer-events: none` — so they can't open the popover). It toggles the
113
+ // popover and is keyboard-focusable. Sizing mirrors Bulma's 2.5em icon slot
114
+ // and tracks the input's size modifier via the sibling selector.
115
+ $picker-trigger-pairs: (
116
+ ('#{iv.$class-prefix}dateinput-container' '#{iv.$class-prefix}dateinput-trigger'),
117
+ ('#{iv.$class-prefix}timeinput-container' '#{iv.$class-prefix}timeinput-trigger'),
118
+ (
119
+ '#{iv.$class-prefix}datetimeinput-container'
120
+ '#{iv.$class-prefix}datetimeinput-trigger'
121
+ )
122
+ );
123
+
124
+ @each $pair in $picker-trigger-pairs {
125
+ $container: nth($pair, 1);
126
+ $trigger: nth($pair, 2);
127
+
128
+ .#{$container} {
129
+ position: relative;
130
+ @include cv.register-vars(
131
+ (
132
+ 'picker-trigger-width': #{$picker-trigger-width},
133
+ 'picker-trigger-color': #{$picker-trigger-color},
134
+ 'picker-trigger-hover-color': #{$picker-trigger-hover-color},
135
+ )
136
+ );
137
+
138
+ // Reserve room so typed text doesn't slide under the launcher.
139
+ > .#{iv.$class-prefix}input {
140
+ padding-right: cv.getVar('picker-trigger-width');
141
+ }
142
+
143
+ > .#{$trigger} {
144
+ position: absolute;
145
+ top: 0;
146
+ right: 0;
147
+ z-index: 4;
148
+ height: 100%;
149
+ width: cv.getVar('picker-trigger-width');
150
+ display: inline-flex;
151
+ align-items: center;
152
+ justify-content: center;
153
+ padding: 0;
154
+ border: none;
155
+ background: transparent;
156
+ color: cv.getVar('picker-trigger-color');
157
+ cursor: pointer;
158
+ transition: color 0.15s ease;
159
+
160
+ .#{iv.$class-prefix}icon {
161
+ pointer-events: none;
162
+ }
163
+
164
+ &:hover:not(:disabled) {
165
+ color: cv.getVar('picker-trigger-hover-color');
166
+ }
167
+ &:disabled {
168
+ cursor: not-allowed;
169
+ opacity: 0.5;
170
+ }
171
+ }
172
+
173
+ // Match the launcher's font-size to the input's size modifier so its
174
+ // em-based width tracks the control.
175
+ > .#{iv.$class-prefix}input.#{iv.$class-prefix}is-small ~ .#{$trigger} {
176
+ font-size: cv.getVar('size-small');
177
+ }
178
+ > .#{iv.$class-prefix}input.#{iv.$class-prefix}is-medium ~ .#{$trigger} {
179
+ font-size: cv.getVar('size-medium');
180
+ }
181
+ > .#{iv.$class-prefix}input.#{iv.$class-prefix}is-large ~ .#{$trigger} {
182
+ font-size: cv.getVar('size-large');
183
+ }
184
+ }
185
+ }
@@ -0,0 +1,196 @@
1
+ // Themed Radio styles
2
+ // Custom-styled radio button with colors, sizes, and visual states
3
+ // Follows Bulma v1 CSS variable convention (see _dialog.scss)
4
+
5
+ @use "bulma/sass/utilities/initial-variables" as iv;
6
+ @use "bulma/sass/utilities/css-variables" as cv;
7
+
8
+ // Radio-specific SCSS variables
9
+ $radio-size: 1.25em !default;
10
+ $radio-border-width: 2px !default;
11
+ $radio-border-color: cv.getVar("border") !default;
12
+ $radio-background: transparent !default;
13
+ $radio-dot-color: cv.getVar("scheme-main") !default;
14
+ $radio-active-color: cv.getVar("primary") !default;
15
+ $radio-label-gap: 0.5em !default;
16
+ $radio-focus-shadow-size: 0 0 0 0.125em !default;
17
+ $radio-transition-duration: cv.getVar("duration") !default;
18
+
19
+ // Register CSS custom properties
20
+ .#{iv.$class-prefix}styled-radio {
21
+ @include cv.register-vars(
22
+ (
23
+ "radio-size": #{$radio-size},
24
+ "radio-border-width": #{$radio-border-width},
25
+ "radio-border-color": #{$radio-border-color},
26
+ "radio-background": #{$radio-background},
27
+ "radio-dot-color": #{$radio-dot-color},
28
+ "radio-active-color": #{$radio-active-color},
29
+ "radio-label-gap": #{$radio-label-gap},
30
+ "radio-focus-shadow-size": #{$radio-focus-shadow-size},
31
+ "radio-transition-duration": #{$radio-transition-duration},
32
+ )
33
+ );
34
+ }
35
+
36
+ // Main radio label
37
+ .#{iv.$class-prefix}styled-radio {
38
+ display: inline-flex;
39
+ align-items: center;
40
+ cursor: pointer;
41
+ position: relative;
42
+ user-select: none;
43
+ line-height: 1.5;
44
+
45
+ // Hidden native input
46
+ input[type="radio"] {
47
+ position: absolute;
48
+ opacity: 0;
49
+ width: 0;
50
+ height: 0;
51
+
52
+ // Checked state
53
+ &:checked + .check {
54
+ border-color: cv.getVar("radio-active-color");
55
+
56
+ // Inner dot
57
+ &::before {
58
+ opacity: 1;
59
+ transform: translate(-50%, -50%) scale(1);
60
+ }
61
+ }
62
+
63
+ // Focus-visible state (keyboard only)
64
+ &:focus-visible + .check {
65
+ outline: 2px solid cv.getVar("radio-active-color");
66
+ outline-offset: 2px;
67
+ }
68
+
69
+ // Disabled state
70
+ &:disabled + .check {
71
+ opacity: 0.5;
72
+ cursor: not-allowed;
73
+ }
74
+
75
+ &:disabled ~ .control-label {
76
+ opacity: 0.5;
77
+ cursor: not-allowed;
78
+ }
79
+ }
80
+
81
+ // Custom radio indicator
82
+ .check {
83
+ display: inline-flex;
84
+ align-items: center;
85
+ justify-content: center;
86
+ flex-shrink: 0;
87
+ position: relative;
88
+ width: cv.getVar("radio-size");
89
+ height: cv.getVar("radio-size");
90
+ min-width: 24px;
91
+ min-height: 24px;
92
+ background-color: cv.getVar("radio-background");
93
+ border: cv.getVar("radio-border-width") solid cv.getVar("radio-border-color");
94
+ border-radius: 50%;
95
+ transition-property: border-color;
96
+ transition-duration: cv.getVar("radio-transition-duration");
97
+ transition-timing-function: ease;
98
+
99
+ // Inner dot
100
+ &::before {
101
+ content: "";
102
+ position: absolute;
103
+ top: 50%;
104
+ left: 50%;
105
+ width: 50%;
106
+ height: 50%;
107
+ border-radius: 50%;
108
+ background-color: cv.getVar("radio-active-color");
109
+ opacity: 0;
110
+ transform: translate(-50%, -50%) scale(0.5);
111
+ transition-property: opacity, transform;
112
+ transition-duration: cv.getVar("radio-transition-duration");
113
+ transition-timing-function: ease;
114
+ }
115
+ }
116
+
117
+ // Label text
118
+ .control-label {
119
+ margin-left: cv.getVar("radio-label-gap");
120
+ line-height: 1.5;
121
+ }
122
+ }
123
+
124
+ // Color variants
125
+ @each $name in "primary", "link", "info", "success", "warning", "danger" {
126
+ .#{iv.$class-prefix}styled-radio.#{iv.$class-prefix}is-#{$name} {
127
+ @include cv.register-vars(
128
+ (
129
+ "radio-active-color": #{cv.getVar($name)},
130
+ )
131
+ );
132
+ }
133
+ }
134
+
135
+ // Size variants
136
+ .#{iv.$class-prefix}styled-radio.#{iv.$class-prefix}is-small {
137
+ font-size: cv.getVar("size-small");
138
+ }
139
+
140
+ .#{iv.$class-prefix}styled-radio.#{iv.$class-prefix}is-medium {
141
+ font-size: cv.getVar("size-medium");
142
+ }
143
+
144
+ .#{iv.$class-prefix}styled-radio.#{iv.$class-prefix}is-large {
145
+ font-size: cv.getVar("size-large");
146
+ }
147
+
148
+ // High Contrast Mode support
149
+ @media (forced-colors: active) {
150
+ .#{iv.$class-prefix}styled-radio {
151
+ .check {
152
+ border-color: ButtonText;
153
+ }
154
+
155
+ input[type="radio"]:checked + .check {
156
+ border-color: Highlight;
157
+
158
+ &::before {
159
+ background-color: Highlight;
160
+ }
161
+ }
162
+
163
+ input[type="radio"]:focus-visible + .check {
164
+ outline-color: Highlight;
165
+ }
166
+
167
+ input[type="radio"]:disabled + .check {
168
+ border-color: GrayText;
169
+ }
170
+ }
171
+ }
172
+
173
+ // Reduced motion
174
+ @media (prefers-reduced-motion: reduce) {
175
+ .#{iv.$class-prefix}styled-radio {
176
+ .check,
177
+ .check::before {
178
+ transition: none;
179
+ }
180
+ }
181
+ }
182
+
183
+ // Vertical alignment for horizontal-field layouts.
184
+ // Bulma applies `padding-top: 0.375em` to `.field-label.is-normal` so its
185
+ // baseline aligns with the text inside `.input`. Our themed radios have no
186
+ // internal padding, so without this match they sit ~6px higher than the
187
+ // field-label and look misaligned. Apply the same padding on the radios
188
+ // wrapper, but only inside a horizontal field-body so vertical/standalone
189
+ // usage is unaffected.
190
+ .#{iv.$class-prefix}field.#{iv.$class-prefix}is-horizontal {
191
+ .#{iv.$class-prefix}field-body {
192
+ .#{iv.$class-prefix}radios {
193
+ padding-top: 0.375em;
194
+ }
195
+ }
196
+ }
@@ -0,0 +1,307 @@
1
+ // Rate Component Styles
2
+ // A star/icon-based rating component
3
+ // Follows Bulma v1 CSS variable convention (see _dialog.scss, _checkbox.scss)
4
+
5
+ @use "bulma/sass/utilities/initial-variables" as iv;
6
+ @use "bulma/sass/utilities/css-variables" as cv;
7
+
8
+ // Rate-specific SCSS variables
9
+ $rate-color-inactive: cv.getVar("grey-light") !default;
10
+ $rate-color-active: hsl(48, 100%, 50%) !default;
11
+ $rate-color-hover: hsl(48, 100%, 67%) !default;
12
+ $rate-icon-size: 1.5em !default;
13
+ $rate-icon-size-small: 1em !default;
14
+ $rate-icon-size-medium: 2em !default;
15
+ $rate-icon-size-large: 2.5em !default;
16
+ $rate-font-icon-size: 1.35em !default;
17
+ $rate-font-icon-size-small: 0.9em !default;
18
+ $rate-font-icon-size-medium: 1.8em !default;
19
+ $rate-font-icon-size-large: 2.25em !default;
20
+ $rate-gap: 0.5rem !default;
21
+ $rate-spaced-gap: 0.25rem !default;
22
+ $rate-score-weight: 600 !default;
23
+ $rate-score-color: cv.getVar("text-strong") !default;
24
+ $rate-text-color: cv.getVar("text") !default;
25
+ $rate-text-size: 0.875em !default;
26
+ $rate-transition-duration: cv.getVar("duration") !default;
27
+ $rate-disabled-opacity: 0.5 !default;
28
+ $rate-pop-scale: 1.2 !default;
29
+
30
+ // Register CSS custom properties
31
+ .#{iv.$class-prefix}rate {
32
+ @include cv.register-vars(
33
+ (
34
+ "rate-color-inactive": #{$rate-color-inactive},
35
+ "rate-color-active": #{$rate-color-active},
36
+ "rate-color-hover": #{$rate-color-hover},
37
+ "rate-icon-size": #{$rate-icon-size},
38
+ "rate-icon-size-small": #{$rate-icon-size-small},
39
+ "rate-icon-size-medium": #{$rate-icon-size-medium},
40
+ "rate-icon-size-large": #{$rate-icon-size-large},
41
+ "rate-font-icon-size": #{$rate-font-icon-size},
42
+ "rate-font-icon-size-small": #{$rate-font-icon-size-small},
43
+ "rate-font-icon-size-medium": #{$rate-font-icon-size-medium},
44
+ "rate-font-icon-size-large": #{$rate-font-icon-size-large},
45
+ "rate-gap": #{$rate-gap},
46
+ "rate-spaced-gap": #{$rate-spaced-gap},
47
+ "rate-score-weight": #{$rate-score-weight},
48
+ "rate-score-color": #{$rate-score-color},
49
+ "rate-text-color": #{$rate-text-color},
50
+ "rate-text-size": #{$rate-text-size},
51
+ "rate-transition-duration": #{$rate-transition-duration},
52
+ "rate-disabled-opacity": #{$rate-disabled-opacity},
53
+ "rate-pop-scale": #{$rate-pop-scale},
54
+ )
55
+ );
56
+ }
57
+
58
+ // Main container
59
+ .#{iv.$class-prefix}rate {
60
+ display: inline-flex;
61
+ align-items: center;
62
+ gap: cv.getVar("rate-gap");
63
+ min-height: cv.getVar("control-height");
64
+ outline: none;
65
+
66
+ &:focus-visible {
67
+ outline: 2px solid cv.getVar("link");
68
+ outline-offset: 2px;
69
+ border-radius: cv.getVar("radius");
70
+ }
71
+ }
72
+
73
+ // Icons container
74
+ .#{iv.$class-prefix}rate-items {
75
+ display: inline-flex;
76
+ align-items: center;
77
+ gap: 0.125rem;
78
+ }
79
+
80
+ // Individual icon
81
+ .#{iv.$class-prefix}rate-item {
82
+ display: inline-flex;
83
+ align-items: center;
84
+ justify-content: center;
85
+ cursor: pointer;
86
+ color: cv.getVar("rate-color-inactive");
87
+ transition: color cv.getVar("rate-transition-duration") ease,
88
+ transform 0.1s ease;
89
+
90
+ svg {
91
+ width: cv.getVar("rate-icon-size");
92
+ height: cv.getVar("rate-icon-size");
93
+ }
94
+
95
+ // Font icon sizing — tuned for MDI/Material which are designed for 24px grid.
96
+ // FA has a wider star glyph (~12.5% beyond em-box) so it gets scaled down.
97
+ .#{iv.$class-prefix}icon {
98
+ font-size: cv.getVar("rate-font-icon-size");
99
+ overflow: hidden;
100
+
101
+ .fas, .far, .fab, .fal, .fad, .fat,
102
+ .fa-solid, .fa-regular, .fa-brands, .fa-light, .fa-duotone, .fa-thin {
103
+ font-size: 0.88em;
104
+ }
105
+ }
106
+
107
+
108
+ &:hover:not(.#{iv.$class-prefix}is-active) {
109
+ color: cv.getVar("rate-color-hover");
110
+ transform: scale(1.1);
111
+ }
112
+
113
+ &.#{iv.$class-prefix}is-active {
114
+ color: cv.getVar("rate-color-active");
115
+ }
116
+
117
+ &.#{iv.$class-prefix}is-hovered {
118
+ color: cv.getVar("rate-color-hover");
119
+ transform: scale(1.1);
120
+ }
121
+ }
122
+
123
+ // Partial fill (precision < 1)
124
+ .#{iv.$class-prefix}rate-icon-partial {
125
+ position: relative;
126
+ display: inline-flex;
127
+ align-items: center;
128
+ justify-content: center;
129
+ }
130
+
131
+ .#{iv.$class-prefix}rate-icon-bg {
132
+ color: cv.getVar("rate-color-inactive");
133
+ }
134
+
135
+ .#{iv.$class-prefix}rate-icon-fg {
136
+ position: absolute;
137
+ top: 0;
138
+ left: 0;
139
+ overflow: hidden;
140
+ width: var(--rate-fill-percent, 100%);
141
+ color: cv.getVar("rate-color-active");
142
+ }
143
+
144
+ // Score display
145
+ .#{iv.$class-prefix}rate-score {
146
+ font-weight: cv.getVar("rate-score-weight");
147
+ color: cv.getVar("rate-score-color");
148
+ min-width: 2em;
149
+ text-align: center;
150
+ }
151
+
152
+ // Text display
153
+ .#{iv.$class-prefix}rate-text {
154
+ color: cv.getVar("rate-text-color");
155
+ font-size: cv.getVar("rate-text-size");
156
+ }
157
+
158
+ // Custom text display
159
+ .#{iv.$class-prefix}rate-custom-text {
160
+ color: cv.getVar("rate-text-color");
161
+ font-size: cv.getVar("rate-text-size");
162
+ }
163
+
164
+ // Disabled state
165
+ .#{iv.$class-prefix}rate.#{iv.$class-prefix}is-disabled {
166
+ opacity: cv.getVar("rate-disabled-opacity");
167
+ pointer-events: none;
168
+
169
+ .#{iv.$class-prefix}rate-item {
170
+ cursor: not-allowed;
171
+ }
172
+ }
173
+
174
+ // Spaced variant
175
+ .#{iv.$class-prefix}rate.#{iv.$class-prefix}is-spaced {
176
+ .#{iv.$class-prefix}rate-items {
177
+ gap: cv.getVar("rate-spaced-gap");
178
+ }
179
+ }
180
+
181
+ // RTL support
182
+ .#{iv.$class-prefix}rate.#{iv.$class-prefix}is-rtl {
183
+ .#{iv.$class-prefix}rate-items {
184
+ flex-direction: row-reverse;
185
+ }
186
+ }
187
+
188
+ // Size variants
189
+ .#{iv.$class-prefix}rate.#{iv.$class-prefix}is-small {
190
+ .#{iv.$class-prefix}rate-item {
191
+ svg {
192
+ width: cv.getVar("rate-icon-size-small");
193
+ height: cv.getVar("rate-icon-size-small");
194
+ }
195
+
196
+ .#{iv.$class-prefix}icon {
197
+ font-size: cv.getVar("rate-font-icon-size-small");
198
+ }
199
+ }
200
+
201
+ .#{iv.$class-prefix}rate-score {
202
+ font-size: cv.getVar("size-small");
203
+ }
204
+
205
+ .#{iv.$class-prefix}rate-text,
206
+ .#{iv.$class-prefix}rate-custom-text {
207
+ font-size: 0.75rem;
208
+ }
209
+ }
210
+
211
+ .#{iv.$class-prefix}rate.#{iv.$class-prefix}is-medium {
212
+ .#{iv.$class-prefix}rate-item {
213
+ svg {
214
+ width: cv.getVar("rate-icon-size-medium");
215
+ height: cv.getVar("rate-icon-size-medium");
216
+ }
217
+
218
+ .#{iv.$class-prefix}icon {
219
+ font-size: cv.getVar("rate-font-icon-size-medium");
220
+ }
221
+ }
222
+
223
+ .#{iv.$class-prefix}rate-score {
224
+ font-size: cv.getVar("size-medium");
225
+ }
226
+
227
+ .#{iv.$class-prefix}rate-text,
228
+ .#{iv.$class-prefix}rate-custom-text {
229
+ font-size: 1rem;
230
+ }
231
+ }
232
+
233
+ .#{iv.$class-prefix}rate.#{iv.$class-prefix}is-large {
234
+ .#{iv.$class-prefix}rate-item {
235
+ svg {
236
+ width: cv.getVar("rate-icon-size-large");
237
+ height: cv.getVar("rate-icon-size-large");
238
+ }
239
+
240
+ .#{iv.$class-prefix}icon {
241
+ font-size: cv.getVar("rate-font-icon-size-large");
242
+ }
243
+ }
244
+
245
+ .#{iv.$class-prefix}rate-score {
246
+ font-size: cv.getVar("size-large");
247
+ }
248
+
249
+ .#{iv.$class-prefix}rate-text,
250
+ .#{iv.$class-prefix}rate-custom-text {
251
+ font-size: 1.125rem;
252
+ }
253
+ }
254
+
255
+ // Animation on selection
256
+ .#{iv.$class-prefix}rate-item.#{iv.$class-prefix}is-active {
257
+ animation: rate-pop 0.2s ease;
258
+ }
259
+
260
+ @keyframes rate-pop {
261
+ 0% {
262
+ transform: scale(1);
263
+ }
264
+ 50% {
265
+ transform: scale(cv.getVar("rate-pop-scale"));
266
+ }
267
+ 100% {
268
+ transform: scale(1);
269
+ }
270
+ }
271
+
272
+ // Color variants
273
+ @each $name in "primary", "link", "info", "success", "warning", "danger" {
274
+ .#{iv.$class-prefix}rate.#{iv.$class-prefix}is-#{$name} {
275
+ @include cv.register-vars(
276
+ (
277
+ "rate-color-active": #{cv.getVar($name)},
278
+ "rate-color-hover": #{cv.getVar("#{$name}-light")},
279
+ )
280
+ );
281
+ }
282
+ }
283
+
284
+ // High Contrast Mode support
285
+ @media (forced-colors: active) {
286
+ .#{iv.$class-prefix}rate {
287
+ .#{iv.$class-prefix}rate-item {
288
+ color: ButtonText;
289
+
290
+ &.#{iv.$class-prefix}is-active {
291
+ color: Highlight;
292
+ }
293
+ }
294
+
295
+ &:focus-visible {
296
+ outline-color: Highlight;
297
+ }
298
+ }
299
+ }
300
+
301
+ // Reduced motion
302
+ @media (prefers-reduced-motion: reduce) {
303
+ .#{iv.$class-prefix}rate-item {
304
+ transition: none;
305
+ animation: none;
306
+ }
307
+ }