@shohojdhara/atomix 0.6.6 → 0.6.8

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 (38) hide show
  1. package/dist/atomix.css +3654 -902
  2. package/dist/atomix.css.map +1 -1
  3. package/dist/atomix.min.css +45 -45
  4. package/dist/atomix.min.css.map +1 -1
  5. package/package.json +21 -1
  6. package/src/layouts/Grid/Grid.stories.tsx +54 -2
  7. package/src/layouts/Grid/README.md +6 -2
  8. package/src/styles/01-settings/_settings.colors.scss +73 -73
  9. package/src/styles/01-settings/_settings.design-tokens.scss +4 -0
  10. package/src/styles/01-settings/_settings.grid.scss +53 -0
  11. package/src/styles/01-settings/_settings.motion.scss +50 -0
  12. package/src/styles/01-settings/_settings.spacing.scss +13 -1
  13. package/src/styles/01-settings/_settings.typography.scss +5 -1
  14. package/src/styles/02-tools/_tools.map-loop.scss +19 -0
  15. package/src/styles/02-tools/_tools.utility-api.scss +57 -53
  16. package/src/styles/05-objects/_objects.grid.scss +4 -1
  17. package/src/styles/99-utilities/_index.core.scss +24 -0
  18. package/src/styles/99-utilities/_index.grid.scss +3 -0
  19. package/src/styles/99-utilities/_index.interaction.scss +3 -0
  20. package/src/styles/99-utilities/_index.motion.scss +5 -0
  21. package/src/styles/99-utilities/_index.scss +5 -0
  22. package/src/styles/99-utilities/_utilities.core.scss +44 -0
  23. package/src/styles/99-utilities/_utilities.generate-grid.scss +7 -0
  24. package/src/styles/99-utilities/_utilities.generate-interaction.scss +7 -0
  25. package/src/styles/99-utilities/_utilities.generate-motion.scss +15 -0
  26. package/src/styles/99-utilities/_utilities.grid.scss +55 -0
  27. package/src/styles/99-utilities/_utilities.interaction.scss +44 -0
  28. package/src/styles/99-utilities/_utilities.link.scss +3 -3
  29. package/src/styles/99-utilities/_utilities.position.scss +15 -0
  30. package/src/styles/99-utilities/_utilities.scss +10 -0
  31. package/src/styles/99-utilities/_utilities.sizes.scss +0 -4
  32. package/src/styles/99-utilities/_utilities.spacing.scss +3 -3
  33. package/src/styles/99-utilities/_utilities.state.scss +64 -0
  34. package/src/styles/99-utilities/_utilities.text-gradient.scss +26 -37
  35. package/src/styles/99-utilities/_utilities.text.scss +0 -11
  36. package/src/styles/99-utilities/_utilities.transform.scss +15 -0
  37. package/src/styles/99-utilities/_utilities.transition.scss +20 -0
  38. package/src/styles/__tests__/utilities-compile.test.ts +37 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shohojdhara/atomix",
3
- "version": "0.6.6",
3
+ "version": "0.6.8",
4
4
  "description": "Atomix Design System - A modern component library for web applications",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -83,6 +83,26 @@
83
83
  "require": "./src/styles/99-utilities/_index.scss",
84
84
  "default": "./src/styles/99-utilities/_index.scss"
85
85
  },
86
+ "./scss/utilities/core": {
87
+ "import": "./src/styles/99-utilities/_index.core.scss",
88
+ "require": "./src/styles/99-utilities/_index.core.scss",
89
+ "default": "./src/styles/99-utilities/_index.core.scss"
90
+ },
91
+ "./scss/utilities/grid": {
92
+ "import": "./src/styles/99-utilities/_index.grid.scss",
93
+ "require": "./src/styles/99-utilities/_index.grid.scss",
94
+ "default": "./src/styles/99-utilities/_index.grid.scss"
95
+ },
96
+ "./scss/utilities/interaction": {
97
+ "import": "./src/styles/99-utilities/_index.interaction.scss",
98
+ "require": "./src/styles/99-utilities/_index.interaction.scss",
99
+ "default": "./src/styles/99-utilities/_index.interaction.scss"
100
+ },
101
+ "./scss/utilities/motion": {
102
+ "import": "./src/styles/99-utilities/_index.motion.scss",
103
+ "require": "./src/styles/99-utilities/_index.motion.scss",
104
+ "default": "./src/styles/99-utilities/_index.motion.scss"
105
+ },
86
106
  "./theme": {
87
107
  "types": "./dist/theme.d.ts",
88
108
  "import": "./dist/theme.js",
@@ -670,13 +670,47 @@ export const AlignmentAndSpacing: Story = {
670
670
  </div>
671
671
  </div>
672
672
 
673
+ {/* Row Gap */}
674
+ <div className="u-mb-8">
675
+ <h2 className="u-mb-4 u-text-brand-emphasis">Row Gap</h2>
676
+ <p className="u-mb-4 u-text-secondary-emphasis">
677
+ Wrapped rows use vertical spacing from the grid gutter width (`row-gap` via
678
+ `--atomix-gutter-y`):
679
+ </p>
680
+
681
+ <Row className="u-mb-4 u-p-3 u-bg-brand-subtle u-rounded">
682
+ <GridCol xs={4}>
683
+ <DemoCard variant="secondary">Column 1</DemoCard>
684
+ </GridCol>
685
+ <GridCol xs={4}>
686
+ <DemoCard variant="secondary">Column 2</DemoCard>
687
+ </GridCol>
688
+ <GridCol xs={4}>
689
+ <DemoCard variant="secondary">Column 3</DemoCard>
690
+ </GridCol>
691
+ <GridCol xs={4}>
692
+ <DemoCard variant="secondary">Column 4</DemoCard>
693
+ </GridCol>
694
+ <GridCol xs={4}>
695
+ <DemoCard variant="secondary">Column 5</DemoCard>
696
+ </GridCol>
697
+ <GridCol xs={4}>
698
+ <DemoCard variant="secondary">Column 6</DemoCard>
699
+ </GridCol>
700
+ </Row>
701
+ </div>
702
+
673
703
  {/* No Gutters */}
674
704
  <div className="u-mb-8">
675
705
  <h2 className="u-mb-4 u-text-brand-emphasis">No Gutters</h2>
676
- <p className="u-mb-4 u-text-secondary-emphasis">Remove spacing between columns:</p>
706
+ <p className="u-mb-4 u-text-secondary-emphasis">
707
+ Remove horizontal and vertical gutter spacing between columns:
708
+ </p>
677
709
 
678
710
  <div className="u-mb-6">
679
- <h3 className="u-mb-3 u-text-secondary-emphasis u-font-medium">With gutters (default)</h3>
711
+ <h3 className="u-mb-3 u-text-secondary-emphasis u-font-medium">
712
+ With gutters (default)
713
+ </h3>
680
714
  <Row className="u-mb-4 u-p-3 u-bg-brand-subtle u-rounded">
681
715
  <GridCol xs={4}>
682
716
  <DemoCard variant="secondary">Column 1</DemoCard>
@@ -687,6 +721,15 @@ export const AlignmentAndSpacing: Story = {
687
721
  <GridCol xs={4}>
688
722
  <DemoCard variant="secondary">Column 3</DemoCard>
689
723
  </GridCol>
724
+ <GridCol xs={4}>
725
+ <DemoCard variant="secondary">Column 4</DemoCard>
726
+ </GridCol>
727
+ <GridCol xs={4}>
728
+ <DemoCard variant="secondary">Column 5</DemoCard>
729
+ </GridCol>
730
+ <GridCol xs={4}>
731
+ <DemoCard variant="secondary">Column 6</DemoCard>
732
+ </GridCol>
690
733
  </Row>
691
734
  </div>
692
735
 
@@ -702,6 +745,15 @@ export const AlignmentAndSpacing: Story = {
702
745
  <GridCol xs={4}>
703
746
  <DemoCard variant="accent">Column 3</DemoCard>
704
747
  </GridCol>
748
+ <GridCol xs={4}>
749
+ <DemoCard variant="accent">Column 4</DemoCard>
750
+ </GridCol>
751
+ <GridCol xs={4}>
752
+ <DemoCard variant="accent">Column 5</DemoCard>
753
+ </GridCol>
754
+ <GridCol xs={4}>
755
+ <DemoCard variant="accent">Column 6</DemoCard>
756
+ </GridCol>
705
757
  </Row>
706
758
  </div>
707
759
  </div>
@@ -30,9 +30,11 @@ import { Grid, GridCol } from '@/layouts/Grid';
30
30
  - Adds utility class `u-justify-content-[value]`
31
31
  - `alignItems`: Control vertical alignment ('start', 'end', 'center', 'baseline', 'stretch')
32
32
  - Adds utility class `u-align-items-[value]`
33
- - `noGutters`: Remove gutters between columns
33
+ - `noGutters`: Remove horizontal and vertical gutter spacing
34
34
  - Adds modifier class `o-grid--no-gutters`
35
35
 
36
+ Grids apply `row-gap` from `--atomix-gutter-y` (defaults to `$grid-gutter-width`) when columns wrap to multiple rows. Horizontal gutters use the existing column padding model. Override vertical spacing with `--atomix-gutter-y` on any `.o-grid`.
37
+
36
38
  ### GridCol
37
39
 
38
40
  Column component with responsive sizing options.
@@ -89,9 +91,11 @@ import { Container, Row, GridCol } from '@/layouts/Grid';
89
91
  - Adds utility class `u-justify-content-[value]`
90
92
  - `alignItems`: Control vertical alignment ('start', 'end', 'center', 'baseline', 'stretch')
91
93
  - Adds utility class `u-align-items-[value]`
92
- - `noGutters`: Remove gutters between columns
94
+ - `noGutters`: Remove horizontal and vertical gutter spacing
93
95
  - Adds modifier class `o-grid--no-gutters`
94
96
 
97
+ Grids apply `row-gap` from `--atomix-gutter-y` (defaults to `$grid-gutter-width`) when columns wrap to multiple rows. Horizontal gutters use the existing column padding model. Override vertical spacing with `--atomix-gutter-y` on any `.o-grid`.
98
+
95
99
  ## Breakpoints
96
100
 
97
101
  The grid system uses the following breakpoints:
@@ -11,81 +11,81 @@ $black: #000000 !default;
11
11
  $color-contrast-dark: #000000 !default;
12
12
  $color-contrast-light: #ffffff !default;
13
13
 
14
- // Primitives Primary Colors (Purple Scale)
15
- $primary-1: #f5f3ff !default;
16
- $primary-2: #ede9fe !default;
17
- $primary-3: #ddd6fe !default;
18
- $primary-4: #c4b5fd !default;
19
- $primary-5: #a78bfa !default;
20
- $primary-6: #8b5cf6 !default; // Balanced primary - main brand color (WCAG AA compliant)
21
- $primary-7: #7c3aed !default;
22
- $primary-8: #6d28d9 !default;
23
- $primary-9: #5b21b6 !default;
24
- $primary-10: #4c1d95 !default;
25
-
26
- // Primitives Red Colors
27
- $red-1: #fef2f2 !default;
28
- $red-2: #fee2e2 !default;
29
- $red-3: #fecaca !default;
30
- $red-4: #fca5a5 !default;
31
- $red-5: #f87171 !default;
32
- $red-6: #ef4444 !default; // Vibrant, accessible red
33
- $red-7: #dc2626 !default;
34
- $red-8: #b91c1c !default;
35
- $red-9: #991b1b !default;
36
- $red-10: #7f1d1d !default;
37
-
38
- // Primitives Green Colors
39
- $green-1: #f0fdf4 !default;
40
- $green-2: #dcfce7 !default;
41
- $green-3: #bbf7d0 !default;
42
- $green-4: #86efac !default;
43
- $green-5: #4ade80 !default;
44
- $green-6: #22c55e !default; // Balanced, accessible green
45
- $green-7: #16a34a !default;
46
- $green-8: #15803d !default;
47
- $green-9: #166534 !default;
48
- $green-10: #14532d !default;
49
-
50
- // Primitives Yellow Colors
51
- $yellow-1: #fefce8 !default;
52
- $yellow-2: #fef9c3 !default;
53
- $yellow-3: #fef08a !default;
54
- $yellow-4: #fde047 !default;
55
- $yellow-5: #facc15 !default;
56
- $yellow-6: #eab308 !default; // Accessible, high-visibility yellow
57
- $yellow-7: #ca8a04 !default;
58
- $yellow-8: #a16207 !default;
59
- $yellow-9: #854d0e !default;
60
- $yellow-10: #713f12 !default;
61
-
62
- // Primitives Blue Colors
63
- $blue-1: #eff6ff !default;
64
- $blue-2: #dbeafe !default;
65
- $blue-3: #bfdbfe !default;
66
- $blue-4: #93c5fd !default;
67
- $blue-5: #60a5fa !default;
68
- $blue-6: #3b82f6 !default; // Balanced, accessible blue
69
- $blue-7: #2563eb !default;
70
- $blue-8: #1d4ed8 !default;
71
- $blue-9: #1e40af !default;
72
- $blue-10: #1e3a8a !default;
73
-
74
- // Primitives Gray Colors
75
- $gray-1: #f9fafb !default;
76
- $gray-2: #f3f4f6 !default;
77
- $gray-3: #e5e7eb !default;
78
- $gray-4: #d1d5db !default;
79
- $gray-5: #9ca3af !default;
80
- $gray-6: #6b7280 !default;
81
- $gray-7: #4b5563 !default;
82
- $gray-8: #374151 !default;
83
- $gray-9: #1f2937 !default;
84
- $gray-10: #111827 !default;
14
+ // Primitives Primary Colors (Premium Violet Scale)
15
+ $primary-1: #f6f4ff !default;
16
+ $primary-2: #ece7ff !default;
17
+ $primary-3: #dccfff !default;
18
+ $primary-4: #c1aafd !default;
19
+ $primary-5: #a07ff9 !default;
20
+ $primary-6: #7c4dff !default; // Premium brand violet - rich, refined main brand color
21
+ $primary-7: #6b3ae8 !default;
22
+ $primary-8: #5a2bc9 !default;
23
+ $primary-9: #47209f !default;
24
+ $primary-10: #341776 !default;
25
+
26
+ // Primitives Red Colors (Premium Rose Scale)
27
+ $red-1: #fff1f2 !default;
28
+ $red-2: #ffe4e6 !default;
29
+ $red-3: #fecdd3 !default;
30
+ $red-4: #fda4af !default;
31
+ $red-5: #fb7185 !default;
32
+ $red-6: #f43f5e !default; // Refined, accessible rose-red
33
+ $red-7: #e11d48 !default;
34
+ $red-8: #be123c !default;
35
+ $red-9: #9f1239 !default;
36
+ $red-10: #881337 !default;
37
+
38
+ // Primitives Green Colors (Premium Emerald Scale)
39
+ $green-1: #ecfdf5 !default;
40
+ $green-2: #d1fae5 !default;
41
+ $green-3: #a7f3d0 !default;
42
+ $green-4: #6ee7b7 !default;
43
+ $green-5: #34d399 !default;
44
+ $green-6: #10b981 !default; // Refined, accessible emerald
45
+ $green-7: #059669 !default;
46
+ $green-8: #047857 !default;
47
+ $green-9: #065f46 !default;
48
+ $green-10: #064e3b !default;
49
+
50
+ // Primitives Yellow Colors (Premium Amber Scale)
51
+ $yellow-1: #fffbeb !default;
52
+ $yellow-2: #fef3c7 !default;
53
+ $yellow-3: #fde68a !default;
54
+ $yellow-4: #fcd34d !default;
55
+ $yellow-5: #fbbf24 !default;
56
+ $yellow-6: #f59e0b !default; // Warm, accessible amber
57
+ $yellow-7: #d97706 !default;
58
+ $yellow-8: #b45309 !default;
59
+ $yellow-9: #92400e !default;
60
+ $yellow-10: #78350f !default;
61
+
62
+ // Primitives Blue Colors (Premium Azure Scale)
63
+ $blue-1: #eff8ff !default;
64
+ $blue-2: #d8edff !default;
65
+ $blue-3: #b6ddff !default;
66
+ $blue-4: #84c5ff !default;
67
+ $blue-5: #52a6fa !default;
68
+ $blue-6: #2f80ed !default; // Refined, accessible azure blue
69
+ $blue-7: #1f66d4 !default;
70
+ $blue-8: #1a4fad !default;
71
+ $blue-9: #1a428a !default;
72
+ $blue-10: #173770 !default;
73
+
74
+ // Primitives Gray Colors (Premium Cool Slate Scale)
75
+ $gray-1: #f8fafc !default;
76
+ $gray-2: #f1f5f9 !default;
77
+ $gray-3: #e2e8f0 !default;
78
+ $gray-4: #cbd5e1 !default;
79
+ $gray-5: #94a3b8 !default;
80
+ $gray-6: #64748b !default;
81
+ $gray-7: #475569 !default;
82
+ $gray-8: #334155 !default;
83
+ $gray-9: #1e293b !default;
84
+ $gray-10: #0f172a !default;
85
85
 
86
86
  // Primitives Overlay
87
- $overlay-1: rgba(20, 20, 20, 0.302) !default;
88
- $overlay-2: rgba($gray-6, 0.6) !default;
87
+ $overlay-1: rgba($gray-10, 0.32) !default;
88
+ $overlay-2: rgba($gray-9, 0.6) !default;
89
89
 
90
90
  //Text colors emphasis
91
91
  $primary-text: $gray-10 !default;
@@ -392,6 +392,10 @@ $font-sizes-extended: (
392
392
  'lg': $font-size-lg,
393
393
  'xl': $font-size-xl,
394
394
  '2xl': $font-size-2xl,
395
+ '3xl': $font-size-3xl,
396
+ '4xl': $font-size-4xl,
397
+ '5xl': $font-size-5xl,
398
+ '6xl': $font-size-6xl,
395
399
  'h1': $h1-font-size,
396
400
  'h2': $h2-font-size,
397
401
  'h3': $h3-font-size,
@@ -13,3 +13,56 @@ $container-max-widths: (
13
13
  xl: 1140px,
14
14
  xxl: 1320px,
15
15
  ) !default;
16
+
17
+ // Utility class value maps for CSS Grid layout
18
+ $utility-grid-template-columns: (
19
+ 1: repeat(1, minmax(0, 1fr)),
20
+ 2: repeat(2, minmax(0, 1fr)),
21
+ 3: repeat(3, minmax(0, 1fr)),
22
+ 4: repeat(4, minmax(0, 1fr)),
23
+ 5: repeat(5, minmax(0, 1fr)),
24
+ 6: repeat(6, minmax(0, 1fr)),
25
+ 7: repeat(7, minmax(0, 1fr)),
26
+ 8: repeat(8, minmax(0, 1fr)),
27
+ 9: repeat(9, minmax(0, 1fr)),
28
+ 10: repeat(10, minmax(0, 1fr)),
29
+ 11: repeat(11, minmax(0, 1fr)),
30
+ 12: repeat(12, minmax(0, 1fr)),
31
+ ) !default;
32
+
33
+ $utility-grid-template-rows: (
34
+ 1: repeat(1, minmax(0, 1fr)),
35
+ 2: repeat(2, minmax(0, 1fr)),
36
+ 3: repeat(3, minmax(0, 1fr)),
37
+ 4: repeat(4, minmax(0, 1fr)),
38
+ 5: repeat(5, minmax(0, 1fr)),
39
+ 6: repeat(6, minmax(0, 1fr)),
40
+ ) !default;
41
+
42
+ @use 'sass:string';
43
+
44
+ $utility-grid-column-spans: (
45
+ 1: span 1 / span 1,
46
+ 2: span 2 / span 2,
47
+ 3: span 3 / span 3,
48
+ 4: span 4 / span 4,
49
+ 5: span 5 / span 5,
50
+ 6: span 6 / span 6,
51
+ 7: span 7 / span 7,
52
+ 8: span 8 / span 8,
53
+ 9: span 9 / span 9,
54
+ 10: span 10 / span 10,
55
+ 11: span 11 / span 11,
56
+ 12: span 12 / span 12,
57
+ full: string.unquote('1 / -1'),
58
+ ) !default;
59
+
60
+ $utility-grid-row-spans: (
61
+ 1: span 1 / span 1,
62
+ 2: span 2 / span 2,
63
+ 3: span 3 / span 3,
64
+ 4: span 4 / span 4,
65
+ 5: span 5 / span 5,
66
+ 6: span 6 / span 6,
67
+ full: string.unquote('1 / -1'),
68
+ ) !default;
@@ -0,0 +1,50 @@
1
+ @use 'sass:string';
2
+
3
+ // Motion tokens for transition and transform utilities (utility-layer only)
4
+
5
+ $utility-transition-durations: (
6
+ 75: 75ms,
7
+ 100: 100ms,
8
+ 150: 150ms,
9
+ 200: 200ms,
10
+ 300: 300ms,
11
+ 500: 500ms,
12
+ 700: 700ms,
13
+ 1000: 1000ms,
14
+ ) !default;
15
+
16
+ $utility-transition-timing-functions: (
17
+ linear: linear,
18
+ in: cubic-bezier(0.4, 0, 1, 1),
19
+ out: cubic-bezier(0, 0, 0.2, 1),
20
+ 'in-out': cubic-bezier(0.4, 0, 0.2, 1),
21
+ ) !default;
22
+
23
+ $utility-transition-properties: (
24
+ none: none,
25
+ all: all,
26
+ colors: string.unquote('color, background-color, border-color, text-decoration-color, fill, stroke'),
27
+ opacity: opacity,
28
+ shadow: box-shadow,
29
+ transform: transform,
30
+ ) !default;
31
+
32
+ $utility-transform-scales: (
33
+ 0: scale(0),
34
+ 50: scale(0.5),
35
+ 75: scale(0.75),
36
+ 90: scale(0.9),
37
+ 95: scale(0.95),
38
+ 100: scale(1),
39
+ 105: scale(1.05),
40
+ 110: scale(1.1),
41
+ 125: scale(1.25),
42
+ 150: scale(1.5),
43
+ ) !default;
44
+
45
+ $utility-transform-rotates: (
46
+ 0: rotate(0deg),
47
+ 45: rotate(45deg),
48
+ 90: rotate(90deg),
49
+ 180: rotate(180deg),
50
+ ) !default;
@@ -1,3 +1,6 @@
1
+ @use 'sass:map';
2
+ @use '../02-tools/tools.map-loop' as map-loop;
3
+
1
4
  $spacer: 1rem !default;
2
5
 
3
6
  $spacing-sizes: (
@@ -74,12 +77,21 @@ $spacing-sizes: (
74
77
  200: 50rem, //800px
75
78
  ) !default;
76
79
 
80
+ // Semantic gap aliases (optional shorthand for common spacing steps)
81
+ $semantic-gap-sizes: (
82
+ xs: map.get($spacing-sizes, 1),
83
+ sm: map.get($spacing-sizes, 2),
84
+ md: map.get($spacing-sizes, 4),
85
+ lg: map.get($spacing-sizes, 6),
86
+ xl: map.get($spacing-sizes, 8),
87
+ ) !default;
88
+
77
89
  $spacing-important: false !default;
78
90
  $enable-negative-margins: false !default;
79
91
 
80
92
  $negative-spacers: null !default;
81
93
 
82
94
  @if $enable-negative-margins {
83
- $negative-spacers: negativify-map($spacing-sizes) !default;
95
+ $negative-spacers: map-loop.negativify-map($spacing-sizes) !default;
84
96
  }
85
97
 
@@ -50,7 +50,11 @@ $font-size-sm: $font-size-base * 0.875 !default; //14px
50
50
  $font-size-md: $font-size-base * 1.125 !default; //18px
51
51
  $font-size-lg: $font-size-base * 1.25 !default; //20px
52
52
  $font-size-xl: $font-size-base * 1.5 !default; //20px
53
- $font-size-2xl: $font-size-base * 2 !default; //20px
53
+ $font-size-2xl: $font-size-base * 2 !default; //32px
54
+ $font-size-3xl: $font-size-base * 2.25 !default; //36px
55
+ $font-size-4xl: $font-size-base * 2.5 !default; //40px
56
+ $font-size-5xl: $font-size-base * 3 !default; //48px
57
+ $font-size-6xl: $font-size-base * 3.75 !default; //60px
54
58
 
55
59
  $h1-font-size: $font-size-base * 2.5 !default; //40px
56
60
  $h2-font-size: $font-size-base * 2 !default; //32px
@@ -29,3 +29,22 @@
29
29
  }
30
30
  @return $result;
31
31
  }
32
+
33
+ /// Negates numeric values in a map and prefixes keys with `n` (e.g. `1` → `n1: -0.25rem`).
34
+ /// Skips zero values. Used for negative margin utilities.
35
+ @function negativify-map($map) {
36
+ $result: ();
37
+
38
+ @each $key, $value in $map {
39
+ @if $key != 0 {
40
+ $result: map.merge(
41
+ $result,
42
+ (
43
+ 'n#{$key}': $value * -1,
44
+ )
45
+ );
46
+ }
47
+ }
48
+
49
+ @return $result;
50
+ }
@@ -29,6 +29,12 @@ $utility-defaults: (
29
29
  @mixin generate-utility($utility, $infix: '', $is-rfs: false) {
30
30
  $values: map.get($utility, values);
31
31
  $css-var: map.get($utility, css-var);
32
+ $pseudo: map.get($utility, pseudo);
33
+ $legacy-state: map.get($utility, state);
34
+
35
+ @if $pseudo == null and $legacy-state != null {
36
+ $pseudo: $legacy-state;
37
+ }
32
38
 
33
39
  // If the values are a list or string, convert it to a map
34
40
  @if meta.type-of($values) == 'string' or meta.type-of($values) == 'list' {
@@ -38,6 +44,13 @@ $utility-defaults: (
38
44
  @each $key, $value in $values {
39
45
  $properties: map.get($utility, property);
40
46
  $property-class: map.get($utility, class);
47
+ $local-vars: map.get($utility, local-vars);
48
+ $local-vars-only: $value == null and $properties == null and $local-vars and list.length($local-vars) > 0;
49
+
50
+ @if $value == null and not $local-vars-only {
51
+ $warn-class: if($property-class, $property-class, $properties);
52
+ @warn 'Utility value is null for class "#{ $warn-class }" key "#{ $key }" — class will not be generated.';
53
+ }
41
54
 
42
55
  // Handle case where property-class is null
43
56
  @if $property-class == null and $properties {
@@ -48,15 +61,8 @@ $utility-defaults: (
48
61
  );
49
62
  }
50
63
 
51
- // State variants (hover, focus, active, etc.)
52
64
  // Create a local copy of infix to avoid affecting other utilities
53
65
  $local-infix: $infix;
54
- $state: map.get($utility, state);
55
- $local-infix: if(
56
- $state,
57
- if(meta.type-of($state) == 'string', '#{$state}#{$local-infix}', $local-infix),
58
- $local-infix
59
- );
60
66
 
61
67
  // Escape special characters in key for valid CSS class names
62
68
  $escaped-key: if($key, _escape-key($key), null);
@@ -69,28 +75,14 @@ $utility-defaults: (
69
75
  '#{$property-class}#{$local-infix}-#{$escaped-key}',
70
76
  '#{$property-class}#{$local-infix}'
71
77
  );
78
+ $selector: '.#{$class-name}';
72
79
 
73
- .#{$class-name} {
74
- @if $css-var {
75
- // Handle CSS variable generation
76
- $css-variable-name: str-replace(#{$property-class}, '.', '\\.');
77
- --atomix-u-#{$css-variable-name}: #{$value};
78
- } @else if $properties {
79
- @each $property in $properties {
80
- #{$property}: $value;
81
- }
82
- } @else if $value != null {
83
- // Guard: only emit property declaration if value is not null
84
- #{$property-class}: $value;
85
- }
80
+ @if $pseudo {
81
+ $selector: '#{$selector}:#{$pseudo}';
82
+ }
86
83
 
87
- // Add local CSS variables if specified
88
- $local-vars: map.get($utility, local-vars);
89
- @if $local-vars and list.length($local-vars) > 0 {
90
- @each $local-var-name, $local-var-value in $local-vars {
91
- --#{$local-var-name}: #{$local-var-value};
92
- }
93
- }
84
+ #{$selector} {
85
+ @include _apply-utility-declarations($utility, $property-class, $properties, $css-var, $value);
94
86
  }
95
87
  } @else {
96
88
  // Generate class with custom class name
@@ -98,34 +90,45 @@ $utility-defaults: (
98
90
  $modifier: if($key, '-#{$escaped-key}', '');
99
91
 
100
92
  // Responsive infix goes between class and modifier: .u-class-{bp}-{value}
101
- .#{$base-class}#{$local-infix}#{$modifier} {
102
- @if $css-var and $properties {
103
- // Handle CSS variable generation with properties
104
- @each $property in $properties {
105
- $css-variable-name: str-replace(#{$property}, '.', '\\.');
106
- --atomix-u-#{$css-variable-name}: #{$value};
107
- }
108
- } @else if $css-var {
109
- // Handle CSS variable generation without properties
110
- $css-variable-name: str-replace(#{$base-class}, '.', '\\.');
111
- --atomix-u-#{$css-variable-name}#{$modifier}: #{$value};
112
- } @else if $properties {
113
- @each $property in $properties {
114
- #{$property}: $value;
115
- }
116
- } @else if $value != null {
117
- // Guard: only emit property declaration if value is not null
118
- #{$base-class}: $value;
119
- }
93
+ $selector: '.#{$base-class}#{$local-infix}#{$modifier}';
120
94
 
121
- // Add local CSS variables if specified
122
- $local-vars: map.get($utility, local-vars);
123
- @if $local-vars and list.length($local-vars) > 0 {
124
- @each $local-var-name, $local-var-value in $local-vars {
125
- --#{$local-var-name}: #{$local-var-value};
126
- }
127
- }
95
+ @if $pseudo {
96
+ $selector: '#{$selector}:#{$pseudo}';
128
97
  }
98
+
99
+ #{$selector} {
100
+ @include _apply-utility-declarations($utility, $base-class, $properties, $css-var, $value);
101
+ }
102
+ }
103
+ }
104
+ }
105
+
106
+ @mixin _apply-utility-declarations($utility, $class-name, $properties, $css-var, $value) {
107
+ @if $css-var and $properties {
108
+ // Handle CSS variable generation with properties
109
+ @each $property in $properties {
110
+ $css-variable-name: str-replace(#{$property}, '.', '\\.');
111
+ --atomix-u-#{$css-variable-name}: #{$value};
112
+ }
113
+ } @else if $css-var {
114
+ // Handle CSS variable generation without properties
115
+ $css-variable-name: str-replace(#{$class-name}, '.', '\\.');
116
+ --atomix-u-#{$css-variable-name}: #{$value};
117
+ } @else if $properties {
118
+ @each $property in $properties {
119
+ @if $value != null {
120
+ #{$property}: $value;
121
+ }
122
+ }
123
+ } @else if $value != null {
124
+ #{$class-name}: $value;
125
+ }
126
+
127
+ // Add local CSS variables if specified
128
+ $local-vars: map.get($utility, local-vars);
129
+ @if $local-vars and list.length($local-vars) > 0 {
130
+ @each $local-var-name, $local-var-value in $local-vars {
131
+ --#{$local-var-name}: #{$local-var-value};
129
132
  }
130
133
  }
131
134
  }
@@ -169,6 +172,7 @@ $utility-defaults: (
169
172
  values: map.get($config, values),
170
173
  class: map.get($config, class),
171
174
  state: map.get($config, state),
175
+ pseudo: map.get($config, pseudo),
172
176
  rtl: map.get($config, rtl),
173
177
  css-var: map.get($config, css-var),
174
178
  local-vars: map.get($config, local-vars),
@@ -2,16 +2,19 @@
2
2
  @use '../01-settings/settings.grid' as grid;
3
3
  @use '../02-tools/tools.grid' as *;
4
4
  @use '../02-tools/tools.breakpoints' as *;
5
+ @use '../02-tools/tools.rem' as *;
5
6
 
6
7
  .o-grid {
7
- --#{config.$prefix}gutter-y: #{grid.$grid-gutter-width};
8
+ --#{config.$prefix}gutter-y: #{rem(grid.$grid-gutter-width)};
8
9
  @include make-row();
10
+ row-gap: var(--#{config.$prefix}gutter-y);
9
11
 
10
12
  &__col {
11
13
  @include make-col-ready();
12
14
  }
13
15
 
14
16
  &--no-gutters {
17
+ --#{config.$prefix}gutter-y: 0;
15
18
  margin-right: 0;
16
19
  margin-left: 0;
17
20