@aortl/admin-css 0.9.0 → 0.11.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aortl/admin-css",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "Pre-built CSS design system. Drop in via <link> and use semantic class names.",
5
5
  "keywords": [
6
6
  "components",
@@ -67,9 +67,13 @@
67
67
  @apply text-success;
68
68
  }
69
69
 
70
+ /* Warning title/icon use `text-text` rather than `text-warning`: the warning
71
+ accent is yellow-400 in both modes, which fails AA contrast against the
72
+ muted yellow background in light mode. The muted bg + border still carry
73
+ the warning signal. */
70
74
  .alert-warning .alert-title,
71
75
  .alert-warning > :is(i, svg):first-child {
72
- @apply text-warning;
76
+ @apply text-text;
73
77
  }
74
78
 
75
79
  .alert-danger .alert-title,
@@ -3,15 +3,13 @@
3
3
  @apply inline-flex items-center justify-center gap-1
4
4
  px-2 h-5 rounded-full
5
5
  text-xs font-medium leading-none whitespace-nowrap
6
- border border-transparent;
6
+ border border-transparent
7
+ bg-surface-strong text-text;
7
8
  }
8
9
 
9
10
  /* Variants — match the alert palette so danger/success/etc. stay coherent
10
- across status indicators and chips in tables. */
11
- .badge-neutral {
12
- @apply bg-surface-strong text-text;
13
- }
14
-
11
+ across status indicators and chips in tables. The bare `.badge` (no
12
+ modifier) renders the neutral look, now folded into the base. */
15
13
  .badge-info {
16
14
  @apply bg-info-muted text-info border-info-muted;
17
15
  }
@@ -20,8 +18,12 @@
20
18
  @apply bg-success-muted text-success border-success-muted;
21
19
  }
22
20
 
21
+ /* Warning text uses `text-text` rather than `text-warning`: the warning
22
+ accent is yellow-400 in both modes, which fails AA contrast against the
23
+ muted yellow background in light mode. The muted bg + border still carry
24
+ the warning signal. */
23
25
  .badge-warning {
24
- @apply bg-warning-muted text-warning border-warning-muted;
26
+ @apply bg-warning-muted text-text border-warning-muted;
25
27
  }
26
28
 
27
29
  .badge-danger {
@@ -2,28 +2,27 @@
2
2
  .btn {
3
3
  @apply inline-flex items-center justify-center gap-2 px-4 py-2
4
4
  rounded-lg font-medium text-sm leading-none
5
- border border-transparent
5
+ border border-border
6
+ bg-surface-muted text-text hover:bg-surface-strong
6
7
  transition-colors duration-150
7
8
  cursor-pointer select-none
8
9
  focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary
9
10
  disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none;
10
11
  }
11
12
 
12
- /* Variants */
13
+ /* Variants — the bare `.btn` (no modifier) is the low-emphasis default, so
14
+ most admin buttons need no variant class. The colored variants reset the
15
+ border to transparent since the base now carries a visible one. */
13
16
  .btn-primary {
14
- @apply bg-primary text-primary-content hover:bg-primary-hover;
15
- }
16
-
17
- .btn-secondary {
18
- @apply bg-surface-muted text-text border-border hover:bg-surface-strong;
17
+ @apply bg-primary text-primary-content border-transparent hover:bg-primary-hover;
19
18
  }
20
19
 
21
20
  .btn-ghost {
22
- @apply bg-transparent text-text hover:bg-surface-muted;
21
+ @apply bg-transparent text-text border-transparent hover:bg-surface-muted;
23
22
  }
24
23
 
25
24
  .btn-danger {
26
- @apply bg-danger text-danger-content hover:opacity-90;
25
+ @apply bg-danger text-danger-content border-transparent hover:opacity-90;
27
26
  }
28
27
 
29
28
  /* Sizes (md is the default; modifiers override) */
@@ -0,0 +1,20 @@
1
+ @layer components {
2
+ .code-block {
3
+ @apply bg-code-surface text-code-text
4
+ font-mono text-sm
5
+ rounded-lg
6
+ p-3;
7
+ white-space: pre-wrap;
8
+ word-wrap: break-word;
9
+ overflow: auto;
10
+ }
11
+
12
+ /* Opt out of wrapping for log-style content where long lines should
13
+ scroll horizontally instead of breaking. Pair with an inline
14
+ `max-height` to clamp vertical growth — `overflow: auto` above
15
+ turns into a scrollbar automatically. */
16
+ .code-block-nowrap {
17
+ white-space: pre;
18
+ word-wrap: normal;
19
+ }
20
+ }
@@ -0,0 +1,35 @@
1
+ @layer components {
2
+ /* Page content region — a centered, max-width column that also owns the
3
+ vertical rhythm between stacked page sections. Drop it inside the bare
4
+ `.app-shell-main` (which has no padding of its own). Width presets just
5
+ set `--container-max`; override the var per-instance to deviate. */
6
+ .container {
7
+ @apply flex flex-col gap-6 w-full mx-auto px-6 py-6;
8
+ max-width: var(--container-max, 90rem);
9
+ }
10
+
11
+ .container-sm {
12
+ --container-max: 60rem;
13
+ }
14
+
15
+ .container-lg {
16
+ --container-max: 115rem;
17
+ }
18
+
19
+ /* Full-bleed: edge-to-edge within `main`, padding retained. */
20
+ .container-fluid {
21
+ --container-max: none;
22
+ }
23
+
24
+ /* Denser vertical rhythm + tighter block padding for packed screens. */
25
+ .container-compact {
26
+ @apply gap-4 py-4;
27
+ }
28
+
29
+ /* Less horizontal padding on small viewports — reuses the shell breakpoint. */
30
+ @media (max-width: 48rem) {
31
+ .container {
32
+ @apply px-4;
33
+ }
34
+ }
35
+ }
@@ -2,7 +2,7 @@
2
2
  .file-input {
3
3
  @apply inline-flex items-center w-full pr-3 text-sm leading-none
4
4
  bg-surface text-text
5
- border border-transparent rounded-lg overflow-hidden
5
+ border border-border hover:border-border-strong rounded-lg overflow-hidden
6
6
  transition-colors duration-150
7
7
  focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary
8
8
  disabled:opacity-50 disabled:cursor-not-allowed
@@ -13,16 +13,12 @@
13
13
  file:cursor-pointer;
14
14
  }
15
15
 
16
- .file-input-bordered {
17
- @apply border-border hover:border-border-strong;
18
- }
19
-
20
16
  .file-input-ghost {
21
- @apply bg-transparent hover:bg-surface-muted;
17
+ @apply bg-transparent border-transparent hover:bg-surface-muted hover:border-transparent;
22
18
  }
23
19
 
24
20
  .file-input-danger {
25
- @apply border-danger focus-visible:outline-danger;
21
+ @apply border-danger hover:border-danger focus-visible:outline-danger;
26
22
  }
27
23
 
28
24
  /* Sizes */
@@ -1,6 +1,7 @@
1
1
  @import "./accordion.css";
2
2
  @import "./alert.css";
3
3
  @import "./app-shell.css";
4
+ @import "./container.css";
4
5
  @import "./badge.css";
5
6
  @import "./brand-tile.css";
6
7
  @import "./kbd.css";
@@ -20,6 +21,7 @@
20
21
  @import "./switch.css";
21
22
  @import "./select.css";
22
23
  @import "./card.css";
24
+ @import "./stat-card.css";
23
25
  @import "./dialog.css";
24
26
  @import "./field.css";
25
27
  @import "./file-input.css";
@@ -30,3 +32,4 @@
30
32
  @import "./tabs.css";
31
33
  @import "./table.css";
32
34
  @import "./tooltip.css";
35
+ @import "./code-block.css";
@@ -3,23 +3,19 @@
3
3
  @apply inline-flex items-center w-full px-3 py-2
4
4
  rounded-lg text-sm leading-none
5
5
  bg-surface text-text
6
- border border-transparent
6
+ border border-border hover:border-border-strong
7
7
  transition-colors duration-150
8
8
  placeholder:text-text-muted
9
9
  focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary
10
10
  disabled:opacity-50 disabled:cursor-not-allowed;
11
11
  }
12
12
 
13
- .input-bordered {
14
- @apply border-border hover:border-border-strong;
15
- }
16
-
17
13
  .input-ghost {
18
- @apply bg-transparent hover:bg-surface-muted;
14
+ @apply bg-transparent border-transparent hover:bg-surface-muted hover:border-transparent;
19
15
  }
20
16
 
21
17
  .input-danger {
22
- @apply border-danger focus-visible:outline-danger;
18
+ @apply border-danger hover:border-danger focus-visible:outline-danger;
23
19
  }
24
20
 
25
21
  /* Sizes */
@@ -3,7 +3,7 @@
3
3
  @apply inline-flex items-center justify-between gap-2 w-full px-3 py-2
4
4
  rounded-lg text-sm leading-none text-left
5
5
  bg-surface text-text
6
- border border-transparent
6
+ border border-border hover:border-border-strong
7
7
  cursor-pointer select-none
8
8
  transition-colors duration-150
9
9
  focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary
@@ -18,16 +18,12 @@
18
18
  @apply text-text-muted;
19
19
  }
20
20
 
21
- .select-bordered {
22
- @apply border-border hover:border-border-strong;
23
- }
24
-
25
21
  .select-ghost {
26
- @apply bg-transparent hover:bg-surface-muted;
22
+ @apply bg-transparent border-transparent hover:bg-surface-muted hover:border-transparent;
27
23
  }
28
24
 
29
25
  .select-danger {
30
- @apply border-danger focus-visible:outline-danger;
26
+ @apply border-danger hover:border-danger focus-visible:outline-danger;
31
27
  }
32
28
 
33
29
  /* Sizes */
@@ -0,0 +1,31 @@
1
+ @layer components {
2
+ .stat-card {
3
+ @apply flex flex-col gap-1
4
+ p-4
5
+ bg-surface text-text
6
+ border border-border
7
+ rounded-xl
8
+ shadow-xs;
9
+ }
10
+
11
+ .stat-card-label {
12
+ @apply flex items-center gap-2 text-sm text-text-muted font-medium;
13
+ }
14
+
15
+ .stat-card-value {
16
+ @apply text-2xl font-bold tabular-nums leading-tight;
17
+ }
18
+
19
+ .stat-card-detail {
20
+ @apply text-sm text-text-muted;
21
+ }
22
+
23
+ /* Modifiers — mirror `.card`. */
24
+ .stat-card-compact {
25
+ @apply p-3 gap-0.5;
26
+ }
27
+
28
+ .stat-card-bordered {
29
+ @apply shadow-none border-border-strong;
30
+ }
31
+ }
@@ -52,14 +52,13 @@
52
52
  @apply outline-2 outline-offset-2 outline-primary;
53
53
  }
54
54
 
55
- /* Bordered (default) — underline marker on the active tab. The pseudo sits
56
- below the .tab, overlapping the .tab-list bottom border. */
57
- .tabs-bordered .tab,
55
+ /* Default — underline marker on the active tab. The pseudo sits below the
56
+ .tab, overlapping the .tab-list bottom border. Applies to any tabs root
57
+ that isn't .tabs-boxed, so the bare `.tabs` default gets it for free. */
58
58
  .tabs:not(.tabs-boxed) .tab {
59
59
  position: relative;
60
60
  }
61
61
 
62
- .tabs-bordered .tab::after,
63
62
  .tabs:not(.tabs-boxed) .tab::after {
64
63
  content: "";
65
64
  position: absolute;
@@ -71,9 +70,6 @@
71
70
  transition: transform 150ms ease;
72
71
  }
73
72
 
74
- .tabs-bordered .tab[data-selected]::after,
75
- .tabs-bordered .tab[aria-selected="true"]::after,
76
- .tabs-bordered .tab-input:checked + .tab::after,
77
73
  .tabs:not(.tabs-boxed) .tab[data-selected]::after,
78
74
  .tabs:not(.tabs-boxed) .tab[aria-selected="true"]::after,
79
75
  .tabs:not(.tabs-boxed) .tab-input:checked + .tab::after {
@@ -153,7 +149,6 @@
153
149
  @apply w-full justify-start;
154
150
  }
155
151
 
156
- .tabs[data-orientation="vertical"].tabs-bordered .tab::after,
157
152
  .tabs[data-orientation="vertical"]:not(.tabs-boxed) .tab::after {
158
153
  inset-inline: auto;
159
154
  inset-inline-end: -1px;
@@ -163,8 +158,6 @@
163
158
  transform: scaleY(0);
164
159
  }
165
160
 
166
- .tabs[data-orientation="vertical"].tabs-bordered .tab[data-selected]::after,
167
- .tabs[data-orientation="vertical"].tabs-bordered .tab[aria-selected="true"]::after,
168
161
  .tabs[data-orientation="vertical"]:not(.tabs-boxed) .tab[data-selected]::after,
169
162
  .tabs[data-orientation="vertical"]:not(.tabs-boxed) .tab[aria-selected="true"]::after {
170
163
  transform: scaleY(1);
@@ -3,23 +3,19 @@
3
3
  @apply block w-full px-3 py-2 min-h-20 resize-y
4
4
  rounded-lg text-sm
5
5
  bg-surface text-text
6
- border border-transparent
6
+ border border-border hover:border-border-strong
7
7
  transition-colors duration-150
8
8
  placeholder:text-text-muted
9
9
  focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary
10
10
  disabled:opacity-50 disabled:cursor-not-allowed;
11
11
  }
12
12
 
13
- .textarea-bordered {
14
- @apply border-border hover:border-border-strong;
15
- }
16
-
17
13
  .textarea-ghost {
18
- @apply bg-transparent hover:bg-surface-muted;
14
+ @apply bg-transparent border-transparent hover:bg-surface-muted hover:border-transparent;
19
15
  }
20
16
 
21
17
  .textarea-danger {
22
- @apply border-danger focus-visible:outline-danger;
18
+ @apply border-danger hover:border-danger focus-visible:outline-danger;
23
19
  }
24
20
 
25
21
  /* Sizes */
package/src/theme.css CHANGED
@@ -211,6 +211,13 @@
211
211
  --color-border: light-dark(var(--color-base-150), var(--color-base-850));
212
212
  --color-border-strong: light-dark(var(--color-base-300), var(--color-base-700));
213
213
 
214
+ /* Code — neutral surface for <pre>-style output blocks (logs, JSON, LLM
215
+ output). One step darker than `surface-strong` in light mode so the
216
+ block visually carves out from regular chrome; matches `surface-muted`
217
+ depth in dark mode. */
218
+ --color-code-surface: light-dark(var(--color-base-150), var(--color-base-950));
219
+ --color-code-text: light-dark(var(--color-base-800), var(--color-base-200));
220
+
214
221
  /* Primary — Flexoki blue */
215
222
  --color-primary: light-dark(var(--color-blue-600), var(--color-blue-400));
216
223
  --color-primary-hover: light-dark(var(--color-blue-700), var(--color-blue-300));
package/src/utilities.css CHANGED
@@ -77,6 +77,12 @@
77
77
  /* Aspect ratio — responsive */
78
78
  @source inline("{,sm:,md:,lg:,xl:,2xl:}aspect-{auto,square,video}");
79
79
 
80
+ /* Object fit + position (avatars, thumbnails, logos) — responsive */
81
+ @source inline("{,sm:,md:,lg:,xl:,2xl:}object-{contain,cover,fill,none,scale-down}");
82
+ @source inline(
83
+ "{,sm:,md:,lg:,xl:,2xl:}object-{top,bottom,left,right,center,left-top,left-bottom,right-top,right-bottom}"
84
+ );
85
+
80
86
  /* Translate (x/y only — full transforms intentionally skipped) — responsive */
81
87
  @source inline(
82
88
  "{,sm:,md:,lg:,xl:,2xl:}translate-{x,y}-{0,0.5,1,1.5,2,3,4,6,8,12,16,20,24,32,1/2,full}"
@@ -85,9 +91,18 @@
85
91
  /* Typography (non-size) — no variants */
86
92
  @source inline("font-{thin,extralight,light,normal,medium,semibold,bold,extrabold,black}");
87
93
  @source inline("font-{sans,mono,serif}");
94
+ @source inline("{italic,not-italic}");
95
+ @source inline("{uppercase,lowercase,capitalize,normal-case}");
96
+ @source inline(
97
+ "{normal-nums,ordinal,slashed-zero,lining-nums,oldstyle-nums,proportional-nums,tabular-nums}"
98
+ );
88
99
  @source inline("leading-{none,tight,snug,normal,relaxed,loose,3,4,5,6,7,8,9,10}");
89
100
  @source inline("tracking-{tighter,tight,normal,wide,wider,widest}");
90
101
  @source inline("text-{wrap,nowrap,balance,pretty}");
102
+ @source inline("whitespace-{normal,nowrap,pre,pre-line,pre-wrap,break-spaces}");
103
+ @source inline("break-{normal,words,all,keep}");
104
+ @source inline("align-{baseline,top,middle,bottom,text-top,text-bottom,sub,super}");
105
+ @source inline("list-{disc,decimal,none,inside,outside}");
91
106
  @source inline("{underline,overline,line-through,no-underline,truncate}");
92
107
 
93
108
  /* Borders + rounded — interactive */
@@ -133,5 +148,9 @@
133
148
  "{,hover:,focus:,focus-visible:,active:}opacity-{0,5,10,15,20,25,30,40,50,60,70,75,80,90,95,100}"
134
149
  );
135
150
 
151
+ /* Interaction primitives (select-all an ID cell, disable a layer) — no variants */
152
+ @source inline("pointer-events-{none,auto}");
153
+ @source inline("select-{none,text,all,auto}");
154
+
136
155
  /* Z-index — no variants */
137
156
  @source inline("z-{0,10,20,30,40,50,auto}");