@actabldesign/bellhop-styles 0.0.3 → 0.0.12

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 (127) hide show
  1. package/README.md +105 -70
  2. package/dist/index.css +1538 -0
  3. package/dist/utilities.css +5730 -0
  4. package/llms.txt +2852 -0
  5. package/package.json +29 -20
  6. package/project.json +29 -0
  7. package/rollup.config.js +44 -0
  8. package/{base → src/base}/normalize.css +4 -0
  9. package/src/bh-tokens/_primitives.scss +296 -0
  10. package/src/bh-tokens/_semantic.scss +158 -0
  11. package/src/bh-tokens/components/_avatar.tokens.scss +64 -0
  12. package/src/bh-tokens/components/_badge-dot.tokens.scss +33 -0
  13. package/src/bh-tokens/components/_badge.tokens.scss +61 -0
  14. package/src/bh-tokens/components/_button-icon.tokens.scss +65 -0
  15. package/src/bh-tokens/components/_button.tokens.scss +185 -0
  16. package/src/bh-tokens/components/_checkbox.tokens.scss +67 -0
  17. package/src/bh-tokens/components/_dropdown.tokens.scss +103 -0
  18. package/src/bh-tokens/components/_featured-icon.tokens.scss +57 -0
  19. package/src/bh-tokens/components/_input-number.tokens.scss +50 -0
  20. package/src/bh-tokens/components/_input.tokens.scss +86 -0
  21. package/src/bh-tokens/components/_label.tokens.scss +37 -0
  22. package/src/bh-tokens/components/_modal.tokens.scss +42 -0
  23. package/src/bh-tokens/components/_pagination.tokens.scss +104 -0
  24. package/src/bh-tokens/components/_password.tokens.scss +63 -0
  25. package/src/bh-tokens/components/_progress-bar.tokens.scss +34 -0
  26. package/src/bh-tokens/components/_progress-spinner.tokens.scss +51 -0
  27. package/src/bh-tokens/components/_radiobutton.tokens.scss +90 -0
  28. package/src/bh-tokens/components/_skeleton.tokens.scss +22 -0
  29. package/src/bh-tokens/components/_textarea.tokens.scss +76 -0
  30. package/src/bh-tokens/components/_toggle.tokens.scss +74 -0
  31. package/src/bh-tokens/components/avatar.scss +288 -0
  32. package/src/bh-tokens/components/badge-dot.scss +177 -0
  33. package/src/bh-tokens/components/badge.scss +497 -0
  34. package/src/bh-tokens/components/button-icon.scss +227 -0
  35. package/src/bh-tokens/components/button.scss +640 -0
  36. package/src/bh-tokens/components/checkbox.scss +254 -0
  37. package/src/bh-tokens/components/dropdown.scss +231 -0
  38. package/src/bh-tokens/components/featured-icon.scss +219 -0
  39. package/src/bh-tokens/components/input-number.scss +147 -0
  40. package/src/bh-tokens/components/input.scss +271 -0
  41. package/src/bh-tokens/components/label.scss +176 -0
  42. package/src/bh-tokens/components/modal.scss +103 -0
  43. package/src/bh-tokens/components/pagination.scss +324 -0
  44. package/src/bh-tokens/components/password.scss +193 -0
  45. package/src/bh-tokens/components/progress-bar.scss +124 -0
  46. package/src/bh-tokens/components/progress-spinner.scss +130 -0
  47. package/src/bh-tokens/components/radiobutton.scss +193 -0
  48. package/src/bh-tokens/components/skeleton.scss +50 -0
  49. package/src/bh-tokens/components/textarea.scss +228 -0
  50. package/src/bh-tokens/components/toggle.scss +320 -0
  51. package/src/index.css +22 -0
  52. package/src/mixins/_responsive.scss +167 -0
  53. package/src/tokens/bellhop-animations.css +392 -0
  54. package/src/tokens/bellhop-global.css +175 -0
  55. package/src/tokens/bellhop-icons.css +77 -0
  56. package/src/tokens/bellhop-layout.css +216 -0
  57. package/src/tokens/bellhop-primary-colors.css +96 -0
  58. package/src/tokens/bellhop-radius.css +14 -0
  59. package/src/tokens/bellhop-secondary-colors.css +154 -0
  60. package/src/tokens/bellhop-shadows.css +55 -0
  61. package/src/tokens/bellhop-spacing.css +66 -0
  62. package/src/tokens/bellhop-styles.css +174 -0
  63. package/src/tokens/bellhop-typography.css +146 -0
  64. package/src/tokens/colors.json +737 -0
  65. package/src/tokens/colors.mdx +59 -0
  66. package/src/tokens/index.css +17 -0
  67. package/src/utilities/_breakpoints.scss +19 -0
  68. package/src/utilities/_flex.scss +228 -0
  69. package/src/utilities/_grid.scss +189 -0
  70. package/src/utilities/_index.scss +32 -0
  71. package/src/utilities/_scrollable.scss +239 -0
  72. package/src/utilities/_sizing.scss +229 -0
  73. package/src/utilities/_spacing.scss +187 -0
  74. package/src/utilities/_truncation.scss +126 -0
  75. package/src/utilities/_visibility.scss +117 -0
  76. package/src/utilities.scss +32 -0
  77. package/components/appbar.css +0 -167
  78. package/components/autocomplete-menu.css +0 -142
  79. package/components/avatar-add.css +0 -112
  80. package/components/avatar.css +0 -253
  81. package/components/badge-dot.css +0 -78
  82. package/components/badge.css +0 -337
  83. package/components/bar-chart-card.css +0 -261
  84. package/components/bar-chart.css +0 -149
  85. package/components/breadcrumbs.css +0 -136
  86. package/components/button.css +0 -266
  87. package/components/chart-tooltip.css +0 -96
  88. package/components/checkbox-label.css +0 -53
  89. package/components/checkbox.css +0 -127
  90. package/components/container-footer.css +0 -22
  91. package/components/container.css +0 -17
  92. package/components/date-picker-content.css +0 -337
  93. package/components/date-picker.css +0 -103
  94. package/components/date-range-picker-content.css +0 -85
  95. package/components/date-range-picker.css +0 -72
  96. package/components/dropdown-menu.css +0 -204
  97. package/components/dropdown.css +0 -126
  98. package/components/empty-state.css +0 -83
  99. package/components/featured-icon.css +0 -194
  100. package/components/illustrations.css +0 -120
  101. package/components/input-autocomplete.css +0 -158
  102. package/components/input-number.css +0 -2
  103. package/components/input-verification.css +0 -137
  104. package/components/input.css +0 -374
  105. package/components/loader-spinner.css +0 -421
  106. package/components/logo-box.css +0 -85
  107. package/components/month-picker-content.css +0 -190
  108. package/components/month-picker.css +0 -83
  109. package/components/nav-item.css +0 -110
  110. package/components/notification.css +0 -262
  111. package/components/page-navigation.css +0 -294
  112. package/components/picker-menu.css +0 -43
  113. package/components/pie-chart-card.css +0 -213
  114. package/components/pie-chart.css +0 -80
  115. package/components/product-switcher.css +0 -127
  116. package/components/property-switcher.css +0 -95
  117. package/components/radio-button-label.css +0 -53
  118. package/components/radio-button.css +0 -134
  119. package/components/sidebar.css +0 -178
  120. package/components/skeleton-loader.css +0 -47
  121. package/components/tag.css +0 -214
  122. package/components/textarea.css +0 -211
  123. package/components/toggle.css +0 -298
  124. package/components/tooltip.css +0 -85
  125. package/components/trend-chart-card.css +0 -189
  126. package/components/trend-chart.css +0 -94
  127. package/index.css +0 -8115
@@ -0,0 +1,320 @@
1
+ /* ==========================================================================
2
+ BH-TOGGLE COMPONENT STYLES - Material You Design
3
+ Uses tokens from _toggle.tokens.scss
4
+ ========================================================================== */
5
+
6
+ @use './_toggle.tokens.scss';
7
+
8
+ :host {
9
+ display: inline-block;
10
+ }
11
+
12
+ /* ==========================================================================
13
+ TOGGLE WRAPPER
14
+ ========================================================================== */
15
+
16
+ .toggle-wrapper {
17
+ display: flex;
18
+ align-items: center;
19
+ gap: 0;
20
+ }
21
+
22
+ .toggle-with-text.toggle-size-sm {
23
+ gap: var(--bh-toggle-gap-with-text-sm);
24
+ }
25
+
26
+ .toggle-with-text.toggle-size-md {
27
+ gap: var(--bh-toggle-gap-with-text-md);
28
+ }
29
+
30
+ /* ==========================================================================
31
+ TOGGLE SWITCH BASE
32
+ ========================================================================== */
33
+
34
+ .toggle-switch {
35
+ position: relative;
36
+ display: inline-block;
37
+ border-radius: var(--bh-toggle-border-radius);
38
+ cursor: pointer;
39
+ transition: var(--bh-toggle-transition);
40
+ outline: none;
41
+ border: 1px solid transparent;
42
+ background: transparent;
43
+ overflow: visible;
44
+ padding: 0;
45
+ }
46
+
47
+ .toggle-switch:focus {
48
+ outline: none;
49
+ }
50
+
51
+ .toggle-switch.toggle-disabled {
52
+ cursor: not-allowed;
53
+ opacity: var(--bh-toggle-disabled-opacity);
54
+ }
55
+
56
+ /* ==========================================================================
57
+ TOGGLE SWITCH SIZES
58
+ ========================================================================== */
59
+
60
+ .toggle-switch.toggle-sm {
61
+ width: var(--bh-toggle-width-sm);
62
+ height: var(--bh-toggle-height-sm);
63
+ }
64
+
65
+ .toggle-switch.toggle-md {
66
+ width: var(--bh-toggle-width-md);
67
+ height: var(--bh-toggle-height-md);
68
+ }
69
+
70
+ /* ==========================================================================
71
+ TOGGLE SWITCH STATES - UNPRESSED (FALSE)
72
+ ========================================================================== */
73
+
74
+ .toggle-switch.toggle-unpressed {
75
+ background-color: var(--bh-toggle-unpressed-bg);
76
+ border-color: transparent;
77
+ }
78
+
79
+ .toggle-switch.toggle-unpressed.toggle-hover {
80
+ background-color: var(--bh-toggle-unpressed-bg-hover);
81
+ border-color: transparent;
82
+ }
83
+
84
+ .toggle-switch.toggle-unpressed.toggle-focus {
85
+ background-color: var(--bh-toggle-unpressed-bg-focus);
86
+ border-color: transparent;
87
+ }
88
+
89
+ /* Focus ring for unpressed state */
90
+ .toggle-switch.toggle-unpressed.toggle-focus .toggle-button::after {
91
+ content: '';
92
+ position: absolute;
93
+ top: var(--bh-toggle-focus-ring-offset);
94
+ left: var(--bh-toggle-focus-ring-offset);
95
+ right: var(--bh-toggle-focus-ring-offset);
96
+ bottom: var(--bh-toggle-focus-ring-offset);
97
+ border-radius: var(--bh-toggle-border-radius);
98
+ background: var(--bh-toggle-unpressed-focus-ring);
99
+ opacity: var(--bh-toggle-unpressed-focus-ring-opacity);
100
+ pointer-events: none;
101
+ }
102
+
103
+ .toggle-switch.toggle-unpressed.toggle-disabled {
104
+ background-color: var(--bh-toggle-unpressed-bg-disabled);
105
+ border-color: transparent;
106
+ }
107
+
108
+ /* ==========================================================================
109
+ TOGGLE SWITCH STATES - PRESSED (TRUE)
110
+ ========================================================================== */
111
+
112
+ .toggle-switch.toggle-pressed {
113
+ background-color: var(--bh-toggle-pressed-bg);
114
+ border-color: var(--bh-toggle-pressed-bg);
115
+ }
116
+
117
+ .toggle-switch.toggle-pressed.toggle-hover {
118
+ background-color: var(--bh-toggle-pressed-bg-hover);
119
+ border-color: var(--bh-toggle-pressed-bg-hover);
120
+ }
121
+
122
+ .toggle-switch.toggle-pressed.toggle-focus {
123
+ background-color: var(--bh-toggle-pressed-bg-focus);
124
+ border-color: var(--bh-toggle-pressed-bg-focus);
125
+ }
126
+
127
+ /* Focus ring for pressed state */
128
+ .toggle-switch.toggle-pressed.toggle-focus .toggle-button::after {
129
+ content: '';
130
+ position: absolute;
131
+ top: var(--bh-toggle-focus-ring-offset);
132
+ left: var(--bh-toggle-focus-ring-offset);
133
+ right: var(--bh-toggle-focus-ring-offset);
134
+ bottom: var(--bh-toggle-focus-ring-offset);
135
+ border-radius: var(--bh-toggle-border-radius);
136
+ background: var(--bh-toggle-pressed-focus-ring);
137
+ opacity: var(--bh-toggle-pressed-focus-ring-opacity);
138
+ pointer-events: none;
139
+ }
140
+
141
+ .toggle-switch.toggle-pressed.toggle-disabled {
142
+ background-color: var(--bh-toggle-pressed-bg-disabled);
143
+ border-color: var(--bh-toggle-pressed-bg-disabled);
144
+ }
145
+
146
+ .toggle-switch.toggle-pressed.toggle-disabled .toggle-button {
147
+ background-color: var(--bh-toggle-button-bg-disabled-pressed);
148
+ }
149
+
150
+ /* ==========================================================================
151
+ TOGGLE BUTTON (HANDLE)
152
+ ========================================================================== */
153
+
154
+ .toggle-button {
155
+ position: absolute;
156
+ top: 50%;
157
+ transform: translateY(-50%);
158
+ border-radius: var(--bh-toggle-border-radius);
159
+ background-color: var(--bh-toggle-button-bg);
160
+ transition: var(--bh-toggle-button-transition);
161
+ }
162
+
163
+ /* Toggle Button States - Unpressed */
164
+ .toggle-switch.toggle-unpressed .toggle-button {
165
+ background-color: var(--bh-toggle-button-bg);
166
+ }
167
+
168
+ .toggle-switch.toggle-sm.toggle-unpressed .toggle-button {
169
+ width: var(--bh-toggle-button-size-sm);
170
+ height: var(--bh-toggle-button-size-sm);
171
+ left: var(--bh-toggle-button-offset-sm);
172
+ }
173
+
174
+ .toggle-switch.toggle-md.toggle-unpressed .toggle-button {
175
+ width: var(--bh-toggle-button-size-md);
176
+ height: var(--bh-toggle-button-size-md);
177
+ left: var(--bh-toggle-button-offset-md);
178
+ }
179
+
180
+ .toggle-switch.toggle-unpressed.toggle-hover .toggle-button {
181
+ background-color: var(--bh-toggle-button-bg);
182
+ box-shadow: var(--bh-toggle-button-shadow-hover);
183
+ }
184
+
185
+ /* Toggle Button States - Pressed */
186
+ .toggle-switch.toggle-pressed .toggle-button {
187
+ background-color: var(--bh-toggle-button-bg);
188
+ }
189
+
190
+ .toggle-switch.toggle-sm.toggle-pressed .toggle-button {
191
+ width: var(--bh-toggle-button-size-sm);
192
+ height: var(--bh-toggle-button-size-sm);
193
+ left: calc(100% - var(--bh-toggle-button-size-sm) - var(--bh-toggle-button-offset-sm));
194
+ }
195
+
196
+ .toggle-switch.toggle-md.toggle-pressed .toggle-button {
197
+ width: var(--bh-toggle-button-size-md);
198
+ height: var(--bh-toggle-button-size-md);
199
+ left: calc(100% - var(--bh-toggle-button-size-md) - var(--bh-toggle-button-offset-md));
200
+ }
201
+
202
+ .toggle-switch.toggle-pressed.toggle-hover .toggle-button {
203
+ background-color: var(--bh-toggle-button-bg);
204
+ }
205
+
206
+ /* Toggle Button Disabled State */
207
+ .toggle-switch.toggle-disabled .toggle-button {
208
+ background-color: var(--bh-toggle-button-bg-disabled);
209
+ box-shadow: none;
210
+ }
211
+
212
+ .toggle-switch.toggle-sm.toggle-unpressed.toggle-disabled .toggle-button {
213
+ width: var(--bh-toggle-button-size-sm);
214
+ height: var(--bh-toggle-button-size-sm);
215
+ left: calc(var(--bh-toggle-button-offset-sm) + 1px);
216
+ background-color: var(--bh-toggle-button-bg-disabled);
217
+ }
218
+
219
+ .toggle-switch.toggle-md.toggle-unpressed.toggle-disabled .toggle-button {
220
+ width: var(--bh-toggle-button-disabled-size-md);
221
+ height: var(--bh-toggle-button-disabled-size-md);
222
+ left: var(--bh-toggle-button-disabled-offset-md);
223
+ background-color: var(--bh-toggle-button-bg-disabled);
224
+ }
225
+
226
+ .toggle-switch.toggle-sm.toggle-pressed.toggle-disabled .toggle-button {
227
+ width: var(--bh-toggle-button-size-sm);
228
+ height: var(--bh-toggle-button-size-sm);
229
+ left: calc(100% - var(--bh-toggle-button-size-sm) - var(--bh-toggle-button-offset-sm));
230
+ background-color: var(--bh-toggle-button-bg-disabled);
231
+ }
232
+
233
+ .toggle-switch.toggle-md.toggle-pressed.toggle-disabled .toggle-button {
234
+ width: var(--bh-toggle-button-size-md);
235
+ height: var(--bh-toggle-button-size-md);
236
+ left: calc(100% - var(--bh-toggle-button-size-md) - var(--bh-toggle-button-offset-md));
237
+ background-color: var(--bh-toggle-button-bg);
238
+ }
239
+
240
+ /* ==========================================================================
241
+ TOGGLE TEXT CONTAINER
242
+ ========================================================================== */
243
+
244
+ .toggle-text {
245
+ display: flex;
246
+ flex-direction: column;
247
+ flex: 1;
248
+ }
249
+
250
+ /* ==========================================================================
251
+ TOGGLE LABEL
252
+ ========================================================================== */
253
+
254
+ .toggle-label {
255
+ color: var(--bh-toggle-label-color);
256
+ font-family: var(--bh-font-family);
257
+ font-weight: var(--bh-toggle-label-font-weight);
258
+ text-align: left;
259
+ margin: 0;
260
+ line-height: var(--bh-toggle-label-line-height);
261
+ }
262
+
263
+ .toggle-label.toggle-label-sm {
264
+ font-size: var(--bh-toggle-label-size-sm);
265
+ line-height: 1.43em;
266
+ }
267
+
268
+ .toggle-label.toggle-label-md {
269
+ font-size: var(--bh-toggle-label-size-md);
270
+ line-height: 1.5em;
271
+ }
272
+
273
+ /* ==========================================================================
274
+ TOGGLE SUPPORTING TEXT
275
+ ========================================================================== */
276
+
277
+ .toggle-supporting-text {
278
+ color: var(--bh-toggle-supporting-text-color);
279
+ font-family: var(--bh-font-family);
280
+ font-weight: var(--bh-toggle-supporting-text-font-weight);
281
+ font-size: var(--bh-toggle-supporting-text-size);
282
+ line-height: 1.43em;
283
+ text-align: left;
284
+ margin: 0;
285
+ margin-top: var(--bh-toggle-supporting-text-margin-top);
286
+ }
287
+
288
+ /* ==========================================================================
289
+ ACCESSIBILITY
290
+ ========================================================================== */
291
+
292
+ @media (prefers-reduced-motion: reduce) {
293
+ .toggle-switch,
294
+ .toggle-button {
295
+ transition: none;
296
+ }
297
+ }
298
+
299
+ @media (prefers-contrast: high) {
300
+ .toggle-switch.toggle-unpressed {
301
+ border: var(--bh-toggle-high-contrast-border-width) solid currentColor;
302
+ }
303
+
304
+ .toggle-switch.toggle-pressed {
305
+ border: var(--bh-toggle-high-contrast-border-width) solid currentColor;
306
+ }
307
+ }
308
+
309
+ .toggle-switch:focus-visible .toggle-button::after {
310
+ content: '';
311
+ position: absolute;
312
+ top: var(--bh-toggle-focus-ring-offset);
313
+ left: var(--bh-toggle-focus-ring-offset);
314
+ right: var(--bh-toggle-focus-ring-offset);
315
+ bottom: var(--bh-toggle-focus-ring-offset);
316
+ border-radius: var(--bh-toggle-border-radius);
317
+ background: currentColor;
318
+ opacity: var(--bh-toggle-pressed-focus-ring-opacity);
319
+ pointer-events: none;
320
+ }
package/src/index.css ADDED
@@ -0,0 +1,22 @@
1
+ /* Bellhop Shared Styles - Design Tokens & Utilities */
2
+
3
+ /* Import Google Fonts */
4
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
5
+
6
+ /* Base normalization - import first */
7
+ @import './base/normalize.css';
8
+
9
+ /* Design Tokens - Foundation */
10
+ @import './tokens/index.css';
11
+
12
+ /*
13
+ * Note: Component styles are no longer included here.
14
+ * All component styles are bundled with their respective Stencil components
15
+ * in the @actabldesign/bellhop-core package using Shadow DOM encapsulation.
16
+ *
17
+ * This package now provides only:
18
+ * - Design tokens (colors, typography, spacing, shadows, radius, etc.)
19
+ * - Base normalization
20
+ * - Layout utilities
21
+ * - Animations
22
+ */
@@ -0,0 +1,167 @@
1
+ /* ==========================================================================
2
+ BELLHOP RESPONSIVE MIXINS
3
+ Breakpoint utilities for generating responsive variants
4
+
5
+ IMPORTANT: These SCSS variables must be kept in sync with the CSS custom
6
+ properties defined in _semantic.scss:
7
+ - --min-width-breakpoint-mobile (320px)
8
+ - --min-width-breakpoint-tablet (640px)
9
+ - --min-width-breakpoint-desktop (1120px)
10
+ - --min-width-breakpoint-wide (1680px)
11
+
12
+ NOTE: CSS custom properties cannot be used in media queries, so we must
13
+ duplicate these values as SCSS variables.
14
+ ========================================================================== */
15
+
16
+ // Breakpoint map (keep synced with _semantic.scss tokens)
17
+ $bh-breakpoints: (
18
+ 'mobile': 320px,
19
+ 'tablet': 640px,
20
+ 'desktop': 1120px,
21
+ 'wide': 1680px,
22
+ ) !default;
23
+
24
+ /**
25
+ * Breakpoint Up
26
+ * Applies styles at the specified breakpoint and above
27
+ * Mobile-first approach (min-width)
28
+ *
29
+ * @example
30
+ * @include bh-breakpoint-up('tablet') {
31
+ * .my-class { display: flex; }
32
+ * }
33
+ */
34
+ @mixin bh-breakpoint-up($name) {
35
+ @if not map-has-key($bh-breakpoints, $name) {
36
+ @error "Breakpoint '#{$name}' not found in $bh-breakpoints map. Available: #{map-keys($bh-breakpoints)}";
37
+ }
38
+
39
+ $min-width: map-get($bh-breakpoints, $name);
40
+
41
+ @if $name == 'mobile' {
42
+ // Mobile is base, no media query needed
43
+ @content;
44
+ } @else {
45
+ @media (min-width: $min-width) {
46
+ @content;
47
+ }
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Breakpoint Down
53
+ * Applies styles below the specified breakpoint
54
+ *
55
+ * @example
56
+ * @include bh-breakpoint-down('tablet') {
57
+ * .my-class { display: block; }
58
+ * }
59
+ */
60
+ @mixin bh-breakpoint-down($name) {
61
+ @if not map-has-key($bh-breakpoints, $name) {
62
+ @error "Breakpoint '#{$name}' not found in $bh-breakpoints map. Available: #{map-keys($bh-breakpoints)}";
63
+ }
64
+
65
+ $max-width: map-get($bh-breakpoints, $name) - 0.02px;
66
+
67
+ @media (max-width: $max-width) {
68
+ @content;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Breakpoint Only
74
+ * Applies styles only within the specified breakpoint range
75
+ *
76
+ * @example
77
+ * @include bh-breakpoint-only('tablet') {
78
+ * .my-class { display: grid; }
79
+ * }
80
+ */
81
+ @mixin bh-breakpoint-only($name) {
82
+ @if not map-has-key($bh-breakpoints, $name) {
83
+ @error "Breakpoint '#{$name}' not found in $bh-breakpoints map. Available: #{map-keys($bh-breakpoints)}";
84
+ }
85
+
86
+ $breakpoint-names: map-keys($bh-breakpoints);
87
+ $current-index: index($breakpoint-names, $name);
88
+
89
+ @if $current-index == length($breakpoint-names) {
90
+ // Last breakpoint, no upper bound
91
+ @include bh-breakpoint-up($name) {
92
+ @content;
93
+ }
94
+ } @else {
95
+ $next-name: nth($breakpoint-names, $current-index + 1);
96
+ $min-width: map-get($bh-breakpoints, $name);
97
+ $max-width: map-get($bh-breakpoints, $next-name) - 0.02px;
98
+
99
+ @if $name == 'mobile' {
100
+ @media (max-width: $max-width) {
101
+ @content;
102
+ }
103
+ } @else {
104
+ @media (min-width: $min-width) and (max-width: $max-width) {
105
+ @content;
106
+ }
107
+ }
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Breakpoint Between
113
+ * Applies styles between two specified breakpoints
114
+ *
115
+ * @example
116
+ * @include bh-breakpoint-between('tablet', 'desktop') {
117
+ * .my-class { columns: 2; }
118
+ * }
119
+ */
120
+ @mixin bh-breakpoint-between($lower, $upper) {
121
+ @if not map-has-key($bh-breakpoints, $lower) {
122
+ @error "Breakpoint '#{$lower}' not found in $bh-breakpoints map. Available: #{map-keys($bh-breakpoints)}";
123
+ }
124
+ @if not map-has-key($bh-breakpoints, $upper) {
125
+ @error "Breakpoint '#{$upper}' not found in $bh-breakpoints map. Available: #{map-keys($bh-breakpoints)}";
126
+ }
127
+
128
+ $min-width: map-get($bh-breakpoints, $lower);
129
+ $max-width: map-get($bh-breakpoints, $upper) - 0.02px;
130
+
131
+ @media (min-width: $min-width) and (max-width: $max-width) {
132
+ @content;
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Generate Responsive Variant
138
+ * Helper mixin to generate base class + responsive variants
139
+ *
140
+ * @param $class-name - The class name without dot prefix
141
+ * @param $properties - Map of CSS properties and values
142
+ *
143
+ * @example
144
+ * @include generate-responsive('bh-m_md', ('margin': var(--bh-spacing-md)));
145
+ * // Generates: .bh-m_md, .bh-m_md@tablet, .bh-m_md@desktop, .bh-m_md@wide
146
+ */
147
+ @mixin generate-responsive($class-name, $properties) {
148
+ // Base class (mobile-first, no media query)
149
+ .#{$class-name} {
150
+ @each $property, $value in $properties {
151
+ #{$property}: #{$value};
152
+ }
153
+ }
154
+
155
+ // Responsive variants
156
+ @each $bp-name, $bp-value in $bh-breakpoints {
157
+ @if $bp-name != 'mobile' {
158
+ .#{$class-name}\@#{$bp-name} {
159
+ @include bh-breakpoint-up($bp-name) {
160
+ @each $property, $value in $properties {
161
+ #{$property}: #{$value};
162
+ }
163
+ }
164
+ }
165
+ }
166
+ }
167
+ }