forked from jordanlambrecht/tracker-tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNotice.tsx
More file actions
99 lines (90 loc) · 2.76 KB
/
Copy pathNotice.tsx
File metadata and controls
99 lines (90 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// src/components/ui/Notice.tsx
import { cva } from "class-variance-authority"
import clsx from "clsx"
import type { ReactElement, ReactNode } from "react"
import { CheckLargeIcon, InfoIcon, TriangleWarningIcon } from "@/components/ui/Icons"
type NoticeVariant = "danger" | "warn" | "success" | "info" | "default"
interface NoticeProps {
message?: string | null
header?: string
variant?: NoticeVariant
box?: boolean
showIcon?: boolean
icon?: ReactElement
children?: ReactNode
className?: string
}
const notice = cva("text-xs font-sans", {
variants: {
variant: {
danger: "text-danger",
warn: "text-warn",
success: "text-success",
info: "text-accent",
default: "text-secondary",
},
box: {
true: "nm-inset-sm rounded-nm-md border px-4 py-3",
false: "",
},
},
compoundVariants: [
{ variant: "danger", box: true, class: "bg-danger/5 border-danger/20" },
{ variant: "warn", box: true, class: "bg-warn/5 border-warn/20" },
{ variant: "success", box: true, class: "bg-success/5 border-success/20" },
{ variant: "info", box: true, class: "bg-accent/5 border-accent/20" },
{ variant: "default", box: true, class: "bg-control-bg border-border" },
],
defaultVariants: {
variant: "danger",
box: false,
},
})
const defaultIcon: Record<NoticeVariant, ReactNode> = {
danger: <TriangleWarningIcon width="14" height="14" className="shrink-0" />,
warn: <TriangleWarningIcon width="14" height="14" className="shrink-0" />,
success: <CheckLargeIcon width="14" height="14" className="shrink-0" />,
info: <InfoIcon width="14" height="14" className="shrink-0" />,
default: <InfoIcon width="14" height="14" className="shrink-0" />,
}
function Notice({
message,
header,
variant = "danger",
box = false,
showIcon,
icon,
children,
className,
}: NoticeProps) {
const body = children ?? message
if (!body && !header) return null
const iconVisible = showIcon ?? (icon !== undefined || box)
const iconElement = iconVisible ? (icon ?? defaultIcon[variant]) : null
return (
<div
className={clsx(notice({ variant, box }), iconElement && "flex gap-2", className)}
role={
variant === "danger"
? "alert"
: variant === "info" || variant === "default"
? "note"
: "status"
}
>
{iconElement && <span className="mt-px">{iconElement}</span>}
{header && !body ? (
<span className="font-medium">{header}</span>
) : header ? (
<div className="flex flex-col gap-1">
<span className="font-medium">{header}</span>
<span className="text-secondary">{body}</span>
</div>
) : (
body
)}
</div>
)
}
export type { NoticeProps, NoticeVariant }
export { Notice }