@brady_h/styles 1.0.2 → 1.0.3

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.
@@ -1,5 +1,212 @@
1
+ @use "sass:color";
1
2
  @use "sass:math";
3
+ @use "sass:map";
4
+ @use "sass:meta";
5
+ @use "./variables" as vars;
6
+ @use "./breakpoints" as bp;
7
+
8
+ @function map-value($collection, $key, $fallback: null) {
9
+ @if not map.has-key($collection, $key) {
10
+ @if $fallback != null {
11
+ @return $fallback;
12
+ }
13
+
14
+ @error "Key '#{$key}' does not exist in the supplied map.";
15
+ }
16
+
17
+ @return map.get($collection, $key);
18
+ }
19
+
20
+ @function spacing($key) {
21
+ @return map-value(vars.$spacing, $key);
22
+ }
23
+
24
+ @function radius($key) {
25
+ @return map-value(vars.$border-radius, $key);
26
+ }
27
+
28
+ @function font-size($key) {
29
+ @return map-value(vars.$font-size, $key);
30
+ }
31
+
32
+ @function font-weight($key) {
33
+ @return map-value(vars.$font-weight, $key);
34
+ }
35
+
36
+ @function line-height($key) {
37
+ @return map-value(vars.$line-height, $key);
38
+ }
39
+
40
+ @function shadow($key) {
41
+ @return map-value(vars.$box-shadow, $key);
42
+ }
43
+
44
+ @function z-index($key) {
45
+ @return map-value(vars.$z-index, $key);
46
+ }
2
47
 
3
48
  @function to-rem($value, $base: 16px) {
49
+ @if math.is-unitless($value) {
50
+ $value: $value * 1px;
51
+ }
52
+
4
53
  @return math.div($value, $base) * 1rem;
5
54
  }
55
+
56
+ @function to-em($value, $base: 16px) {
57
+ @if math.is-unitless($value) {
58
+ $value: $value * 1px;
59
+ }
60
+
61
+ @return math.div($value, $base) * 1em;
62
+ }
63
+
64
+ @function to-px($value, $base: 16px) {
65
+ @if math.is-unitless($value) {
66
+ @return $value * 1px;
67
+ }
68
+
69
+ @return math.div($value, 1rem) * $base;
70
+ }
71
+
72
+ @function strip-unit($value) {
73
+ @if math.is-unitless($value) {
74
+ @return $value;
75
+ }
76
+
77
+ @return math.div($value, $value * 0 + 1);
78
+ }
79
+
80
+ @function clamp-value($value, $min, $max) {
81
+ @return clamp($min, $value, $max);
82
+ }
83
+
84
+ @function fluid-size($min, $max, $min-viewport: 320px, $max-viewport: 1440px) {
85
+ $slope: math.div($max - $min, $max-viewport - $min-viewport) * 100;
86
+ $intercept: $min - math.div($slope * $min-viewport, 100);
87
+
88
+ @return clamp($min, calc(#{$intercept} + #{$slope}vw), $max);
89
+ }
90
+
91
+ @function breakpoint($key) {
92
+ @return bp.breakpoint($key);
93
+ }
94
+
95
+ @function color-opacity($value, $opacity) {
96
+ @return color.change($value, $alpha: $opacity);
97
+ }
98
+
99
+ @function lighten-color($value, $amount: 10%) {
100
+ @return color.adjust($value, $lightness: $amount);
101
+ }
102
+
103
+ @function darken-color($value, $amount: 10%) {
104
+ @return color.adjust($value, $lightness: -$amount);
105
+ }
106
+
107
+ @function saturate-color($value, $amount: 10%) {
108
+ @return color.adjust($value, $saturation: $amount);
109
+ }
110
+
111
+ @function desaturate-color($value, $amount: 10%) {
112
+ @return color.adjust($value, $saturation: -$amount);
113
+ }
114
+
115
+ @function grayscale($value) {
116
+ @return color.grayscale($value);
117
+ }
118
+
119
+ @function invert-color($value) {
120
+ @return color.invert($value);
121
+ }
122
+
123
+ @function mix-colors($first, $second, $weight: 50%) {
124
+ @return color.mix($first, $second, $weight: $weight);
125
+ }
126
+
127
+ @function color-contrast($value, $light: #fff, $dark: #000) {
128
+ @return color.contrast($value, $light, $dark);
129
+ }
130
+
131
+ @function is-light($value) {
132
+ @return color.channel($value, "lightness", $space: hsl) > 50%;
133
+ }
134
+
135
+ @function is-dark($value) {
136
+ @return not is-light($value);
137
+ }
138
+
139
+ @function percentage-of($value, $total) {
140
+ @return math.percentage(math.div($value, $total));
141
+ }
142
+
143
+ @function ratio($value, $total) {
144
+ @return math.div($value, $total);
145
+ }
146
+
147
+ @function px-to-percent($value, $container) {
148
+ @return math.percentage(math.div($value, $container));
149
+ }
150
+
151
+ @function px-to-vw($value, $viewport: 1440px) {
152
+ @return math.div($value, $viewport) * 100vw;
153
+ }
154
+
155
+ @function px-to-vh($value, $viewport: 900px) {
156
+ @return math.div($value, $viewport) * 100vh;
157
+ }
158
+
159
+ @function negative($value) {
160
+ @return -$value;
161
+ }
162
+
163
+ @function half($value) {
164
+ @return math.div($value, 2);
165
+ }
166
+
167
+ @function double($value) {
168
+ @return $value * 2;
169
+ }
170
+
171
+ @function triple($value) {
172
+ @return $value * 3;
173
+ }
174
+
175
+ @function power($value, $exponent) {
176
+ $result: 1;
177
+
178
+ @if $exponent < 0 {
179
+ @return math.div(1, power($value, -$exponent));
180
+ }
181
+
182
+ @for $i from 1 through $exponent {
183
+ $result: $result * $value;
184
+ }
185
+
186
+ @return $result;
187
+ }
188
+
189
+ @function fluid-spacing(
190
+ $min,
191
+ $max,
192
+ $min-viewport: 320px,
193
+ $max-viewport: 1440px
194
+ ) {
195
+ @return fluid-size($min, $max, $min-viewport, $max-viewport);
196
+ }
197
+
198
+ @function aspect-ratio-height($width, $ratio-width: 16, $ratio-height: 9) {
199
+ @return math.div($width * $ratio-height, $ratio-width);
200
+ }
201
+
202
+ @function aspect-ratio-width($height, $ratio-width: 16, $ratio-height: 9) {
203
+ @return math.div($height * $ratio-width, $ratio-height);
204
+ }
205
+
206
+ @function alpha($value, $opacity) {
207
+ @return color-opacity($value, $opacity);
208
+ }
209
+
210
+ @function map-contains($collection, $key) {
211
+ @return map.has-key($collection, $key);
212
+ }
package/src/_mixins.scss CHANGED
@@ -1,3 +1,4 @@
1
+ @use "sass:map";
1
2
  @use "./breakpoints" as bp;
2
3
 
3
4
  @mixin respond-down($breakpoint: md) {
@@ -12,6 +13,12 @@
12
13
  }
13
14
  }
14
15
 
16
+ @mixin respond-between($min, $max) {
17
+ @media (min-width: bp.breakpoint($min)) and (max-width: bp.breakpoint($max)) {
18
+ @content;
19
+ }
20
+ }
21
+
15
22
  @mixin touch-query($breakpoint: md) {
16
23
  @media (max-width: bp.breakpoint($breakpoint)) and (pointer: coarse) and (hover: none) {
17
24
  @content;
@@ -38,6 +45,32 @@
38
45
  }
39
46
  }
40
47
 
48
+ @mixin reduced-motion {
49
+ @media (prefers-reduced-motion: reduce) {
50
+ @content;
51
+ }
52
+ }
53
+
54
+ @mixin dark-mode {
55
+ @media (prefers-color-scheme: dark) {
56
+ @content;
57
+ }
58
+ }
59
+
60
+ @mixin light-mode {
61
+ @media (prefers-color-scheme: light) {
62
+ @content;
63
+ }
64
+ }
65
+
66
+ @mixin hover-supported {
67
+ @media (hover: hover) and (pointer: fine) {
68
+ &:hover {
69
+ @content;
70
+ }
71
+ }
72
+ }
73
+
41
74
  @mixin flex-center {
42
75
  display: flex;
43
76
  align-items: center;
@@ -50,12 +83,186 @@
50
83
  justify-content: space-between;
51
84
  }
52
85
 
86
+ @mixin flex-start {
87
+ display: flex;
88
+ align-items: center;
89
+ justify-content: flex-start;
90
+ }
91
+
92
+ @mixin flex-end {
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: flex-end;
96
+ }
97
+
98
+ @mixin flex-column {
99
+ display: flex;
100
+ flex-direction: column;
101
+ }
102
+
103
+ @mixin flex-column-center {
104
+ @include flex-center;
105
+ flex-direction: column;
106
+ }
107
+
108
+ @mixin flex-wrap {
109
+ display: flex;
110
+ flex-wrap: wrap;
111
+ }
112
+
113
+ @mixin flex-inline-center {
114
+ display: inline-flex;
115
+ align-items: center;
116
+ justify-content: center;
117
+ }
118
+
119
+ @mixin flex-gap($gap: 16px) {
120
+ display: flex;
121
+ gap: $gap;
122
+ }
123
+
124
+ @mixin grid-center {
125
+ display: grid;
126
+ place-items: center;
127
+ }
128
+
129
+ @mixin grid-columns($columns: 2, $gap: 16px) {
130
+ display: grid;
131
+ grid-template-columns: repeat($columns, minmax(0, 1fr));
132
+ gap: $gap;
133
+ }
134
+
135
+ @mixin grid-auto-fit($min-width: 250px, $gap: 16px) {
136
+ display: grid;
137
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, $min-width), 1fr));
138
+ gap: $gap;
139
+ }
140
+
141
+ @mixin grid-auto-fill($min-width: 250px, $gap: 16px) {
142
+ display: grid;
143
+ grid-template-columns: repeat(auto-fill, minmax(min(100%, $min-width), 1fr));
144
+ gap: $gap;
145
+ }
146
+
147
+ @mixin grid-areas($areas, $columns: 1fr, $rows: auto, $gap: 16px) {
148
+ display: grid;
149
+ grid-template-areas: $areas;
150
+ grid-template-columns: $columns;
151
+ grid-template-rows: $rows;
152
+ gap: $gap;
153
+ }
154
+
155
+ @mixin center-block {
156
+ display: block;
157
+ margin-inline: auto;
158
+ }
159
+
160
+ @mixin container($max-width: 1200px, $padding: 16px) {
161
+ width: 100%;
162
+ max-width: $max-width;
163
+ margin-inline: auto;
164
+ padding-inline: $padding;
165
+ }
166
+
167
+ @mixin absolute-center {
168
+ position: absolute;
169
+ top: 50%;
170
+ left: 50%;
171
+ transform: translate(-50%, -50%);
172
+ }
173
+
174
+ @mixin absolute-fill {
175
+ position: absolute;
176
+ inset: 0;
177
+ }
178
+
179
+ @mixin fixed-fill {
180
+ position: fixed;
181
+ inset: 0;
182
+ }
183
+
184
+ @mixin sticky-top($top: 0) {
185
+ position: sticky;
186
+ top: $top;
187
+ }
188
+
189
+ @mixin aspect-ratio($width: 16, $height: 9) {
190
+ aspect-ratio: #{$width} / #{$height};
191
+ }
192
+
193
+ @mixin circle($size) {
194
+ width: $size;
195
+ height: $size;
196
+ flex: 0 0 $size;
197
+ border-radius: 50%;
198
+ }
199
+
200
+ @mixin square($size) {
201
+ width: $size;
202
+ height: $size;
203
+ }
204
+
53
205
  @mixin text-truncate {
54
206
  overflow: hidden;
55
207
  white-space: nowrap;
56
208
  text-overflow: ellipsis;
57
209
  }
58
210
 
211
+ @mixin text-truncate-lines($lines: 2) {
212
+ display: -webkit-box;
213
+ overflow: hidden;
214
+ -webkit-box-orient: vertical;
215
+ -webkit-line-clamp: $lines;
216
+ line-clamp: $lines;
217
+ }
218
+
219
+ @mixin text-balance {
220
+ text-wrap: balance;
221
+ }
222
+
223
+ @mixin text-pretty {
224
+ text-wrap: pretty;
225
+ }
226
+
227
+ @mixin heading-reset {
228
+ margin: 0;
229
+ font-size: inherit;
230
+ font-weight: inherit;
231
+ line-height: inherit;
232
+ }
233
+
234
+ @mixin paragraph-reset {
235
+ margin: 0;
236
+ }
237
+
238
+ @mixin list-reset {
239
+ margin: 0;
240
+ padding: 0;
241
+ list-style: none;
242
+ }
243
+
244
+ @mixin button-reset {
245
+ padding: 0;
246
+ border: 0;
247
+ background: none;
248
+ color: inherit;
249
+ font: inherit;
250
+ text-align: inherit;
251
+ cursor: pointer;
252
+ }
253
+
254
+ @mixin link-reset {
255
+ color: inherit;
256
+ text-decoration: none;
257
+ }
258
+
259
+ @mixin appearance-reset {
260
+ appearance: none;
261
+ border: 0;
262
+ background: none;
263
+ font: inherit;
264
+ }
265
+
59
266
  @mixin visually-hidden {
60
267
  position: absolute;
61
268
  width: 1px;
@@ -68,9 +275,198 @@
68
275
  border: 0;
69
276
  }
70
277
 
71
- @mixin focus-ring($color: currentColor) {
278
+ @mixin focus-ring($color: currentColor, $width: 2px, $offset: 3px) {
72
279
  &:focus-visible {
73
- outline: 2px solid $color;
74
- outline-offset: 3px;
280
+ outline: $width solid $color;
281
+ outline-offset: $offset;
282
+ }
283
+ }
284
+
285
+ @mixin focus-within-ring($color: currentColor, $width: 2px, $offset: 3px) {
286
+ &:focus-within {
287
+ outline: $width solid $color;
288
+ outline-offset: $offset;
289
+ }
290
+ }
291
+
292
+ @mixin no-focus-outline {
293
+ &:focus {
294
+ outline: none;
295
+ }
296
+ }
297
+
298
+ @mixin hover-lift($distance: 3px) {
299
+ transition: transform 200ms ease;
300
+
301
+ @include hover-supported {
302
+ transform: translateY(-$distance);
303
+ }
304
+
305
+ @include reduced-motion {
306
+ transition: none;
307
+ }
308
+ }
309
+
310
+ @mixin hover-scale($scale: 1.03) {
311
+ transition: transform 200ms ease;
312
+
313
+ @include hover-supported {
314
+ transform: scale($scale);
315
+ }
316
+
317
+ @include reduced-motion {
318
+ transition: none;
319
+ }
320
+ }
321
+
322
+ @mixin transition($properties: all, $duration: 200ms, $timing: ease) {
323
+ transition: $properties $duration $timing;
324
+ }
325
+
326
+ @mixin transition-colors($duration: 200ms, $timing: ease) {
327
+ transition:
328
+ color $duration $timing,
329
+ background-color $duration $timing,
330
+ border-color $duration $timing;
331
+ }
332
+
333
+ @mixin no-transition {
334
+ transition: none;
335
+ }
336
+
337
+ @mixin shadow($value: 0 4px 12px rgba(0, 0, 0, 0.1)) {
338
+ box-shadow: $value;
339
+ }
340
+
341
+ @mixin overlay($color: rgba(0, 0, 0, 0.5)) {
342
+ position: absolute;
343
+ inset: 0;
344
+ background: $color;
345
+ }
346
+
347
+ @mixin gradient-overlay(
348
+ $direction: to bottom,
349
+ $start: rgba(0, 0, 0, 0.65),
350
+ $end: transparent
351
+ ) {
352
+ position: absolute;
353
+ inset: 0;
354
+ background: linear-gradient($direction, $start, $end);
355
+ }
356
+
357
+ @mixin background-cover($position: center) {
358
+ background-position: $position;
359
+ background-repeat: no-repeat;
360
+ background-size: cover;
361
+ }
362
+
363
+ @mixin background-contain($position: center) {
364
+ background-position: $position;
365
+ background-repeat: no-repeat;
366
+ background-size: contain;
367
+ }
368
+
369
+ @mixin border($color: currentColor, $width: 1px, $style: solid) {
370
+ border: $width $style $color;
371
+ }
372
+
373
+ @mixin divider($color: currentColor, $direction: horizontal, $width: 1px) {
374
+ @if $direction == horizontal {
375
+ height: $width;
376
+ width: 100%;
377
+ } @else {
378
+ width: $width;
379
+ height: 100%;
380
+ }
381
+
382
+ background: $color;
383
+ }
384
+
385
+ @mixin scrollbar-hide {
386
+ scrollbar-width: none;
387
+
388
+ &::-webkit-scrollbar {
389
+ display: none;
390
+ }
391
+ }
392
+
393
+ @mixin scrollbar-style(
394
+ $width: 8px,
395
+ $track: transparent,
396
+ $thumb: rgba(128, 128, 128, 0.5)
397
+ ) {
398
+ scrollbar-width: thin;
399
+ scrollbar-color: $thumb $track;
400
+
401
+ &::-webkit-scrollbar {
402
+ width: $width;
403
+ height: $width;
404
+ }
405
+
406
+ &::-webkit-scrollbar-track {
407
+ background: $track;
408
+ }
409
+
410
+ &::-webkit-scrollbar-thumb {
411
+ background: $thumb;
412
+ border-radius: 999px;
413
+ }
414
+ }
415
+
416
+ @mixin selection($background, $color: inherit) {
417
+ &::selection {
418
+ background: $background;
419
+ color: $color;
420
+ }
421
+ }
422
+
423
+ @mixin placeholder($color: currentColor) {
424
+ &::placeholder {
425
+ color: $color;
426
+ opacity: 1;
427
+ }
428
+ }
429
+
430
+ @mixin disabled-state {
431
+ &:disabled,
432
+ &[aria-disabled="true"] {
433
+ opacity: 0.5;
434
+ cursor: not-allowed;
435
+ pointer-events: none;
436
+ }
437
+ }
438
+
439
+ @mixin loading-state {
440
+ &[aria-busy="true"] {
441
+ cursor: progress;
442
+ }
443
+ }
444
+
445
+ @mixin reduced-motion-safe {
446
+ @include reduced-motion {
447
+ animation-duration: 0.01ms !important;
448
+ animation-iteration-count: 1 !important;
449
+ scroll-behavior: auto !important;
450
+ transition-duration: 0.01ms !important;
451
+ }
452
+ }
453
+
454
+ @mixin print {
455
+ @media print {
456
+ @content;
457
+ }
458
+ }
459
+
460
+ @mixin print-hidden {
461
+ @media print {
462
+ display: none !important;
463
+ }
464
+ }
465
+
466
+ @mixin print-visible {
467
+ display: none;
468
+
469
+ @media print {
470
+ display: block !important;
75
471
  }
76
472
  }