@boyernick/standard-ui-react 0.1.1-canary.13 → 0.1.1-canary.14

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/dialog.tsx +33 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boyernick/standard-ui-react",
3
- "version": "0.1.1-canary.13",
3
+ "version": "0.1.1-canary.14",
4
4
  "description": "React components for StandardUI",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/dialog.tsx CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { Dialog as BaseDialog } from "@base-ui/react/dialog"
4
4
  import type { ComponentProps, HTMLAttributes } from "react"
5
+ import { useRef } from "react"
5
6
  import { cn } from "./lib/cn"
6
7
  import { motion } from "./lib/motion"
7
8
 
@@ -41,16 +42,38 @@ export const DialogBackdrop = ({
41
42
  />
42
43
  )
43
44
 
44
- export const DialogPopup = ({ className, ...props }: DialogPopupProps) => (
45
- <BaseDialog.Popup
46
- className={cn(
47
- "fixed top-1/2 left-1/2 z-50 flex w-full max-w-md -translate-x-1/2 -translate-y-1/2 flex-col gap-6 rounded-xl border border-border-primary bg-surface-raised p-5 shadow-md outline-none max-h-[calc(100dvh-2rem)] overflow-y-auto max-sm:max-w-[calc(100vw-2rem)]",
48
- motion.popupCenter,
49
- className,
50
- )}
51
- {...props}
52
- />
53
- )
45
+ export const DialogPopup = ({
46
+ className,
47
+ initialFocus,
48
+ ref,
49
+ ...props
50
+ }: DialogPopupProps) => {
51
+ const popupRef = useRef<HTMLDivElement | null>(null)
52
+
53
+ const setRef = (node: HTMLDivElement | null) => {
54
+ popupRef.current = node
55
+ if (typeof ref === "function") ref(node)
56
+ else if (ref) ref.current = node
57
+ }
58
+
59
+ return (
60
+ <BaseDialog.Popup
61
+ ref={setRef}
62
+ // Base UI focuses the first tabbable element by default. In a dialog long
63
+ // enough to scroll that is usually the action at the bottom, and focusing
64
+ // it scrolls the body to the end before the reader has seen the start —
65
+ // so the popup takes focus itself, which is what its `tabindex="-1"` is
66
+ // for. Callers can still name their own target.
67
+ initialFocus={initialFocus ?? popupRef}
68
+ className={cn(
69
+ "fixed top-1/2 left-1/2 z-50 flex w-full max-w-md -translate-x-1/2 -translate-y-1/2 flex-col gap-6 rounded-xl border border-border-primary bg-surface-raised p-5 shadow-md outline-none max-h-[calc(100dvh-2rem)] overflow-y-auto max-sm:max-w-[calc(100vw-2rem)]",
70
+ motion.popupCenter,
71
+ className,
72
+ )}
73
+ {...props}
74
+ />
75
+ )
76
+ }
54
77
 
55
78
  export const DialogTitle = ({ className, ...props }: DialogTitleProps) => (
56
79
  <BaseDialog.Title