margo-ui 1.2.0 → 1.2.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.
package/margo.css CHANGED
@@ -3,5 +3,6 @@
3
3
  @import "./src/css/theme.css";
4
4
  @import "./src/css/custom-variant.css";
5
5
  @import "./src/css/utility.css";
6
+ @import "./src/css/grid.css";
6
7
 
7
8
  @source "../**/*.{ts,tsx,js,mjs}";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "margo-ui",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "A small React UI kit built on Tailwind CSS v4 design tokens, themeable through plain CSS custom properties.",
5
5
  "keywords": [
6
6
  "react",
@@ -10,7 +10,7 @@ export const buttonIconClassName =
10
10
  "relative z-10 flex size-4 min-w-0 shrink-0 items-center justify-center [direction:ltr]";
11
11
 
12
12
  export const buttonLabelClassName =
13
- "relative z-10 flex items-center text-sm whitespace-nowrap lowercase [direction:ltr] px-0.5";
13
+ "relative z-10 flex items-center text-sm whitespace-nowrap margo-text-box-trim lowercase [direction:ltr] px-0.5";
14
14
 
15
15
  export const buttonGridClassName =
16
16
  "grid items-center gap-0 transition-[grid-template-columns,gap] duration-[180ms] ease-in-out";
@@ -1,4 +1,4 @@
1
1
  export const chipBaseClassName =
2
- "bg-secondary px-3 py-0.5 whitespace-nowrap lowercase flex-none leading-none rounded-md text-mc shadow-chip";
2
+ "bg-secondary margo-text-box-trim flex items-center justify-center px-3 py-0.5 whitespace-nowrap lowercase flex-none leading-none rounded-md text-mc shadow-chip";
3
3
 
4
4
  export const chipActiveClassName = "bg-on-main text-main";
@@ -0,0 +1,229 @@
1
+ /*
2
+ * 12-column grid with full-bleed support.
3
+ *
4
+ * Tunable from the consumer through four variables only (see variables.css):
5
+ * --margo-grid-max-width, --margo-grid-padding, --margo-grid-gutter-x,
6
+ * --margo-grid-gutter-y. Padding and gutters are fully independent: the side
7
+ * padding is real padding on the container, the gutters are column gaps that
8
+ * only exist between the 12 columns. Any combination is valid, including a
9
+ * padding smaller than the gutter.
10
+ *
11
+ * Named lines available inside `margo-grid`:
12
+ * content-start | col-start 1..12 / col-end 1..12 | content-end
13
+ * Rows have no template and no names: they are addressed by index.
14
+ *
15
+ * Full bleed is not a line: it is a negative margin that cancels the distance
16
+ * between the content area and the viewport edge (--margo-grid-bleed), so it
17
+ * works from any column and at any nesting depth.
18
+ */
19
+
20
+ /*
21
+ * Root layout container: centers a 12-column content area capped at
22
+ * --margo-grid-max-width and pads it by --margo-grid-padding on both sides.
23
+ * Direct children sit on the whole content area by default, so a plain
24
+ * `<div className="margo-grid"><section /></div>` is already correctly aligned.
25
+ * That default has zero specificity, so any margo-col-* utility overrides it.
26
+ *
27
+ * Use on: page sections, headers, footers — the outermost element of a layout.
28
+ */
29
+ @utility margo-grid {
30
+ --margo-grid-bleed: max(var(--margo-grid-padding), calc((100vw - var(--margo-grid-max-width)) / 2));
31
+
32
+ width: 100%;
33
+ max-width: calc(var(--margo-grid-max-width) + var(--margo-grid-padding) * 2);
34
+ margin-inline: auto;
35
+ padding-inline: var(--margo-grid-padding);
36
+
37
+ display: grid;
38
+ column-gap: var(--margo-grid-gutter-x);
39
+ row-gap: var(--margo-grid-gutter-y);
40
+ grid-template-columns: [content-start] repeat(12, [col-start] minmax(0, 1fr) [col-end]) [content-end];
41
+
42
+ :where(&) > * {
43
+ grid-column-start: content-start;
44
+ grid-column-end: content-end;
45
+ }
46
+ }
47
+
48
+ /*
49
+ * Nested grid that reuses the parent tracks and line names instead of creating
50
+ * new ones, so children keep aligning to the same 12 columns at any depth.
51
+ * Must be a child of margo-grid (or of another margo-grid-sub) and must span
52
+ * the columns it wants to inherit — as a child of margo-grid it already covers
53
+ * the whole content area.
54
+ *
55
+ * Children are auto-placed: one column each unless they carry a margo-col-*
56
+ * utility, so `margo-col-span-6` items flow two per row.
57
+ *
58
+ * Use on: a list/card wrapper whose grandchildren still need global alignment.
59
+ */
60
+ @utility margo-grid-sub {
61
+ display: grid;
62
+ grid-template-columns: subgrid;
63
+ row-gap: var(--margo-grid-gutter-y);
64
+ }
65
+
66
+ /*
67
+ * Standalone 12-column grid: same line names and gutters, but no max-width and
68
+ * no side padding — it fills whatever box it is placed in.
69
+ *
70
+ * Use on: an isolated component that needs 12 columns of its own, outside of
71
+ * (or independent from) the page layout.
72
+ */
73
+ @utility margo-grid-flat {
74
+ display: grid;
75
+ grid-template-columns: [content-start] repeat(12, [col-start] minmax(0, 1fr) [col-end]) [content-end];
76
+ column-gap: var(--margo-grid-gutter-x);
77
+ row-gap: var(--margo-grid-gutter-y);
78
+ }
79
+
80
+ /*
81
+ * Full bleed: edge to edge of the viewport, escaping both the max-width and the
82
+ * side padding. Use on: background bands, hero images, sticky bars.
83
+ * To keep inner content on the grid, nest a margo-grid inside it.
84
+ */
85
+ @utility margo-col-full {
86
+ grid-column-start: content-start;
87
+ grid-column-end: content-end;
88
+ margin-inline: calc(var(--margo-grid-bleed) * -1);
89
+ }
90
+
91
+ /*
92
+ * Back to the centered content area (all 12 columns), dropping any bleed.
93
+ * Use to reset an element that a variant put on `full` at another breakpoint.
94
+ */
95
+ @utility margo-col-content {
96
+ grid-column-start: content-start;
97
+ grid-column-end: content-end;
98
+ margin-inline: 0;
99
+ }
100
+
101
+ /*
102
+ * A single column, by index: `margo-col-4` occupies column 4 only.
103
+ * Use for one-cell items; combine with variants, e.g. `900:margo-col-7`.
104
+ */
105
+ @utility margo-col-* {
106
+ grid-column-start: col-start --value(integer);
107
+ grid-column-end: col-end --value(integer);
108
+ }
109
+
110
+ /* Bleed off the left edge of the viewport, keeping the current end line. */
111
+ @utility margo-col-start-full {
112
+ grid-column-start: content-start;
113
+ margin-inline-start: calc(var(--margo-grid-bleed) * -1);
114
+ }
115
+
116
+ /* Start at the left edge of the content area, dropping any left bleed. */
117
+ @utility margo-col-start-content {
118
+ grid-column-start: content-start;
119
+ margin-inline-start: 0;
120
+ }
121
+
122
+ /*
123
+ * Start at the beginning of column N: `margo-col-start-5`.
124
+ * Pairs with margo-col-end-* (explicit range) or margo-col-span-* (length).
125
+ */
126
+ @utility margo-col-start-* {
127
+ grid-column-start: col-start --value(integer);
128
+ }
129
+
130
+ /* Bleed off the right edge of the viewport, keeping the current start line. */
131
+ @utility margo-col-end-full {
132
+ grid-column-end: content-end;
133
+ margin-inline-end: calc(var(--margo-grid-bleed) * -1);
134
+ }
135
+
136
+ /* End at the right edge of the content area, dropping any right bleed. */
137
+ @utility margo-col-end-content {
138
+ grid-column-end: content-end;
139
+ margin-inline-end: 0;
140
+ }
141
+
142
+ /*
143
+ * End at the end of column N, inclusive: `margo-col-start-5 margo-col-end-8`
144
+ * covers columns 5 through 8.
145
+ */
146
+ @utility margo-col-end-* {
147
+ grid-column-end: col-end --value(integer);
148
+ }
149
+
150
+ /* Span the full bleed width regardless of where the item starts. */
151
+ @utility margo-col-span-full {
152
+ grid-column-start: content-start;
153
+ grid-column-end: content-end;
154
+ margin-inline: calc(var(--margo-grid-bleed) * -1);
155
+ }
156
+
157
+ /*
158
+ * Span N columns from wherever the item starts: `margo-col-span-6`.
159
+ * In margo-grid-sub / margo-grid-flat the item keeps auto-placing, so
160
+ * `margo-col-span-12 900:margo-col-span-6` items flow one per row on mobile
161
+ * and two per row from 900 up. As a direct child of margo-grid the start is
162
+ * pinned to the content edge instead.
163
+ */
164
+ @utility margo-col-span-* {
165
+ grid-column-end: span --value(integer);
166
+ }
167
+
168
+ /*
169
+ * Rows are implicit and unnamed, so they are addressed by index only.
170
+ * `margo-row-2` puts the item on the second row, which is how two items are
171
+ * made to share a row band or to overlap a column that spans several rows.
172
+ */
173
+ @utility margo-row-* {
174
+ grid-row-start: --value(integer);
175
+ grid-row-end: span 1;
176
+ }
177
+
178
+ /*
179
+ * Start on row N and keep the current end: `margo-row-start-2`.
180
+ * Pair with margo-row-span-* for the length; there is no margo-row-end-*,
181
+ * because without named row lines an end index would mean the line before
182
+ * the row, the opposite of how margo-col-end-* reads.
183
+ */
184
+ @utility margo-row-start-* {
185
+ grid-row-start: --value(integer);
186
+ }
187
+
188
+ /* Span N rows from wherever the item starts: `margo-row-span-2`. */
189
+ @utility margo-row-span-* {
190
+ grid-row-end: span --value(integer);
191
+ }
192
+
193
+ /*
194
+ * Gutter overrides, on the spacing scale: `margo-gutter-y-0`, `margo-gutter-x-4`.
195
+ * They set the grid variables rather than the gap properties, so they never
196
+ * depend on utility order to win, and they cascade into nested margo-grid /
197
+ * margo-grid-sub unless those override the gutter again.
198
+ */
199
+ @utility margo-gutter-* {
200
+ --margo-grid-gutter-x: --spacing(--value(integer));
201
+ --margo-grid-gutter-y: --spacing(--value(integer));
202
+ }
203
+
204
+ @utility margo-gutter-x-* {
205
+ --margo-grid-gutter-x: --spacing(--value(integer));
206
+ }
207
+
208
+ @utility margo-gutter-y-* {
209
+ --margo-grid-gutter-y: --spacing(--value(integer));
210
+ }
211
+
212
+ /*
213
+ * Side padding override, on the spacing scale: `margo-padding-8`.
214
+ * Also feeds --margo-grid-bleed, so full-bleed children stay exact.
215
+ */
216
+ @utility margo-padding-* {
217
+ --margo-grid-padding: --spacing(--value(integer));
218
+ }
219
+
220
+ /*
221
+ * Non-grid escape hatch: same max-width and side padding as margo-grid, but a
222
+ * plain block. Use when a section needs the layout width without any columns.
223
+ */
224
+ @utility margo-container {
225
+ width: 100%;
226
+ max-width: calc(var(--margo-grid-max-width) + var(--margo-grid-padding) * 2);
227
+ margin-inline: auto;
228
+ padding-inline: var(--margo-grid-padding);
229
+ }
@@ -4,3 +4,7 @@
4
4
  linear-gradient(var(--margo-color-main), var(--margo-color-main)) padding-box,
5
5
  linear-gradient(to bottom right, var(--margo-color-primary-darken), var(--margo-color-primary)) border-box;
6
6
  }
7
+
8
+ @utility margo-text-box-trim {
9
+ text-box: trim-start cap alphabetic;
10
+ }
@@ -31,9 +31,11 @@
31
31
 
32
32
  --margo-border-width-2: 1.5px;
33
33
 
34
- --margo-shadow-card-color: 0 0 0;
35
- --margo-shadow-button-color: 0 0 0;
36
- --margo-shadow-chip-color: 0 0 0;
34
+ --margo-grid-max-width: 80rem;
35
+ --margo-grid-padding: 1rem;
36
+ --margo-grid-gutter-x: 2rem;
37
+ --margo-grid-gutter-y: 2rem;
38
+ --margo-grid-bleed: max(var(--margo-grid-padding), calc((100vw - var(--margo-grid-max-width)) / 2));
37
39
  }
38
40
 
39
41
  :root {
@@ -47,11 +49,11 @@
47
49
  --margo-color-primary-darken: #45b93f;
48
50
  --margo-color-secondary: #d3d3d3;
49
51
  --margo-color-medium: #7e7e7e;
50
- --margo-color-border: #dcdcdc;
52
+ --margo-color-border: #cfcfcf;
51
53
 
52
- --margo-shadow-card: 0 4px 12px -4px rgb(var(--margo-shadow-card-color) / 0.1);
53
- --margo-shadow-button: 0 2px 6px -2px rgb(var(--margo-shadow-button-color) / 0.1);
54
- --margo-shadow-chip: 0 1px 3px -1px rgb(var(--margo-shadow-chip-color) / 0.5);
54
+ --margo-shadow-card: 0 8px 6px -4px rgb(220, 220, 220, 0.5);
55
+ --margo-shadow-button: 0px 2px 3px -1px rgb(220, 220, 220, 0.6);
56
+ --margo-shadow-chip: 0 1px 3px -1px rgb(0, 0, 0, 0.6);
55
57
  }
56
58
 
57
59
  .dark {
@@ -67,7 +69,7 @@
67
69
  --margo-color-medium: #999999;
68
70
  --margo-color-border: #2c2c2c;
69
71
 
70
- --margo-shadow-card: 0 4px 12px -4px rgb(var(--margo-shadow-card-color) / 0.5);
71
- --margo-shadow-button: 0 2px 6px -2px rgb(var(--margo-shadow-button-color) / 0.5);
72
- --margo-shadow-chip: 0 1px 3px -1px rgb(var(--margo-shadow-chip-color) / 0.5);
72
+ --margo-shadow-card: 0 4px 12px -4px rgb(0, 0, 0, 0.5);
73
+ --margo-shadow-button: 0 2px 6px -2px rgb(0, 0, 0, 0.5);
74
+ --margo-shadow-chip: 0 1px 3px -1px rgb(0, 0, 0, 0.5);
73
75
  }
@@ -3,10 +3,45 @@ import { extendTailwindMerge } from "tailwind-merge";
3
3
 
4
4
  import type { ClassValue } from "clsx";
5
5
 
6
- const twMerge = extendTailwindMerge({
6
+ const isNumber = (value: string) => /^\d+$/.test(value);
7
+
8
+ const isColumnLine = (value: string) => value === "full" || value === "content" || isNumber(value);
9
+
10
+ type MargoClassGroupIds =
11
+ | "margo-col"
12
+ | "margo-col-start"
13
+ | "margo-col-end"
14
+ | "margo-col-span"
15
+ | "margo-row"
16
+ | "margo-row-start"
17
+ | "margo-row-span"
18
+ | "margo-gutter"
19
+ | "margo-gutter-x"
20
+ | "margo-gutter-y"
21
+ | "margo-padding";
22
+
23
+ const twMerge = extendTailwindMerge<MargoClassGroupIds>({
7
24
  extend: {
8
25
  classGroups: {
9
26
  "font-size": ["text-mc"],
27
+ "margo-col": [{ "margo-col": [isColumnLine] }],
28
+ "margo-col-start": [{ "margo-col-start": [isColumnLine] }],
29
+ "margo-col-end": [{ "margo-col-end": [isColumnLine] }],
30
+ "margo-col-span": [{ "margo-col-span": [isColumnLine] }],
31
+ "margo-row": [{ "margo-row": [isNumber] }],
32
+ "margo-row-start": [{ "margo-row-start": [isNumber] }],
33
+ "margo-row-span": [{ "margo-row-span": [isNumber] }],
34
+ "margo-gutter": [{ "margo-gutter": [isNumber] }],
35
+ "margo-gutter-x": [{ "margo-gutter-x": [isNumber] }],
36
+ "margo-gutter-y": [{ "margo-gutter-y": [isNumber] }],
37
+ "margo-padding": [{ "margo-padding": [isNumber] }],
38
+ },
39
+ conflictingClassGroups: {
40
+ "margo-col": ["margo-col-start", "margo-col-end", "margo-col-span"],
41
+ "margo-col-span": ["margo-col-end"],
42
+ "margo-col-end": ["margo-col-span"],
43
+ "margo-row": ["margo-row-start", "margo-row-span"],
44
+ "margo-gutter": ["margo-gutter-x", "margo-gutter-y"],
10
45
  },
11
46
  },
12
47
  });