@anyknown/ui 0.4.0 → 0.4.1

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.
@@ -3,6 +3,7 @@ import { AlertDialog } from "@base-ui/react/alert-dialog";
3
3
  import { Dialog as BaseDialog } from "@base-ui/react/dialog";
4
4
  import * as stylex from "@stylexjs/stylex";
5
5
  import { useRef } from "react";
6
+ import { layerStyles } from "../../lib/popup.js";
6
7
  import { color, font, radius, shadow, space, text } from "../../tokens.stylex.js";
7
8
  import { Button } from "../button/Button.js";
8
9
  const REDUCED = "@media (prefers-reduced-motion: reduce)";
@@ -14,14 +15,12 @@ const styles = stylex.create({
14
15
  backdrop: {
15
16
  position: "fixed",
16
17
  inset: 0,
17
- zIndex: 70,
18
18
  backgroundColor: "rgba(24, 22, 19, 0.35)",
19
19
  backdropFilter: "blur(2px)",
20
20
  },
21
21
  viewport: {
22
22
  position: "fixed",
23
23
  inset: 0,
24
- zIndex: 71,
25
24
  display: "grid",
26
25
  placeItems: "center",
27
26
  padding: space.md,
@@ -69,9 +68,9 @@ export function DialogActions({ children }) {
69
68
  return _jsx("div", { ...stylex.props(styles.actions), children: children });
70
69
  }
71
70
  export function DialogContent({ title, description, children }) {
72
- return (_jsxs(BaseDialog.Portal, { children: [_jsx(BaseDialog.Backdrop, { ...stylex.props(styles.backdrop) }), _jsx(BaseDialog.Viewport, { ...stylex.props(styles.viewport), children: _jsxs(BaseDialog.Popup, { ...stylex.props(styles.popup), children: [_jsx(BaseDialog.Title, { ...stylex.props(styles.title), children: title }), description != null && (_jsx(BaseDialog.Description, { ...stylex.props(styles.description), children: description })), children] }) })] }));
71
+ return (_jsxs(BaseDialog.Portal, { children: [_jsx(BaseDialog.Backdrop, { ...stylex.props(layerStyles.dialogBackdrop, styles.backdrop) }), _jsx(BaseDialog.Viewport, { ...stylex.props(layerStyles.dialog, styles.viewport), children: _jsxs(BaseDialog.Popup, { ...stylex.props(styles.popup), children: [_jsx(BaseDialog.Title, { ...stylex.props(styles.title), children: title }), description != null && (_jsx(BaseDialog.Description, { ...stylex.props(styles.description), children: description })), children] }) })] }));
73
72
  }
74
73
  export function ConfirmDialog({ trigger, title, description, danger = false, confirmLabel = "確認", cancelLabel = "取消", onConfirm, ...props }) {
75
74
  const cancelRef = useRef(null);
76
- return (_jsxs(AlertDialog.Root, { ...props, children: [trigger != null && _jsx(AlertDialog.Trigger, { render: trigger }), _jsxs(AlertDialog.Portal, { children: [_jsx(AlertDialog.Backdrop, { ...stylex.props(styles.backdrop) }), _jsx(AlertDialog.Viewport, { ...stylex.props(styles.viewport), children: _jsxs(AlertDialog.Popup, { initialFocus: danger ? cancelRef : undefined, ...stylex.props(styles.popup), children: [_jsx(AlertDialog.Title, { ...stylex.props(styles.title), children: title }), description != null && (_jsx(AlertDialog.Description, { ...stylex.props(styles.description), children: description })), _jsxs("div", { ...stylex.props(styles.actions), children: [_jsx(AlertDialog.Close, { render: _jsx(Button, { ref: cancelRef, variant: "ghost" }), children: cancelLabel }), _jsx(AlertDialog.Close, { render: _jsx(Button, { variant: danger ? "danger" : "primary" }), onClick: onConfirm, children: confirmLabel })] })] }) })] })] }));
75
+ return (_jsxs(AlertDialog.Root, { ...props, children: [trigger != null && _jsx(AlertDialog.Trigger, { render: trigger }), _jsxs(AlertDialog.Portal, { children: [_jsx(AlertDialog.Backdrop, { ...stylex.props(layerStyles.dialogBackdrop, styles.backdrop) }), _jsx(AlertDialog.Viewport, { ...stylex.props(layerStyles.dialog, styles.viewport), children: _jsxs(AlertDialog.Popup, { initialFocus: danger ? cancelRef : undefined, ...stylex.props(styles.popup), children: [_jsx(AlertDialog.Title, { ...stylex.props(styles.title), children: title }), description != null && (_jsx(AlertDialog.Description, { ...stylex.props(styles.description), children: description })), _jsxs("div", { ...stylex.props(styles.actions), children: [_jsx(AlertDialog.Close, { render: _jsx(Button, { ref: cancelRef, variant: "ghost" }), children: cancelLabel }), _jsx(AlertDialog.Close, { render: _jsx(Button, { variant: danger ? "danger" : "primary" }), onClick: onConfirm, children: confirmLabel })] })] }) })] })] }));
77
76
  }
@@ -5,6 +5,7 @@ import { createContext, useContext, useState } from "react";
5
5
  import { reset } from "../../lib/styled.js";
6
6
  import { usePrefersReducedMotion } from "../../lib/motion.js";
7
7
  import { UNWEAVE_PATH } from "../../lib/paths.js";
8
+ import { layerStyles } from "../../lib/popup.js";
8
9
  import { color, font, motion, radius, shadow, space, text } from "../../tokens.stylex.js";
9
10
  const REDUCED = "@media (prefers-reduced-motion: reduce)";
10
11
  const DEFAULT_TIMEOUT = 5000;
@@ -19,7 +20,6 @@ const unweave = stylex.keyframes({
19
20
  const styles = stylex.create({
20
21
  viewport: {
21
22
  position: "fixed",
22
- zIndex: 80,
23
23
  display: "flex",
24
24
  gap: space.xs,
25
25
  width: "min(20rem, calc(100vw - 2.5rem))",
@@ -161,7 +161,7 @@ export function Toaster({ position = "bottom-right", timeout = DEFAULT_TIMEOUT,
161
161
  const [api] = useState(() => makeApi(() => own));
162
162
  const [paused, setPaused] = useState(false);
163
163
  const fromBottom = position.startsWith("bottom");
164
- return (_jsx(ToastApiContext, { value: api, children: _jsx(BaseToast.Provider, { toastManager: own, timeout: timeout, limit: limit, children: _jsx(BaseToast.Portal, { children: _jsx(BaseToast.Viewport, { onMouseEnter: () => setPaused(true), onMouseLeave: () => setPaused(false), onFocus: () => setPaused(true), onBlur: () => setPaused(false), ...stylex.props(styles.viewport, fromBottom ? styles.fromBottom : styles.fromTop, POSITIONS[position]), children: _jsx(ToastList, { fallbackTimeout: timeout, paused: paused }) }) }) }) }));
164
+ return (_jsx(ToastApiContext, { value: api, children: _jsx(BaseToast.Provider, { toastManager: own, timeout: timeout, limit: limit, children: _jsx(BaseToast.Portal, { children: _jsx(BaseToast.Viewport, { onMouseEnter: () => setPaused(true), onMouseLeave: () => setPaused(false), onFocus: () => setPaused(true), onBlur: () => setPaused(false), ...stylex.props(layerStyles.toast, styles.viewport, fromBottom ? styles.fromBottom : styles.fromTop, POSITIONS[position]), children: _jsx(ToastList, { fallbackTimeout: timeout, paused: paused }) }) }) }) }));
165
165
  }
166
166
  function ToastList({ fallbackTimeout, paused }) {
167
167
  const { toasts } = BaseToast.useToastManager();
@@ -3,12 +3,12 @@ import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
3
3
  import * as stylex from "@stylexjs/stylex";
4
4
  import { useId, useState } from "react";
5
5
  import { usePrefersReducedMotion } from "../../lib/motion.js";
6
+ import { layerStyles } from "../../lib/popup.js";
6
7
  import { color, font, motion, radius, space, text } from "../../tokens.stylex.js";
7
8
  import { KbdToneContext } from "../kbd/Kbd.js";
8
9
  const REDUCED = "@media (prefers-reduced-motion: reduce)";
9
10
  const fade = stylex.keyframes({ from: { opacity: 0 }, to: { opacity: 1 } });
10
11
  const styles = stylex.create({
11
- positioner: { zIndex: 60 },
12
12
  bubble: {
13
13
  display: "inline-flex",
14
14
  alignItems: "center",
@@ -34,5 +34,5 @@ export function Tooltip({ content, shortcut, side = "top", align = "center", del
34
34
  const [open, setOpen] = useState(false);
35
35
  if (disabled)
36
36
  return children;
37
- return (_jsxs(BaseTooltip.Root, { open: open, onOpenChange: setOpen, children: [_jsx(BaseTooltip.Trigger, { delay: reduced ? 0 : delay, "aria-describedby": open ? id : undefined, render: children }), _jsx(BaseTooltip.Portal, { children: _jsx(BaseTooltip.Positioner, { side: side, align: align, sideOffset: 6, ...stylex.props(styles.positioner), children: _jsx(BaseTooltip.Popup, { id: id, role: "tooltip", ...stylex.props(styles.bubble), children: _jsxs(KbdToneContext, { value: "inverted", children: [content, shortcut] }) }) }) })] }));
37
+ return (_jsxs(BaseTooltip.Root, { open: open, onOpenChange: setOpen, children: [_jsx(BaseTooltip.Trigger, { delay: reduced ? 0 : delay, "aria-describedby": open ? id : undefined, render: children }), _jsx(BaseTooltip.Portal, { children: _jsx(BaseTooltip.Positioner, { side: side, align: align, sideOffset: 6, ...stylex.props(layerStyles.tooltip), children: _jsx(BaseTooltip.Popup, { id: id, role: "tooltip", ...stylex.props(styles.bubble), children: _jsxs(KbdToneContext, { value: "inverted", children: [content, shortcut] }) }) }) })] }));
38
38
  }
@@ -1,4 +1,39 @@
1
1
  import * as stylex from "@stylexjs/stylex";
2
+ /**
3
+ * 全站疊層表。Base UI 的浮層一律 portal 到 body,跟 dialog / toast 同在一層比 z-index,
4
+ * 各元件各寫一個數字就會出現「dialog 裡的 select 打不開」這種洞,所以值集中在這裡。
5
+ *
6
+ * 順序的理由:popup 壓過 dialog(浮層是當下互動的最上層);tooltip 壓過 popup
7
+ * (popup 裡的元素也能有 tooltip);toast 永遠最上(非阻斷通知不能被 modal 蓋掉)。
8
+ */
9
+ export declare const layer: {
10
+ readonly dialogBackdrop: 70;
11
+ readonly dialog: 71;
12
+ readonly popup: 75;
13
+ readonly tooltip: 78;
14
+ readonly toast: 80;
15
+ };
16
+ /**
17
+ * `layer` 的 stylex 版。跨檔案 import 的值在 `stylex.create()` 裡不能靜態求值,
18
+ * 所以疊層要以「做好的樣式」而不是數字提供給其他元件。
19
+ */
20
+ export declare const layerStyles: Readonly<{
21
+ readonly dialogBackdrop: Readonly<{
22
+ readonly zIndex: stylex.StyleXClassNameFor<"zIndex", 70>;
23
+ }>;
24
+ readonly dialog: Readonly<{
25
+ readonly zIndex: stylex.StyleXClassNameFor<"zIndex", 71>;
26
+ }>;
27
+ readonly popup: Readonly<{
28
+ readonly zIndex: stylex.StyleXClassNameFor<"zIndex", 75>;
29
+ }>;
30
+ readonly tooltip: Readonly<{
31
+ readonly zIndex: stylex.StyleXClassNameFor<"zIndex", 78>;
32
+ }>;
33
+ readonly toast: Readonly<{
34
+ readonly zIndex: stylex.StyleXClassNameFor<"zIndex", 80>;
35
+ }>;
36
+ }>;
2
37
  export declare const growIn: string;
3
38
  export declare const popupStyles: Readonly<{
4
39
  readonly surface: Readonly<{
@@ -23,7 +58,7 @@ export declare const popupStyles: Readonly<{
23
58
  readonly maxHeight: stylex.StyleXClassNameFor<"maxHeight", "var(--available-height)">;
24
59
  }>;
25
60
  readonly positioner: Readonly<{
26
- readonly zIndex: stylex.StyleXClassNameFor<"zIndex", 40>;
61
+ readonly zIndex: stylex.StyleXClassNameFor<"zIndex", 75>;
27
62
  readonly outline: stylex.StyleXClassNameFor<"outline", "none">;
28
63
  }>;
29
64
  }>;
package/dist/lib/popup.js CHANGED
@@ -1,6 +1,31 @@
1
1
  import * as stylex from "@stylexjs/stylex";
2
2
  import { color, radius, shadow } from "../tokens.stylex.js";
3
3
  const REDUCED = "@media (prefers-reduced-motion: reduce)";
4
+ /**
5
+ * 全站疊層表。Base UI 的浮層一律 portal 到 body,跟 dialog / toast 同在一層比 z-index,
6
+ * 各元件各寫一個數字就會出現「dialog 裡的 select 打不開」這種洞,所以值集中在這裡。
7
+ *
8
+ * 順序的理由:popup 壓過 dialog(浮層是當下互動的最上層);tooltip 壓過 popup
9
+ * (popup 裡的元素也能有 tooltip);toast 永遠最上(非阻斷通知不能被 modal 蓋掉)。
10
+ */
11
+ export const layer = {
12
+ dialogBackdrop: 70,
13
+ dialog: 71,
14
+ popup: 75,
15
+ tooltip: 78,
16
+ toast: 80,
17
+ };
18
+ /**
19
+ * `layer` 的 stylex 版。跨檔案 import 的值在 `stylex.create()` 裡不能靜態求值,
20
+ * 所以疊層要以「做好的樣式」而不是數字提供給其他元件。
21
+ */
22
+ export const layerStyles = stylex.create({
23
+ dialogBackdrop: { zIndex: layer.dialogBackdrop },
24
+ dialog: { zIndex: layer.dialog },
25
+ popup: { zIndex: layer.popup },
26
+ tooltip: { zIndex: layer.tooltip },
27
+ toast: { zIndex: layer.toast },
28
+ });
4
29
  export const growIn = stylex.keyframes({
5
30
  from: { opacity: 0, scale: "1 0.97" },
6
31
  to: { opacity: 1, scale: "1 1" },
@@ -23,5 +48,5 @@ export const popupStyles = stylex.create({
23
48
  },
24
49
  anchorWidth: { width: "var(--anchor-width)" },
25
50
  availableHeight: { maxHeight: "var(--available-height)" },
26
- positioner: { zIndex: 40, outline: "none" },
51
+ positioner: { zIndex: layer.popup, outline: "none" },
27
52
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anyknown/ui",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "AnyKnown design system — StyleX tokens, themes, and 34 components",
5
5
  "homepage": "https://ui.anyknown.com",
6
6
  "bugs": {