@aortl/admin-react 0.18.5 → 0.19.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/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.19.0] - 2026-07-02
8
+
9
+ ### Added
10
+
11
+ - `ToggleButton` — a two-state button styled like `Button` (same variants, sizes, icons, `hotkey`), wrapping Base UI Toggle. CSS-side there is no new class: any `.btn` with an `aria-pressed` attribute renders a leading mini-switch indicator, and `aria-pressed="true"` slides it on and adds a selected wash — so vanilla toggles and `.btn-group` composition work out of the box. (both)
12
+
13
+ ### Fixed
14
+
15
+ - Dialog body no longer clips its content in Safari. `.dialog-body` (and the form-dialog wrapper) used `flex: 1 1 0%`; Safari collapses a `flex-basis: 0` item that is itself an `overflow` scroll container to ~0 content height, so even short bodies were cut off behind a scrollbar. Switched to `flex: 1 1 auto` — content still shrinks and scrolls when tall. (css)
16
+
7
17
  ## [0.18.5] - 2026-06-30
8
18
 
9
19
  ### Fixed
@@ -111,12 +121,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
111
121
  - Make `primary` a high-contrast neutral and move blue to `info`. (both)
112
122
  - Use solid color fills for `Alert` and `Badge` status variants. (both)
113
123
 
114
- [Unreleased]: https://github.com/Digital-Udvikling/admin-design-system/compare/v0.18.5...HEAD
124
+ [Unreleased]: https://github.com/Digital-Udvikling/admin-design-system/compare/v0.19.0...HEAD
115
125
  [0.16.1]: https://github.com/Digital-Udvikling/admin-design-system/compare/v0.16.0...v0.16.1
116
126
  [0.16.0]: https://github.com/Digital-Udvikling/admin-design-system/compare/v0.15.1...v0.16.0
117
127
  [0.15.1]: https://github.com/Digital-Udvikling/admin-design-system/compare/v0.15.0...v0.15.1
118
128
  [0.15.0]: https://github.com/Digital-Udvikling/admin-design-system/releases/tag/v0.15.0
119
129
 
130
+ [0.19.0]: https://github.com/Digital-Udvikling/admin-design-system/compare/v0.18.5...v0.19.0
120
131
  [0.18.5]: https://github.com/Digital-Udvikling/admin-design-system/compare/v0.18.4...v0.18.5
121
132
  [0.18.4]: https://github.com/Digital-Udvikling/admin-design-system/compare/v0.18.3...v0.18.4
122
133
  [0.18.3]: https://github.com/Digital-Udvikling/admin-design-system/compare/v0.18.2...v0.18.3
@@ -1 +1 @@
1
- {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../src/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAEjE,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAInD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AACjF,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE5C,MAAM,WAAW,WAAY,SAAQ,cAAc,CAAC,OAAO,UAAU,CAAC;IACpE,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;uEACmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wEAAwE;IACxE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,uFAAuF;IACvF,YAAY,CAAC,EAAE,QAAQ,CAAC;IACxB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,wBAAgB,MAAM,CAAC,EACrB,OAAmB,EACnB,IAAW,EACX,SAAS,EACT,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,SAAS,EACT,IAAe,EACf,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,GAAG,EACH,GAAG,IAAI,EACR,EAAE,WAAW,2CA8Cb"}
1
+ {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../src/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAInD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AACjF,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE5C,MAAM,WAAW,WAAY,SAAQ,cAAc,CAAC,OAAO,UAAU,CAAC;IACpE,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;uEACmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wEAAwE;IACxE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,uFAAuF;IACvF,YAAY,CAAC,EAAE,QAAQ,CAAC;IACxB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,wBAAgB,MAAM,CAAC,EACrB,OAAmB,EACnB,IAAW,EACX,SAAS,EACT,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,SAAS,EACT,IAAe,EACf,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,GAAG,EACH,GAAG,IAAI,EACR,EAAE,WAAW,2CAkCb"}
@@ -0,0 +1,25 @@
1
+ import { Toggle as BaseToggle } from '@base-ui/react/toggle';
2
+ import { ComponentProps } from 'react';
3
+ import { ButtonSize, ButtonVariant } from './Button';
4
+ import { IconProp } from './icon';
5
+ export interface ToggleButtonProps extends ComponentProps<typeof BaseToggle> {
6
+ variant?: ButtonVariant;
7
+ size?: ButtonSize;
8
+ fullWidth?: boolean;
9
+ /** Leading icon. Pass a component (`icon={IconStar}`) or an element. */
10
+ icon?: IconProp;
11
+ /** Trailing icon. Pass a component (`iconTrailing={IconChevronDown}`) or an element. */
12
+ iconTrailing?: IconProp;
13
+ /**
14
+ * Keyboard shortcut that dispatches a native click on the button, flipping
15
+ * the pressed state. Same syntax as `useHotkey`. Pass an array for
16
+ * alternatives — only the first is rendered as a visual chip.
17
+ */
18
+ hotkey?: string | readonly string[];
19
+ }
20
+ /**
21
+ * A two-state button styled like `Button`; `aria-pressed` carries the state,
22
+ * which CSS renders as a leading mini switch. Composes with `ButtonGroup`.
23
+ */
24
+ export declare function ToggleButton({ variant, size, fullWidth, icon, iconTrailing, hotkey, className, disabled, children, ref, ...rest }: ToggleButtonProps): import("react/jsx-runtime").JSX.Element;
25
+ //# sourceMappingURL=ToggleButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToggleButton.d.ts","sourceRoot":"","sources":["../src/ToggleButton.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE1D,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAInD,MAAM,WAAW,iBAAkB,SAAQ,cAAc,CAAC,OAAO,UAAU,CAAC;IAC1E,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wEAAwE;IACxE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,wFAAwF;IACxF,YAAY,CAAC,EAAE,QAAQ,CAAC;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAC3B,OAAmB,EACnB,IAAW,EACX,SAAS,EACT,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,GAAG,EACH,GAAG,IAAI,EACR,EAAE,iBAAiB,2CA2BnB"}
@@ -1874,6 +1874,29 @@
1874
1874
  opacity: 90%;
1875
1875
  }
1876
1876
  }
1877
+ :scope._ao-btn:is([aria-pressed="true"], [data-pressed]), :scope ._ao-btn:is([aria-pressed="true"], [data-pressed]) {
1878
+ background-color: var(--color-primary-muted);
1879
+ color: var(--color-primary);
1880
+ }
1881
+ :scope._ao-btn:is([aria-pressed], [data-pressed])::before, :scope ._ao-btn:is([aria-pressed], [data-pressed])::before {
1882
+ --btn-toggle-thumb: var(--color-paper);
1883
+ content: "";
1884
+ flex-shrink: 0;
1885
+ inline-size: 1.75em;
1886
+ block-size: 1em;
1887
+ border-radius: 9999px;
1888
+ background-color: var(--color-border-strong);
1889
+ background-image: radial-gradient( circle closest-side, var(--btn-toggle-thumb) calc(100% - 0.5px), transparent );
1890
+ background-size: calc(1em - 4px) calc(1em - 4px);
1891
+ background-position: 2px 50%;
1892
+ background-repeat: no-repeat;
1893
+ transition: background-color 150ms, background-position 150ms;
1894
+ }
1895
+ :scope._ao-btn:is([aria-pressed="true"], [data-pressed])::before, :scope ._ao-btn:is([aria-pressed="true"], [data-pressed])::before {
1896
+ --btn-toggle-thumb: var(--color-primary-content);
1897
+ background-color: var(--color-primary);
1898
+ background-position: calc(100% - 2px) 50%;
1899
+ }
1877
1900
  :scope._ao-btn-sm, :scope ._ao-btn-sm {
1878
1901
  gap: calc(var(--spacing) * 1.5);
1879
1902
  padding-inline: calc(var(--spacing) * 3);
@@ -1930,6 +1953,9 @@
1930
1953
  :scope._ao-btn-loading::before, :scope ._ao-btn-loading::before {
1931
1954
  animation-duration: 2s;
1932
1955
  }
1956
+ :scope._ao-btn:is([aria-pressed], [data-pressed])::before, :scope ._ao-btn:is([aria-pressed], [data-pressed])::before {
1957
+ transition: none;
1958
+ }
1933
1959
  }
1934
1960
  :scope._ao-btn-group, :scope ._ao-btn-group {
1935
1961
  display: inline-flex;
@@ -3635,7 +3661,7 @@
3635
3661
  :scope._ao-dialog-body, :scope ._ao-dialog-body {
3636
3662
  display: flex;
3637
3663
  min-height: calc(var(--spacing) * 0);
3638
- flex: 1;
3664
+ flex: auto;
3639
3665
  flex-direction: column;
3640
3666
  gap: calc(var(--spacing) * 3);
3641
3667
  overflow-y: auto;
@@ -3645,7 +3671,7 @@
3645
3671
  :scope._ao-dialog > form, :scope ._ao-dialog > form {
3646
3672
  display: flex;
3647
3673
  min-height: calc(var(--spacing) * 0);
3648
- flex: 1;
3674
+ flex: auto;
3649
3675
  flex-direction: column;
3650
3676
  }
3651
3677
  :scope._ao-dialog-footer, :scope ._ao-dialog-footer {
package/dist/index.cjs CHANGED
@@ -4,6 +4,7 @@ let react_jsx_runtime = require("react/jsx-runtime");
4
4
  let react = require("react");
5
5
  let _base_ui_react_avatar = require("@base-ui/react/avatar");
6
6
  let _base_ui_react_button = require("@base-ui/react/button");
7
+ let _base_ui_react_toggle = require("@base-ui/react/toggle");
7
8
  let _base_ui_react_input = require("@base-ui/react/input");
8
9
  let _base_ui_react_number_field = require("@base-ui/react/number-field");
9
10
  let _base_ui_react_field = require("@base-ui/react/field");
@@ -568,16 +569,28 @@ function useHotkey(keys, handler, options) {
568
569
  }, [derived, enabled]);
569
570
  return derived;
570
571
  }
571
- //#endregion
572
- //#region src/Button.tsx
573
- function Button({ variant = "default", size = "md", fullWidth, loading, icon, iconTrailing, hotkey, className, type = "button", disabled, children, onClick, ref, ...rest }) {
572
+ /**
573
+ * `useHotkey` bound to a rendered element: the chord dispatches a native
574
+ * `.click()`, so `onClick` fires, `type="submit"` submits, an anchor
575
+ * navigates. Returns `setRef` to pass as the element's ref; it latches the
576
+ * element and forwards `ref`.
577
+ */
578
+ function useHotkeyClick(keys, ref, options) {
574
579
  const elementRef = (0, react.useRef)(null);
575
580
  const setRef = (0, react.useCallback)((node) => {
576
581
  elementRef.current = node;
577
582
  if (typeof ref === "function") ref(node);
578
583
  else if (ref) ref.current = node;
579
584
  }, [ref]);
580
- const { ariaKeyShortcuts, primaryChord } = useHotkey(hotkey, () => elementRef.current?.click(), { enabled: !disabled && !loading });
585
+ return {
586
+ ...useHotkey(keys, () => elementRef.current?.click(), options),
587
+ setRef
588
+ };
589
+ }
590
+ //#endregion
591
+ //#region src/Button.tsx
592
+ function Button({ variant = "default", size = "md", fullWidth, loading, icon, iconTrailing, hotkey, className, type = "button", disabled, children, onClick, ref, ...rest }) {
593
+ const { ariaKeyShortcuts, primaryChord, setRef } = useHotkeyClick(hotkey, ref, { enabled: !disabled && !loading });
581
594
  const iconOnly = children == null && (icon != null || iconTrailing != null);
582
595
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_base_ui_react_button.Button, {
583
596
  ref: setRef,
@@ -617,6 +630,33 @@ function ButtonGroup({ orientation = "horizontal", fullWidth = false, role = "gr
617
630
  });
618
631
  }
619
632
  //#endregion
633
+ //#region src/ToggleButton.tsx
634
+ /**
635
+ * A two-state button styled like `Button`; `aria-pressed` carries the state,
636
+ * which CSS renders as a leading mini switch. Composes with `ButtonGroup`.
637
+ */
638
+ function ToggleButton({ variant = "default", size = "md", fullWidth, icon, iconTrailing, hotkey, className, disabled, children, ref, ...rest }) {
639
+ const { ariaKeyShortcuts, primaryChord, setRef } = useHotkeyClick(hotkey, ref, { enabled: !disabled });
640
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_base_ui_react_toggle.Toggle, {
641
+ ref: setRef,
642
+ disabled,
643
+ "aria-keyshortcuts": ariaKeyShortcuts,
644
+ className: cn([
645
+ "btn",
646
+ variant !== "default" && `btn-${variant}`,
647
+ size !== "md" && `btn-${size}`,
648
+ fullWidth && "btn-full-width"
649
+ ], className),
650
+ ...rest,
651
+ children: [
652
+ renderIcon(icon),
653
+ children,
654
+ renderIcon(iconTrailing),
655
+ primaryChord !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Kbd, { keys: primaryChord }) : null
656
+ ]
657
+ });
658
+ }
659
+ //#endregion
620
660
  //#region src/Breadcrumbs.tsx
621
661
  function BreadcrumbsRoot({ separator, className, children, "aria-label": ariaLabel = "Breadcrumb", ...rest }) {
622
662
  const items = react.Children.toArray(children).filter(react.isValidElement);
@@ -2895,6 +2935,7 @@ exports.Table = Table;
2895
2935
  exports.Tabs = Tabs;
2896
2936
  exports.Textarea = Textarea;
2897
2937
  exports.Timeline = Timeline;
2938
+ exports.ToggleButton = ToggleButton;
2898
2939
  exports.Tooltip = Tooltip;
2899
2940
  exports.getPaginationItems = getPaginationItems;
2900
2941
  exports.useAppShell = useAppShell;