@aortl/admin-css 0.7.0 → 0.8.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.
@@ -7,18 +7,6 @@
7
7
  @apply rounded-none relative focus-visible:z-10;
8
8
  }
9
9
 
10
- .btn-group > .btn:not(:first-child) {
11
- @apply -ml-px;
12
- }
13
-
14
- .btn-group > .btn:first-child {
15
- @apply rounded-l-lg;
16
- }
17
-
18
- .btn-group > .btn:last-child {
19
- @apply rounded-r-lg;
20
- }
21
-
22
10
  /* Split-button support: a <details class="menu"> child sits in the strip
23
11
  alongside .btn children, with its .menu-trigger getting the same edge
24
12
  treatment as the buttons around it. inline-flex on the details makes
@@ -29,19 +17,26 @@
29
17
  display: inline-flex;
30
18
  }
31
19
 
32
- .btn-group > .menu:not(:first-child) {
33
- @apply -ml-px;
34
- }
35
-
36
20
  .btn-group > .menu > .menu-trigger {
37
21
  @apply rounded-none;
38
22
  }
39
23
 
40
- .btn-group > .menu:first-child > .menu-trigger {
24
+ /* Horizontal-only: overlap left edges, round outer left/right corners,
25
+ and paint the seam between adjacent items as a left-side divider.
26
+ Scoped with :not(.btn-group-vertical) so vertical groups (which share
27
+ the .btn-group class) don't inherit horizontal edge treatment. */
28
+ .btn-group:not(.btn-group-vertical) > .btn:not(:first-child),
29
+ .btn-group:not(.btn-group-vertical) > .menu:not(:first-child) {
30
+ @apply -ml-px;
31
+ }
32
+
33
+ .btn-group:not(.btn-group-vertical) > .btn:first-child,
34
+ .btn-group:not(.btn-group-vertical) > .menu:first-child > .menu-trigger {
41
35
  @apply rounded-l-lg;
42
36
  }
43
37
 
44
- .btn-group > .menu:last-child > .menu-trigger {
38
+ .btn-group:not(.btn-group-vertical) > .btn:last-child,
39
+ .btn-group:not(.btn-group-vertical) > .menu:last-child > .menu-trigger {
45
40
  @apply rounded-r-lg;
46
41
  }
47
42
 
@@ -50,8 +45,8 @@
50
45
  means the divider works across every .btn variant — light on
51
46
  coloured buttons, dark on ghost/secondary — without per-variant
52
47
  rules. */
53
- .btn-group > .btn:not(:first-child),
54
- .btn-group > .menu:not(:first-child) > .menu-trigger {
48
+ .btn-group:not(.btn-group-vertical) > .btn:not(:first-child),
49
+ .btn-group:not(.btn-group-vertical) > .menu:not(:first-child) > .menu-trigger {
55
50
  border-left-color: color-mix(in srgb, currentColor 25%, transparent);
56
51
  }
57
52
 
@@ -59,15 +54,27 @@
59
54
  @apply inline-flex flex-col;
60
55
  }
61
56
 
62
- .btn-group-vertical > .btn:not(:first-child) {
63
- @apply -mt-px ml-0;
57
+ .btn-group-vertical > .btn {
58
+ @apply justify-start;
59
+ }
60
+
61
+ .btn-group-vertical > .btn:not(:first-child),
62
+ .btn-group-vertical > .menu:not(:first-child) {
63
+ @apply -mt-px;
64
+ }
65
+
66
+ .btn-group-vertical > .btn:first-child,
67
+ .btn-group-vertical > .menu:first-child > .menu-trigger {
68
+ @apply rounded-t-lg;
64
69
  }
65
70
 
66
- .btn-group-vertical > .btn:first-child {
67
- @apply rounded-t-lg rounded-bl-none;
71
+ .btn-group-vertical > .btn:last-child,
72
+ .btn-group-vertical > .menu:last-child > .menu-trigger {
73
+ @apply rounded-b-lg;
68
74
  }
69
75
 
70
- .btn-group-vertical > .btn:last-child {
71
- @apply rounded-b-lg rounded-tr-none;
76
+ .btn-group-vertical > .btn:not(:first-child),
77
+ .btn-group-vertical > .menu:not(:first-child) > .menu-trigger {
78
+ border-top-color: color-mix(in srgb, currentColor 25%, transparent);
72
79
  }
73
80
  }
@@ -5,7 +5,6 @@
5
5
  border border-border
6
6
  rounded-xl
7
7
  shadow-lg
8
- overflow-hidden
9
8
  flex-col;
10
9
  width: calc(100% - 2rem);
11
10
  max-width: 32rem;
@@ -76,6 +75,11 @@
76
75
  px-5 py-3
77
76
  border-t border-border
78
77
  bg-surface-muted;
78
+ /* Inherits the dialog's bottom-corner radius so the muted background
79
+ doesn't square off past the parent's rounded corners — previously
80
+ handled by `overflow: hidden` on `.dialog`, which clipped popups. */
81
+ border-bottom-left-radius: inherit;
82
+ border-bottom-right-radius: inherit;
79
83
  }
80
84
 
81
85
  .dialog-close {
@@ -3,6 +3,8 @@
3
3
  @import "./app-shell.css";
4
4
  @import "./badge.css";
5
5
  @import "./brand-tile.css";
6
+ @import "./kbd.css";
7
+ @import "./indicator.css";
6
8
  @import "./spinner.css";
7
9
  @import "./progress.css";
8
10
  @import "./breadcrumbs.css";
@@ -0,0 +1,113 @@
1
+ @layer components {
2
+ /*
3
+ * Wrapper for placing a small floating element (badge, count, status dot)
4
+ * at a corner or edge of another element — notification badges on icon
5
+ * buttons, status dots on avatars, "new" markers on tiles.
6
+ *
7
+ * Composition is driven by CSS custom properties so a horizontal modifier
8
+ * (start/center/end) and a vertical modifier (top/middle/bottom) compose
9
+ * naturally without needing a 3×3 grid of explicit selectors.
10
+ */
11
+ .indicator {
12
+ @apply relative inline-flex w-max;
13
+ }
14
+
15
+ /*
16
+ * Auto-offset for common rounded anchors so the indicator aligns with the
17
+ * visual corner instead of the geometric box corner. Roughly half the
18
+ * anchor's border-radius. Override per-instance by passing the `offset`
19
+ * prop or setting `--indicator-offset` inline.
20
+ */
21
+ .indicator:has(> .btn),
22
+ .indicator:has(> .input) {
23
+ --indicator-offset: 2px;
24
+ }
25
+ .indicator:has(> .card) {
26
+ --indicator-offset: 6px;
27
+ }
28
+
29
+ .indicator-item {
30
+ @apply absolute z-[1] whitespace-nowrap;
31
+ top: var(--indicator-top, 0);
32
+ bottom: var(--indicator-bottom, auto);
33
+ inset-inline-start: var(--indicator-start, auto);
34
+ inset-inline-end: var(--indicator-end, 0);
35
+ /*
36
+ * Two composed translates: the first half-overlaps the corner; the second
37
+ * pulls the item back toward the anchor center by `--indicator-offset`
38
+ * (default 0). The pull direction is set per-modifier so it tracks the
39
+ * placement automatically — e.g. `top-end` pulls left-and-down. Useful
40
+ * for anchors with rounded corners: try `--indicator-offset: 4px` for a
41
+ * `rounded-md` button.
42
+ */
43
+ transform: translate(var(--indicator-tx, 50%), var(--indicator-ty, -50%))
44
+ translate(
45
+ var(--indicator-offset-x, calc(-1 * var(--indicator-offset, 0px))),
46
+ var(--indicator-offset-y, var(--indicator-offset, 0px))
47
+ );
48
+ }
49
+
50
+ /* Horizontal */
51
+ .indicator-start {
52
+ --indicator-start: 0;
53
+ --indicator-end: auto;
54
+ --indicator-tx: -50%;
55
+ --indicator-offset-x: var(--indicator-offset, 0px);
56
+ }
57
+ .indicator-center {
58
+ --indicator-start: 50%;
59
+ --indicator-end: auto;
60
+ --indicator-tx: -50%;
61
+ --indicator-offset-x: 0px;
62
+ }
63
+ .indicator-end {
64
+ --indicator-start: auto;
65
+ --indicator-end: 0;
66
+ --indicator-tx: 50%;
67
+ --indicator-offset-x: calc(-1 * var(--indicator-offset, 0px));
68
+ }
69
+
70
+ /* Vertical */
71
+ .indicator-top {
72
+ --indicator-top: 0;
73
+ --indicator-bottom: auto;
74
+ --indicator-ty: -50%;
75
+ --indicator-offset-y: var(--indicator-offset, 0px);
76
+ }
77
+ .indicator-middle {
78
+ --indicator-top: 50%;
79
+ --indicator-bottom: auto;
80
+ --indicator-ty: -50%;
81
+ --indicator-offset-y: 0px;
82
+ }
83
+ .indicator-bottom {
84
+ --indicator-top: auto;
85
+ --indicator-bottom: 0;
86
+ --indicator-ty: 50%;
87
+ --indicator-offset-y: calc(-1 * var(--indicator-offset, 0px));
88
+ }
89
+
90
+ /*
91
+ * Status dot — a small saturated circle for label-less presence/status.
92
+ * A `.badge` with no content is still a pill (fixed height, horizontal
93
+ * padding); a dot needs to actually be round.
94
+ */
95
+ .indicator-dot {
96
+ @apply inline-block w-2 h-2 rounded-full bg-text-muted;
97
+ }
98
+ .indicator-dot-info {
99
+ @apply bg-info;
100
+ }
101
+ .indicator-dot-success {
102
+ @apply bg-success;
103
+ }
104
+ .indicator-dot-warning {
105
+ @apply bg-warning;
106
+ }
107
+ .indicator-dot-danger {
108
+ @apply bg-danger;
109
+ }
110
+ .indicator-dot-primary {
111
+ @apply bg-primary;
112
+ }
113
+ }
@@ -0,0 +1,47 @@
1
+ @layer components {
2
+ /* A single keyboard chip — one modifier or key. Stack inside a `.kbd-group`
3
+ for multi-key chords. */
4
+ .kbd {
5
+ @apply inline-flex items-center justify-center
6
+ min-w-[1.25em] h-[1.4em] px-[0.35em]
7
+ rounded border border-border
8
+ bg-surface-strong text-text-muted
9
+ text-[0.75em] font-mono leading-none align-middle
10
+ whitespace-nowrap;
11
+ font-variant-numeric: tabular-nums;
12
+ }
13
+
14
+ /* Cluster of `.kbd` chips. Always emitted by the React `<Kbd>` component so
15
+ selectors can target the whole binding as a unit. */
16
+ .kbd-group {
17
+ @apply inline-flex items-center gap-1 align-middle;
18
+ }
19
+
20
+ /* Inside an action surface (button, menu item), the chip derives its
21
+ colour from the host so it stays legible on any variant without
22
+ fighting the surrounding chrome. */
23
+ .btn .kbd,
24
+ .menu-item .kbd {
25
+ color: currentColor;
26
+ background-color: color-mix(in srgb, currentColor 12%, transparent);
27
+ border-color: color-mix(in srgb, currentColor 22%, transparent);
28
+ }
29
+
30
+ /* Subtle dimming for the leading cluster on a button so the label keeps
31
+ visual priority. The cluster, not each chip, so a `Ctrl S` reads as
32
+ a single unit. */
33
+ .btn > .kbd-group {
34
+ opacity: 0.85;
35
+ }
36
+
37
+ /* Right-pin the binding inside menu items — matches native menu convention. */
38
+ .menu-item > .kbd-group {
39
+ margin-inline-start: auto;
40
+ }
41
+
42
+ /* Right-pin inside vertical button groups only. Standalone buttons keep the
43
+ inline-trailing layout (chip sits next to the label). */
44
+ .btn-group-vertical > .btn > .kbd-group {
45
+ margin-inline-start: auto;
46
+ }
47
+ }
@@ -59,6 +59,38 @@
59
59
  border border-border rounded-lg shadow-md;
60
60
  }
61
61
 
62
+ /* CSS anchor positioning makes the popup `position: fixed` so it escapes
63
+ ancestor `overflow: hidden`/`overflow: auto` clipping — necessary when
64
+ the menu lives inside a `<dialog>` (top-layer + overflow: hidden) or a
65
+ scroll-clipped surface like a card body. `anchor-scope` keeps each
66
+ menu's anchor lookups isolated so multiple menus on the page don't
67
+ cross-target, and `position-try-fallbacks` flips the popup above the
68
+ trigger when there isn't room below. Browsers without anchor
69
+ positioning (Firefox, as of early 2026) fall back to the absolute
70
+ rules above and clip as before. */
71
+ @supports (anchor-name: --x) {
72
+ .menu {
73
+ anchor-scope: --menu-trigger;
74
+ }
75
+ .menu-trigger {
76
+ anchor-name: --menu-trigger;
77
+ }
78
+ .menu-popup {
79
+ position: fixed;
80
+ position-anchor: --menu-trigger;
81
+ top: anchor(bottom);
82
+ left: anchor(left);
83
+ position-try-fallbacks: --menu-popup-flip-up;
84
+ }
85
+ }
86
+
87
+ @position-try --menu-popup-flip-up {
88
+ top: auto;
89
+ bottom: anchor(top);
90
+ margin-top: 0;
91
+ margin-bottom: 0.25rem;
92
+ }
93
+
62
94
  .menu-item {
63
95
  @apply flex items-center gap-2 w-full px-3 py-1.5 text-sm leading-none
64
96
  text-text bg-transparent
@@ -33,6 +33,14 @@
33
33
  min-width: 0;
34
34
  }
35
35
 
36
+ /* Compact density — tighter rows for sidebar info blocks or very many
37
+ short attributes. */
38
+ .property-list-compact .property-list-label,
39
+ .property-list-compact .property-list-value {
40
+ padding: 0.125rem 0.5rem;
41
+ min-height: 1.5rem;
42
+ }
43
+
36
44
  /* Numeric — right-align + tabular-nums on the value. */
37
45
  .property-list-value-numeric {
38
46
  justify-content: flex-end;
@@ -51,7 +59,7 @@
51
59
  }
52
60
 
53
61
  /* Copy button — always emitted by the Value but kept out of layout entirely
54
- unless copyable is active on the list or on this specific value. */
62
+ unless this specific value opts in. */
55
63
  .property-list-copy {
56
64
  @apply inline-flex items-center justify-center
57
65
  ml-auto rounded
@@ -66,7 +74,6 @@
66
74
  color 100ms ease;
67
75
  }
68
76
 
69
- .property-list-copyable .property-list-copy,
70
77
  .property-list-value-copyable .property-list-copy {
71
78
  display: inline-flex;
72
79
  opacity: 0;
@@ -75,8 +82,6 @@
75
82
 
76
83
  /* Reveal on hover of either the label or the value of a copyable row, on
77
84
  button focus, or while feedback is active. */
78
- .property-list-copyable .property-list-label:hover + .property-list-value .property-list-copy,
79
- .property-list-copyable .property-list-value:hover .property-list-copy,
80
85
  .property-list-label:has(+ .property-list-value-copyable):hover
81
86
  + .property-list-value
82
87
  .property-list-copy,
package/src/theme.css CHANGED
@@ -33,21 +33,21 @@
33
33
  --color-*: initial;
34
34
 
35
35
  /* Base */
36
- --color-paper: #fffcf0;
37
- --color-black: #100f0f;
38
- --color-base-50: #f2f0e5;
39
- --color-base-100: #e6e4d9;
40
- --color-base-150: #dad8ce;
41
- --color-base-200: #cecdc3;
42
- --color-base-300: #b7b5ac;
43
- --color-base-400: #9f9d96;
44
- --color-base-500: #878580;
45
- --color-base-600: #6f6e69;
46
- --color-base-700: #575653;
47
- --color-base-800: #403e3c;
48
- --color-base-850: #343331;
49
- --color-base-900: #282726;
50
- --color-base-950: #1c1b1a;
36
+ --color-paper: #ffffff;
37
+ --color-black: #0f0f0f;
38
+ --color-base-50: #fafafa;
39
+ --color-base-100: #f4f4f4;
40
+ --color-base-150: #e7e7e7;
41
+ --color-base-200: #d4d4d4;
42
+ --color-base-300: #b3b3b3;
43
+ --color-base-400: #9b9b9b;
44
+ --color-base-500: #848484;
45
+ --color-base-600: #6c6c6c;
46
+ --color-base-700: #555555;
47
+ --color-base-800: #3e3e3e;
48
+ --color-base-850: #333333;
49
+ --color-base-900: #272727;
50
+ --color-base-950: #1b1b1b;
51
51
 
52
52
  /* Red */
53
53
  --color-red-50: #ffe1d5;