@boyernick/standard-ui-react 0.1.1-canary.12 → 0.1.1-canary.13
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 +1 -1
- package/src/toast.tsx +34 -14
- package/src/tooltip.tsx +10 -3
package/package.json
CHANGED
package/src/toast.tsx
CHANGED
|
@@ -28,25 +28,45 @@ export const ToastPortal = (props: ToastPortalProps) => (
|
|
|
28
28
|
|
|
29
29
|
export const ToastViewport = ({ className, ...props }: ToastViewportProps) => (
|
|
30
30
|
<BaseToast.Viewport
|
|
31
|
+
// No flex column: the toasts inside are absolutely positioned so they pile
|
|
32
|
+
// up as a stack. In flow they would march down past the bottom edge.
|
|
31
33
|
className={cn(
|
|
32
|
-
"fixed right-4 bottom-4 z-[100]
|
|
34
|
+
"fixed right-4 bottom-4 z-[100] w-[min(100vw-2rem,24rem)] outline-none",
|
|
33
35
|
className,
|
|
34
36
|
)}
|
|
35
37
|
{...props}
|
|
36
38
|
/>
|
|
37
39
|
)
|
|
38
40
|
|
|
41
|
+
/** Each toast is pinned to the bottom of the viewport and lifted by its own
|
|
42
|
+
* index, so the stack reads as a pile of cards rather than a list: the one
|
|
43
|
+
* behind peeks out by `--peek` and sits a step smaller. Hovering the viewport
|
|
44
|
+
* sets `data-expanded`, which fans them out to their real heights. */
|
|
39
45
|
export const ToastRoot = ({ className, ...props }: ToastRootProps) => (
|
|
40
46
|
<BaseToast.Root
|
|
41
47
|
className={cn(
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
"absolute right-0 bottom-0 left-auto z-[calc(1000-var(--toast-index))] box-border w-full origin-bottom",
|
|
49
|
+
"[--gap:0.625rem] [--peek:0.75rem]",
|
|
50
|
+
"[--scale:calc(max(0,1-(var(--toast-index)*0.05)))] [--shrink:calc(1-var(--scale))]",
|
|
51
|
+
"[--height:var(--toast-frontmost-height,var(--toast-height))]",
|
|
52
|
+
"[--offset-y:calc(var(--toast-offset-y)*-1+calc(var(--toast-index)*var(--gap)*-1)+var(--toast-swipe-movement-y,0px))]",
|
|
53
|
+
// No border: `shadow-lg` composes `--elevation-hairline`, the same edge the
|
|
54
|
+
// dropdowns carry — theme-aware and 0.5px on hi-dpi. A border on top of it
|
|
55
|
+
// stacked a second, darker line. The error type tints that edge with a
|
|
56
|
+
// ring, which also sits outside the box model so the height never shifts.
|
|
57
|
+
"rounded-xl bg-surface px-3.5 py-3 shadow-lg outline-none select-none",
|
|
58
|
+
// Collapsed, every toast behind the front one is scaled down and shifted
|
|
59
|
+
// up; `--shrink` cancels the gap that scaling opens at the bottom edge.
|
|
60
|
+
"h-[var(--height)] data-expanded:h-[var(--toast-height)]",
|
|
61
|
+
"[transform:translateX(var(--toast-swipe-movement-x,0px))_translateY(calc(var(--toast-swipe-movement-y,0px)-(var(--toast-index)*var(--peek))-(var(--shrink)*var(--height))))_scale(var(--scale))]",
|
|
62
|
+
"data-expanded:[transform:translateX(var(--toast-swipe-movement-x,0px))_translateY(var(--offset-y))]",
|
|
63
|
+
// Bridges the gap between cards so crossing it does not collapse the fan.
|
|
64
|
+
"after:absolute after:top-full after:left-0 after:h-[calc(var(--gap)+1px)] after:w-full after:content-['']",
|
|
65
|
+
"transition-[transform,opacity,height] duration-[var(--duration-md)] ease-enter motion-reduce:transition-none",
|
|
66
|
+
"data-starting-style:[transform:translateY(150%)]",
|
|
67
|
+
"data-ending-style:opacity-0 data-limited:opacity-0",
|
|
68
|
+
"[&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[transform:translateY(150%)]",
|
|
69
|
+
"data-[type=error]:ring-1 data-[type=error]:ring-destructive/40",
|
|
50
70
|
className,
|
|
51
71
|
)}
|
|
52
72
|
{...props}
|
|
@@ -56,7 +76,7 @@ export const ToastRoot = ({ className, ...props }: ToastRootProps) => (
|
|
|
56
76
|
export const ToastContent = ({ className, ...props }: ToastContentProps) => (
|
|
57
77
|
<BaseToast.Content
|
|
58
78
|
className={cn(
|
|
59
|
-
"flex flex-col gap-
|
|
79
|
+
"flex flex-col gap-0.5 overflow-hidden transition-opacity duration-[var(--duration-sm)]",
|
|
60
80
|
"data-behind:pointer-events-none data-behind:opacity-0 data-expanded:data-behind:opacity-100",
|
|
61
81
|
className,
|
|
62
82
|
)}
|
|
@@ -66,7 +86,7 @@ export const ToastContent = ({ className, ...props }: ToastContentProps) => (
|
|
|
66
86
|
|
|
67
87
|
export const ToastTitle = ({ className, ...props }: ToastTitleProps) => (
|
|
68
88
|
<BaseToast.Title
|
|
69
|
-
className={cn("text-
|
|
89
|
+
className={cn("text-xs-strong pr-10 text-fg-primary", className)}
|
|
70
90
|
{...props}
|
|
71
91
|
/>
|
|
72
92
|
)
|
|
@@ -76,7 +96,7 @@ export const ToastDescription = ({
|
|
|
76
96
|
...props
|
|
77
97
|
}: ToastDescriptionProps) => (
|
|
78
98
|
<BaseToast.Description
|
|
79
|
-
className={cn("text-
|
|
99
|
+
className={cn("text-xs text-fg-secondary", className)}
|
|
80
100
|
{...props}
|
|
81
101
|
/>
|
|
82
102
|
)
|
|
@@ -100,7 +120,7 @@ export const ToastClose = ({
|
|
|
100
120
|
}: ToastCloseProps) => (
|
|
101
121
|
<BaseToast.Close
|
|
102
122
|
className={cn(
|
|
103
|
-
"absolute top-
|
|
123
|
+
"absolute top-2.5 right-2.5 inline-flex size-7 cursor-pointer items-center justify-center rounded-md text-fg-tertiary outline-none",
|
|
104
124
|
motion.colors,
|
|
105
125
|
"hover:bg-background-tertiary hover:text-fg-primary outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20",
|
|
106
126
|
className,
|
|
@@ -108,7 +128,7 @@ export const ToastClose = ({
|
|
|
108
128
|
{...props}
|
|
109
129
|
>
|
|
110
130
|
{children ?? (
|
|
111
|
-
<IconCrossSmall size={
|
|
131
|
+
<IconCrossSmall size={18} className="size-4.5" aria-hidden />
|
|
112
132
|
)}
|
|
113
133
|
</BaseToast.Close>
|
|
114
134
|
)
|
package/src/tooltip.tsx
CHANGED
|
@@ -52,9 +52,16 @@ const tooltipPopupVariants = cva(
|
|
|
52
52
|
cn(
|
|
53
53
|
"z-50 max-w-xs rounded-md px-2.5 py-1 text-xs shadow-md outline-none",
|
|
54
54
|
// A trailing keycap already carries its own inset, so the full 10px beside
|
|
55
|
-
// it reads as a gap rather than padding
|
|
56
|
-
//
|
|
57
|
-
|
|
55
|
+
// it reads as a gap rather than padding — but sitting flush on the vertical
|
|
56
|
+
// inset crowds the corner, so it gets a touch more than that.
|
|
57
|
+
//
|
|
58
|
+
// Laying the row out as flex is what centres it. On a text line the keycap
|
|
59
|
+
// is an inline-flex aligned `middle`, which sets its centre against the
|
|
60
|
+
// baseline plus half an x-height rather than the line's centre — at 16px it
|
|
61
|
+
// hung 1.18px low, leaving 6.36px above and 4px below. Scoped to `has-[kbd]`
|
|
62
|
+
// because making every popup a flex container would turn a multi-child
|
|
63
|
+
// tooltip from stacked blocks into a row.
|
|
64
|
+
"has-[kbd]:flex has-[kbd]:items-center has-[kbd]:pr-1.5",
|
|
58
65
|
),
|
|
59
66
|
{
|
|
60
67
|
variants: {
|