@you-agent-factory/components 0.0.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/README.md +223 -0
- package/docs/README.md +83 -0
- package/docs/button.md +119 -0
- package/docs/charts.md +325 -0
- package/docs/data-display-code-panel.md +120 -0
- package/docs/feedback-alert-panel.md +117 -0
- package/docs/feedback-skeleton.md +54 -0
- package/docs/forms-form-field.md +490 -0
- package/docs/forms-input-primitives.md +311 -0
- package/docs/forms-select-primitives.md +362 -0
- package/docs/graphs.md +250 -0
- package/docs/layout-display-primitives.md +211 -0
- package/docs/overlays.md +414 -0
- package/docs/table-data-table.md +331 -0
- package/docs/typography-roles.md +182 -0
- package/docs/widget-frame-recipes.md +273 -0
- package/package.json +161 -0
- package/src/category-paths.ts +20 -0
- package/src/charts/chart-state-panel.tsx +103 -0
- package/src/charts/chart.tsx +287 -0
- package/src/charts/index.ts +21 -0
- package/src/data-display/code-panel.tsx +67 -0
- package/src/data-display/data-table.tsx +180 -0
- package/src/data-display/description-list.tsx +24 -0
- package/src/data-display/index.ts +34 -0
- package/src/data-display/table-layout.ts +12 -0
- package/src/data-display/table.tsx +131 -0
- package/src/feedback/alert-panel-semantics.ts +75 -0
- package/src/feedback/alert-panel.tsx +187 -0
- package/src/feedback/index.ts +21 -0
- package/src/feedback/skeleton.tsx +16 -0
- package/src/forms/index.ts +73 -0
- package/src/forms/package-checkbox.tsx +50 -0
- package/src/forms/package-enum-select.tsx +185 -0
- package/src/forms/package-file-input.tsx +25 -0
- package/src/forms/package-form-field.tsx +202 -0
- package/src/forms/package-input.tsx +25 -0
- package/src/forms/package-native-select.tsx +25 -0
- package/src/forms/package-select.tsx +209 -0
- package/src/forms/package-textarea.tsx +35 -0
- package/src/forms/select-icons.tsx +35 -0
- package/src/graphs/graph-edge-path.ts +241 -0
- package/src/graphs/graph-edge.tsx +130 -0
- package/src/graphs/graph-interactive-example.tsx +187 -0
- package/src/graphs/graph-node-button.tsx +51 -0
- package/src/graphs/graph-node-handle-badge.tsx +108 -0
- package/src/graphs/graph-node-handle.ts +28 -0
- package/src/graphs/graph-node-shell.tsx +111 -0
- package/src/graphs/graph-node-state-indicator.tsx +47 -0
- package/src/graphs/graph-node-state.ts +111 -0
- package/src/graphs/graph-viewport-surface.tsx +27 -0
- package/src/graphs/index.ts +41 -0
- package/src/icons/index.ts +4 -0
- package/src/index.ts +209 -0
- package/src/layout/action-row.tsx +53 -0
- package/src/layout/index.ts +9 -0
- package/src/layout/surface-panel.tsx +91 -0
- package/src/navigation/index.ts +4 -0
- package/src/overlays/collapsible.tsx +22 -0
- package/src/overlays/dialog.tsx +148 -0
- package/src/overlays/index.ts +31 -0
- package/src/overlays/overlay-layout.ts +9 -0
- package/src/overlays/popover.tsx +29 -0
- package/src/overlays/scroll-area.tsx +78 -0
- package/src/primitives/button-link.tsx +22 -0
- package/src/primitives/button.tsx +258 -0
- package/src/primitives/icon-button-shell.tsx +49 -0
- package/src/primitives/index.ts +31 -0
- package/src/primitives/package-text.tsx +29 -0
- package/src/primitives/typography-roles.ts +12 -0
- package/src/primitives/typography.tsx +165 -0
- package/src/recipes/index.ts +61 -0
- package/src/recipes/widget-frame-content.tsx +114 -0
- package/src/recipes/widget-frame-disclosure.tsx +161 -0
- package/src/recipes/widget-frame-layout.ts +40 -0
- package/src/recipes/widget-frame-skeleton.tsx +16 -0
- package/src/recipes/widget-frame-states.tsx +99 -0
- package/src/recipes/widget-frame-typography.ts +19 -0
- package/src/recipes/widget-frame.tsx +84 -0
- package/src/styles/color-palette-presets.css +167 -0
- package/src/styles/color-role-tokens.css +163 -0
- package/src/styles/layout-role-tokens.css +27 -0
- package/src/styles/text-color-role-tokens.css +29 -0
- package/src/styles/typography-role-tokens.css +72 -0
- package/src/styles/typography-role-utilities.css +73 -0
- package/src/styles/typography-roles.css +53 -0
- package/src/styles.css +32 -0
- package/src/testing/index.ts +13 -0
- package/src/testing/render.tsx +16 -0
- package/src/tokens/index.ts +4 -0
- package/src/utilities/cn.ts +5 -0
- package/src/utilities/index.ts +6 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../utilities/cn";
|
|
4
|
+
|
|
5
|
+
const ACTION_ROW_CLASS =
|
|
6
|
+
"flex min-w-0 flex-wrap items-center gap-2 max-md:justify-start";
|
|
7
|
+
const ACTION_ROW_SECTION_CLASS =
|
|
8
|
+
"flex min-w-0 flex-wrap items-center gap-2";
|
|
9
|
+
|
|
10
|
+
export interface ActionRowProps
|
|
11
|
+
extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
|
|
12
|
+
actions?: ReactNode;
|
|
13
|
+
actionsClassName?: string;
|
|
14
|
+
statuses?: ReactNode;
|
|
15
|
+
statusesClassName?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function ActionRow({
|
|
19
|
+
actions,
|
|
20
|
+
actionsClassName,
|
|
21
|
+
className,
|
|
22
|
+
statuses,
|
|
23
|
+
statusesClassName,
|
|
24
|
+
...props
|
|
25
|
+
}: ActionRowProps) {
|
|
26
|
+
const hasStatuses = statuses !== undefined && statuses !== null;
|
|
27
|
+
const hasActions = actions !== undefined && actions !== null;
|
|
28
|
+
|
|
29
|
+
if (!hasStatuses && !hasActions) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<div className={cn(ACTION_ROW_CLASS, className)} {...props}>
|
|
35
|
+
{hasStatuses ? (
|
|
36
|
+
<div
|
|
37
|
+
className={cn(ACTION_ROW_SECTION_CLASS, statusesClassName)}
|
|
38
|
+
data-action-row-section="statuses"
|
|
39
|
+
>
|
|
40
|
+
{statuses}
|
|
41
|
+
</div>
|
|
42
|
+
) : null}
|
|
43
|
+
{hasActions ? (
|
|
44
|
+
<div
|
|
45
|
+
className={cn(ACTION_ROW_SECTION_CLASS, actionsClassName)}
|
|
46
|
+
data-action-row-section="actions"
|
|
47
|
+
>
|
|
48
|
+
{actions}
|
|
49
|
+
</div>
|
|
50
|
+
) : null}
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Stable category path for `@you-agent-factory/components/layout`. */
|
|
2
|
+
export const COMPONENTS_CATEGORY = "layout" as const;
|
|
3
|
+
|
|
4
|
+
export type ComponentsCategory = typeof COMPONENTS_CATEGORY;
|
|
5
|
+
|
|
6
|
+
export { ActionRow } from "./action-row";
|
|
7
|
+
export type { ActionRowProps } from "./action-row";
|
|
8
|
+
export { SurfacePanel, surfacePanelVariants } from "./surface-panel";
|
|
9
|
+
export type { SurfacePanelProps } from "./surface-panel";
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
2
|
+
import { forwardRef, type HTMLAttributes } from "react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../utilities/cn";
|
|
5
|
+
|
|
6
|
+
type SurfacePanelPadding = "compact" | "default" | "none";
|
|
7
|
+
type SurfacePanelRadius = "lg" | "xl" | "2xl" | "3xl" | "full";
|
|
8
|
+
type SurfacePanelSurface = "high" | "low";
|
|
9
|
+
type SurfacePanelTone = "default" | "accent" | "selected";
|
|
10
|
+
|
|
11
|
+
export interface SurfacePanelProps extends HTMLAttributes<HTMLDivElement> {
|
|
12
|
+
asChild?: boolean;
|
|
13
|
+
padding?: SurfacePanelPadding;
|
|
14
|
+
radius?: SurfacePanelRadius;
|
|
15
|
+
surface?: SurfacePanelSurface;
|
|
16
|
+
tone?: SurfacePanelTone;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const SURFACE_PANEL_BASE_CLASS = "border border-outline";
|
|
20
|
+
const SURFACE_PANEL_PADDING_CLASS: Record<SurfacePanelPadding, string> = {
|
|
21
|
+
compact: "p-2",
|
|
22
|
+
default: "p-3",
|
|
23
|
+
none: "",
|
|
24
|
+
};
|
|
25
|
+
const SURFACE_PANEL_RADIUS_CLASS: Record<SurfacePanelRadius, string> = {
|
|
26
|
+
lg: "rounded-lg",
|
|
27
|
+
xl: "rounded-xl",
|
|
28
|
+
"2xl": "rounded-2xl",
|
|
29
|
+
"3xl": "rounded-3xl",
|
|
30
|
+
full: "rounded-full",
|
|
31
|
+
};
|
|
32
|
+
const SURFACE_PANEL_SURFACE_CLASS: Record<SurfacePanelSurface, string> = {
|
|
33
|
+
high: "bg-surface-container-high",
|
|
34
|
+
low: "bg-surface-container-low",
|
|
35
|
+
};
|
|
36
|
+
const SURFACE_PANEL_TONE_CLASS: Record<SurfacePanelTone, string> = {
|
|
37
|
+
default: "",
|
|
38
|
+
accent: "border-primary text-on-surface",
|
|
39
|
+
selected: "border-primary bg-primary-container text-on-primary-container",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export function surfacePanelVariants({
|
|
43
|
+
className,
|
|
44
|
+
padding = "default",
|
|
45
|
+
radius = "xl",
|
|
46
|
+
surface = "high",
|
|
47
|
+
tone = "default",
|
|
48
|
+
}: Pick<
|
|
49
|
+
SurfacePanelProps,
|
|
50
|
+
"className" | "padding" | "radius" | "surface" | "tone"
|
|
51
|
+
>) {
|
|
52
|
+
return cn(
|
|
53
|
+
SURFACE_PANEL_BASE_CLASS,
|
|
54
|
+
SURFACE_PANEL_PADDING_CLASS[padding],
|
|
55
|
+
SURFACE_PANEL_RADIUS_CLASS[radius],
|
|
56
|
+
SURFACE_PANEL_SURFACE_CLASS[surface],
|
|
57
|
+
SURFACE_PANEL_TONE_CLASS[tone],
|
|
58
|
+
className,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const SurfacePanel = forwardRef<HTMLDivElement, SurfacePanelProps>(
|
|
63
|
+
function SurfacePanel(
|
|
64
|
+
{
|
|
65
|
+
asChild = false,
|
|
66
|
+
className,
|
|
67
|
+
padding = "default",
|
|
68
|
+
radius = "xl",
|
|
69
|
+
surface = "high",
|
|
70
|
+
tone = "default",
|
|
71
|
+
...props
|
|
72
|
+
},
|
|
73
|
+
ref,
|
|
74
|
+
) {
|
|
75
|
+
const Component = asChild ? Slot : "div";
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<Component
|
|
79
|
+
className={surfacePanelVariants({
|
|
80
|
+
className,
|
|
81
|
+
padding,
|
|
82
|
+
radius,
|
|
83
|
+
surface,
|
|
84
|
+
tone,
|
|
85
|
+
})}
|
|
86
|
+
ref={ref}
|
|
87
|
+
{...props}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
},
|
|
91
|
+
);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
|
|
2
|
+
import type { ComponentProps } from "react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../utilities/cn";
|
|
5
|
+
|
|
6
|
+
export const Collapsible = CollapsiblePrimitive.Root;
|
|
7
|
+
export const CollapsibleTrigger = CollapsiblePrimitive.Trigger;
|
|
8
|
+
|
|
9
|
+
export function CollapsibleContent({
|
|
10
|
+
className,
|
|
11
|
+
...props
|
|
12
|
+
}: ComponentProps<typeof CollapsiblePrimitive.Content>) {
|
|
13
|
+
return (
|
|
14
|
+
<CollapsiblePrimitive.Content
|
|
15
|
+
className={cn(
|
|
16
|
+
"overflow-hidden data-[state=closed]:animate-[overlay-collapsible-up_160ms_ease-out] data-[state=open]:animate-[overlay-collapsible-down_200ms_ease-out]",
|
|
17
|
+
className,
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
2
|
+
import type { ComponentProps, HTMLAttributes } from "react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../utilities/cn";
|
|
5
|
+
import {
|
|
6
|
+
OVERLAY_DIALOG_CONTENT_SHELL_CLASS,
|
|
7
|
+
OVERLAY_FORM_GROUP_CLASS,
|
|
8
|
+
} from "./overlay-layout";
|
|
9
|
+
|
|
10
|
+
const DIALOG_CLOSE_BUTTON_CLASS =
|
|
11
|
+
"absolute right-4 top-4 inline-flex min-h-9 w-9 items-center justify-center rounded-full border border-outline bg-transparent p-0 text-on-surface transition-colors hover:bg-surface-container-low disabled:pointer-events-none disabled:opacity-50";
|
|
12
|
+
|
|
13
|
+
function DialogCloseIcon() {
|
|
14
|
+
return (
|
|
15
|
+
<svg
|
|
16
|
+
aria-hidden="true"
|
|
17
|
+
fill="none"
|
|
18
|
+
height="18"
|
|
19
|
+
viewBox="0 0 24 24"
|
|
20
|
+
width="18"
|
|
21
|
+
>
|
|
22
|
+
<path
|
|
23
|
+
d="M6 6l12 12M18 6L6 18"
|
|
24
|
+
stroke="currentColor"
|
|
25
|
+
strokeLinecap="round"
|
|
26
|
+
strokeLinejoin="round"
|
|
27
|
+
strokeWidth="1.8"
|
|
28
|
+
/>
|
|
29
|
+
</svg>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const Dialog = DialogPrimitive.Root;
|
|
34
|
+
export const DialogTrigger = DialogPrimitive.Trigger;
|
|
35
|
+
export const DialogPortal = DialogPrimitive.Portal;
|
|
36
|
+
export const DialogClose = DialogPrimitive.Close;
|
|
37
|
+
|
|
38
|
+
export function DialogOverlay({
|
|
39
|
+
className,
|
|
40
|
+
...props
|
|
41
|
+
}: ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
42
|
+
return (
|
|
43
|
+
<DialogPrimitive.Overlay
|
|
44
|
+
className={cn(
|
|
45
|
+
"fixed inset-0 z-50 bg-black/70 backdrop-blur-sm data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
46
|
+
className,
|
|
47
|
+
)}
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type DialogContentProps = ComponentProps<typeof DialogPrimitive.Content> & {
|
|
54
|
+
closeDisabled?: boolean;
|
|
55
|
+
closeLabel?: string;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export function DialogContent({
|
|
59
|
+
children,
|
|
60
|
+
className,
|
|
61
|
+
closeDisabled = false,
|
|
62
|
+
closeLabel = "Close",
|
|
63
|
+
...props
|
|
64
|
+
}: DialogContentProps) {
|
|
65
|
+
return (
|
|
66
|
+
<DialogPortal>
|
|
67
|
+
<DialogOverlay />
|
|
68
|
+
<DialogPrimitive.Content
|
|
69
|
+
className={cn(
|
|
70
|
+
"fixed inset-x-4 top-1/2 z-50 mx-auto max-h-dvh max-w-2xl -translate-y-1/2 overflow-y-auto rounded-2xl border border-outline bg-surface-container-high text-on-surface shadow-xl",
|
|
71
|
+
OVERLAY_DIALOG_CONTENT_SHELL_CLASS,
|
|
72
|
+
className,
|
|
73
|
+
)}
|
|
74
|
+
{...props}
|
|
75
|
+
>
|
|
76
|
+
{children}
|
|
77
|
+
{closeDisabled ? (
|
|
78
|
+
<button
|
|
79
|
+
aria-label={closeLabel}
|
|
80
|
+
className={DIALOG_CLOSE_BUTTON_CLASS}
|
|
81
|
+
disabled
|
|
82
|
+
type="button"
|
|
83
|
+
>
|
|
84
|
+
<DialogCloseIcon />
|
|
85
|
+
</button>
|
|
86
|
+
) : (
|
|
87
|
+
<DialogPrimitive.Close
|
|
88
|
+
aria-label={closeLabel}
|
|
89
|
+
className={DIALOG_CLOSE_BUTTON_CLASS}
|
|
90
|
+
>
|
|
91
|
+
<DialogCloseIcon />
|
|
92
|
+
</DialogPrimitive.Close>
|
|
93
|
+
)}
|
|
94
|
+
</DialogPrimitive.Content>
|
|
95
|
+
</DialogPortal>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function DialogHeader({
|
|
100
|
+
className,
|
|
101
|
+
...props
|
|
102
|
+
}: HTMLAttributes<HTMLDivElement>) {
|
|
103
|
+
return (
|
|
104
|
+
<div
|
|
105
|
+
className={cn(OVERLAY_FORM_GROUP_CLASS, "text-left", className)}
|
|
106
|
+
{...props}
|
|
107
|
+
/>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function DialogFooter({
|
|
112
|
+
className,
|
|
113
|
+
...props
|
|
114
|
+
}: HTMLAttributes<HTMLDivElement>) {
|
|
115
|
+
return (
|
|
116
|
+
<div
|
|
117
|
+
className={cn("flex flex-wrap justify-end gap-layout-element", className)}
|
|
118
|
+
{...props}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function DialogTitle({
|
|
124
|
+
className,
|
|
125
|
+
...props
|
|
126
|
+
}: ComponentProps<typeof DialogPrimitive.Title>) {
|
|
127
|
+
return (
|
|
128
|
+
<DialogPrimitive.Title
|
|
129
|
+
className={cn(
|
|
130
|
+
"font-display text-2xl leading-tight tracking-[-0.03em] text-on-surface",
|
|
131
|
+
className,
|
|
132
|
+
)}
|
|
133
|
+
{...props}
|
|
134
|
+
/>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function DialogDescription({
|
|
139
|
+
className,
|
|
140
|
+
...props
|
|
141
|
+
}: ComponentProps<typeof DialogPrimitive.Description>) {
|
|
142
|
+
return (
|
|
143
|
+
<DialogPrimitive.Description
|
|
144
|
+
className={cn("text-sm leading-6 text-on-surface-variant", className)}
|
|
145
|
+
{...props}
|
|
146
|
+
/>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Stable category path for `@you-agent-factory/components/overlays`. */
|
|
2
|
+
export const COMPONENTS_CATEGORY = "overlays" as const;
|
|
3
|
+
|
|
4
|
+
export type ComponentsCategory = typeof COMPONENTS_CATEGORY;
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
Collapsible,
|
|
8
|
+
CollapsibleContent,
|
|
9
|
+
CollapsibleTrigger,
|
|
10
|
+
} from "./collapsible";
|
|
11
|
+
export {
|
|
12
|
+
Dialog,
|
|
13
|
+
DialogClose,
|
|
14
|
+
DialogContent,
|
|
15
|
+
DialogDescription,
|
|
16
|
+
DialogFooter,
|
|
17
|
+
DialogHeader,
|
|
18
|
+
DialogOverlay,
|
|
19
|
+
DialogPortal,
|
|
20
|
+
DialogTitle,
|
|
21
|
+
DialogTrigger,
|
|
22
|
+
} from "./dialog";
|
|
23
|
+
export type { DialogContentProps } from "./dialog";
|
|
24
|
+
export {
|
|
25
|
+
OVERLAY_DIALOG_BODY_CLASS,
|
|
26
|
+
OVERLAY_DIALOG_CONTENT_SHELL_CLASS,
|
|
27
|
+
OVERLAY_FORM_GROUP_CLASS,
|
|
28
|
+
} from "./overlay-layout";
|
|
29
|
+
export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "./popover";
|
|
30
|
+
export { ScrollArea, ScrollBar } from "./scroll-area";
|
|
31
|
+
export type { ScrollAreaProps, ScrollBarProps } from "./scroll-area";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Interior stack for dialog header, body, and footer regions. */
|
|
2
|
+
export const OVERLAY_FORM_GROUP_CLASS = "grid gap-layout-tight";
|
|
3
|
+
|
|
4
|
+
/** Dialog and modal body regions between header and footer. */
|
|
5
|
+
export const OVERLAY_DIALOG_BODY_CLASS = "grid gap-layout-group";
|
|
6
|
+
|
|
7
|
+
/** Radix dialog content shell spacing for package-owned dialogs. */
|
|
8
|
+
export const OVERLAY_DIALOG_CONTENT_SHELL_CLASS =
|
|
9
|
+
"grid gap-layout-group p-layout-inset-dialog";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
2
|
+
import type { ComponentProps } from "react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../utilities/cn";
|
|
5
|
+
|
|
6
|
+
export const Popover = PopoverPrimitive.Root;
|
|
7
|
+
export const PopoverTrigger = PopoverPrimitive.Trigger;
|
|
8
|
+
export const PopoverAnchor = PopoverPrimitive.Anchor;
|
|
9
|
+
|
|
10
|
+
export function PopoverContent({
|
|
11
|
+
align = "center",
|
|
12
|
+
className,
|
|
13
|
+
sideOffset = 10,
|
|
14
|
+
...props
|
|
15
|
+
}: ComponentProps<typeof PopoverPrimitive.Content>) {
|
|
16
|
+
return (
|
|
17
|
+
<PopoverPrimitive.Portal>
|
|
18
|
+
<PopoverPrimitive.Content
|
|
19
|
+
align={align}
|
|
20
|
+
className={cn(
|
|
21
|
+
"z-50 w-72 rounded-2xl border border-outline bg-surface-container-high p-3 text-on-surface shadow-xl outline-none data-[state=closed]:animate-out data-[state=open]:animate-in sm:w-80",
|
|
22
|
+
className,
|
|
23
|
+
)}
|
|
24
|
+
sideOffset={sideOffset}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
</PopoverPrimitive.Portal>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
|
2
|
+
import { type ComponentProps, type ComponentRef, forwardRef } from "react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../utilities/cn";
|
|
5
|
+
|
|
6
|
+
const SCROLL_AREA_VIEWPORT_CLASS = cn(
|
|
7
|
+
"size-full outline-none",
|
|
8
|
+
"[&>div]:!block [&>div]:size-full",
|
|
9
|
+
"[scrollbar-width:none] [-ms-overflow-style:none]",
|
|
10
|
+
"[&::-webkit-scrollbar]:hidden",
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
export type ScrollAreaProps = ComponentProps<
|
|
14
|
+
typeof ScrollAreaPrimitive.Root
|
|
15
|
+
> & {
|
|
16
|
+
viewportClassName?: string;
|
|
17
|
+
viewportProps?: ComponentProps<typeof ScrollAreaPrimitive.Viewport>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const ScrollArea = forwardRef<
|
|
21
|
+
ComponentRef<typeof ScrollAreaPrimitive.Root>,
|
|
22
|
+
ScrollAreaProps
|
|
23
|
+
>(function ScrollArea(
|
|
24
|
+
{
|
|
25
|
+
children,
|
|
26
|
+
className,
|
|
27
|
+
type = "auto",
|
|
28
|
+
viewportClassName,
|
|
29
|
+
viewportProps,
|
|
30
|
+
...props
|
|
31
|
+
},
|
|
32
|
+
ref,
|
|
33
|
+
) {
|
|
34
|
+
return (
|
|
35
|
+
<ScrollAreaPrimitive.Root
|
|
36
|
+
className={cn("relative overflow-hidden", className)}
|
|
37
|
+
ref={ref}
|
|
38
|
+
type={type}
|
|
39
|
+
{...props}
|
|
40
|
+
>
|
|
41
|
+
<ScrollAreaPrimitive.Viewport
|
|
42
|
+
className={cn(SCROLL_AREA_VIEWPORT_CLASS, viewportClassName)}
|
|
43
|
+
{...viewportProps}
|
|
44
|
+
>
|
|
45
|
+
{children}
|
|
46
|
+
</ScrollAreaPrimitive.Viewport>
|
|
47
|
+
<ScrollBar />
|
|
48
|
+
<ScrollAreaPrimitive.Corner />
|
|
49
|
+
</ScrollAreaPrimitive.Root>
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export type ScrollBarProps = ComponentProps<
|
|
54
|
+
typeof ScrollAreaPrimitive.ScrollAreaScrollbar
|
|
55
|
+
>;
|
|
56
|
+
|
|
57
|
+
export const ScrollBar = forwardRef<
|
|
58
|
+
ComponentRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
|
|
59
|
+
ScrollBarProps
|
|
60
|
+
>(function ScrollBar({ className, orientation = "vertical", ...props }, ref) {
|
|
61
|
+
return (
|
|
62
|
+
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
|
63
|
+
className={cn(
|
|
64
|
+
"flex touch-none select-none bg-transparent p-px transition-colors",
|
|
65
|
+
orientation === "vertical" &&
|
|
66
|
+
"h-full w-2.5 border-l border-l-transparent",
|
|
67
|
+
orientation === "horizontal" &&
|
|
68
|
+
"h-2.5 flex-col border-t border-t-transparent",
|
|
69
|
+
className,
|
|
70
|
+
)}
|
|
71
|
+
orientation={orientation}
|
|
72
|
+
ref={ref}
|
|
73
|
+
{...props}
|
|
74
|
+
>
|
|
75
|
+
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-outline-variant transition-colors hover:bg-on-surface-variant" />
|
|
76
|
+
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
|
77
|
+
);
|
|
78
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type AnchorHTMLAttributes, forwardRef } from "react";
|
|
2
|
+
|
|
3
|
+
import { Button, type ButtonProps } from "./button";
|
|
4
|
+
|
|
5
|
+
export interface ButtonLinkProps
|
|
6
|
+
extends AnchorHTMLAttributes<HTMLAnchorElement>,
|
|
7
|
+
Pick<ButtonProps, "size" | "tone"> {}
|
|
8
|
+
|
|
9
|
+
export const ButtonLink = forwardRef<HTMLAnchorElement, ButtonLinkProps>(
|
|
10
|
+
function ButtonLink(
|
|
11
|
+
{ children, className, size = "default", tone = "default", ...props },
|
|
12
|
+
ref,
|
|
13
|
+
) {
|
|
14
|
+
return (
|
|
15
|
+
<Button asChild className={className} size={size} tone={tone}>
|
|
16
|
+
<a ref={ref} {...props}>
|
|
17
|
+
{children}
|
|
18
|
+
</a>
|
|
19
|
+
</Button>
|
|
20
|
+
);
|
|
21
|
+
},
|
|
22
|
+
);
|