Skip to content

Commit b5df8b6

Browse files
authored
Merge pull request #13617 from ethereum/shadcn-alert
Shadcn migration - alert
2 parents ef24328 + d5ee22b commit b5df8b6

File tree

4 files changed

+183
-2
lines changed

4 files changed

+183
-2
lines changed

src/components/Alert/Alert.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Meta, StoryObj } from "@storybook/react"
55
import Alert from "."
66

77
const meta = {
8-
title: "Molecules / Action Feedback / Alerts",
8+
title: "Molecules / Action Feedback / Old Alerts",
99
component: Alert,
1010
decorators: [
1111
(Story) => (
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import * as React from "react"
2+
import { MdInfoOutline } from "react-icons/md"
3+
import { Meta, StoryObj } from "@storybook/react"
4+
5+
import {
6+
Alert,
7+
AlertCloseButton,
8+
AlertContent,
9+
AlertDescription,
10+
AlertTitle,
11+
} from "../alert"
12+
import { Center } from "../flex"
13+
14+
const meta = {
15+
title: "Molecules / Action Feedback / Alerts",
16+
component: Alert,
17+
parameters: {
18+
layout: "none",
19+
},
20+
decorators: [
21+
(Story) => (
22+
<Center className="min-h-[100vh]">
23+
<Story />
24+
</Center>
25+
),
26+
],
27+
} satisfies Meta<typeof Alert>
28+
29+
export default meta
30+
31+
type Story = StoryObj<typeof meta>
32+
33+
const DEMO_TITLE = "Alert or callout title"
34+
const DEMO_DESC = "This is an alert to be used for important information."
35+
36+
const VARIANTS = ["info", "error", "success", "warning", "update"] as const
37+
38+
export const Variants: Story = {
39+
render: (args) => (
40+
<div className="flex w-[500px] flex-col gap-4">
41+
{VARIANTS.map((variant) => (
42+
<Alert key={variant} variant={variant} className="w-full" {...args}>
43+
<AlertContent>
44+
<AlertTitle>{DEMO_TITLE}</AlertTitle>
45+
<AlertDescription>This is a {variant} alert</AlertDescription>
46+
</AlertContent>
47+
</Alert>
48+
))}
49+
</div>
50+
),
51+
}
52+
53+
export const WithCloseButton: Story = {
54+
render: (args) => (
55+
<div className="flex flex-col gap-4">
56+
{VARIANTS.map((variant) => (
57+
<Alert key={variant} variant={variant} {...args}>
58+
<AlertContent>
59+
<AlertTitle>{DEMO_TITLE}</AlertTitle>
60+
<AlertDescription>{DEMO_DESC}</AlertDescription>
61+
</AlertContent>
62+
<AlertCloseButton />
63+
</Alert>
64+
))}
65+
</div>
66+
),
67+
}
68+
69+
export const Banner: Story = {
70+
render: (args) => (
71+
<div className="mx-8 flex w-full flex-col gap-4">
72+
{VARIANTS.map((variant) => (
73+
<Alert key={variant} variant={variant} size="full" {...args}>
74+
<MdInfoOutline className="h-6 w-6" />
75+
<AlertContent>
76+
<AlertTitle>Banner use case</AlertTitle>
77+
<AlertDescription>
78+
<p>{DEMO_DESC}</p>
79+
<p>{DEMO_DESC}</p>
80+
</AlertDescription>
81+
</AlertContent>
82+
<AlertCloseButton />
83+
</Alert>
84+
))}
85+
</div>
86+
),
87+
}

src/components/ui/alert.tsx

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import * as React from "react"
2+
import { cva, type VariantProps } from "class-variance-authority"
3+
import { MdClose } from "react-icons/md"
4+
5+
import { cn } from "@/lib/utils/cn"
6+
7+
import { Button } from "./buttons/Button"
8+
9+
const alertVariants = cva(
10+
"flex flex-row gap-4 items-center rounded-lg border p-4",
11+
{
12+
variants: {
13+
variant: {
14+
info: "bg-background-highlight border",
15+
error:
16+
"border-error bg-error-light [&_h6]:text-error [&_svg]:text-error text-gray-800",
17+
success:
18+
"border-success bg-success-light [&_h6]:text-success [&_svg]:text-success text-gray-800",
19+
warning:
20+
"border-attention-outline bg-attention-light [&_h6]:text-attention [&_svg]:text-attention text-gray-800",
21+
update:
22+
"bg-primary-low-contrast border-primary-high-contrast [&_h6]:text-primary-high-contrast [&_svg]:text-primary-high-contrast",
23+
},
24+
size: {
25+
// Useful for banner alerts
26+
full: "rounded-none border-none w-full",
27+
},
28+
},
29+
defaultVariants: {
30+
variant: "info",
31+
},
32+
}
33+
)
34+
35+
const Alert = React.forwardRef<
36+
HTMLDivElement,
37+
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
38+
>(({ className, variant, size, ...props }, ref) => (
39+
<div
40+
ref={ref}
41+
role="alert"
42+
className={cn(alertVariants({ variant, size }), className)}
43+
{...props}
44+
/>
45+
))
46+
Alert.displayName = "Alert"
47+
48+
const AlertContent = React.forwardRef<
49+
HTMLDivElement,
50+
React.HTMLAttributes<HTMLDivElement>
51+
>(({ className, ...props }, ref) => (
52+
<div ref={ref} className={cn("flex flex-1 flex-col", className)} {...props} />
53+
))
54+
AlertContent.displayName = "AlertContent"
55+
56+
const AlertTitle = React.forwardRef<
57+
HTMLParagraphElement,
58+
React.HTMLAttributes<HTMLHeadingElement>
59+
>(({ className, ...props }, ref) => (
60+
<h6 ref={ref} className={cn("tracking-tight", className)} {...props} />
61+
))
62+
AlertTitle.displayName = "AlertTitle"
63+
64+
const AlertDescription = React.forwardRef<
65+
HTMLParagraphElement,
66+
React.HTMLAttributes<HTMLParagraphElement>
67+
>(({ className, ...props }, ref) => (
68+
<div
69+
ref={ref}
70+
className={cn("text-sm [&_p]:leading-relaxed", className)}
71+
{...props}
72+
/>
73+
))
74+
AlertDescription.displayName = "AlertDescription"
75+
76+
const AlertCloseButton = React.forwardRef<
77+
HTMLButtonElement,
78+
React.ButtonHTMLAttributes<HTMLButtonElement>
79+
>(({ className, ...props }, ref) => (
80+
<Button
81+
ref={ref}
82+
variant="ghost"
83+
className={cn("-me-4 rounded-full text-body", className)}
84+
{...props}
85+
>
86+
<MdClose className="h-6 w-6" />
87+
<span className="sr-only">Close</span>
88+
</Button>
89+
))
90+
AlertCloseButton.displayName = "AlertCloseButton"
91+
92+
export { Alert, AlertCloseButton, AlertContent, AlertDescription, AlertTitle }

src/styles/global.css

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,9 @@
160160
/* Complementary Set */
161161
--attention-outline: var(--attention-light);
162162

163-
--error-light: var(--error-light);
163+
--error: var(--red-500);
164+
--error-light: var(--red-100);
165+
--error-outline: var(--error);
164166
/* ! Deprecating error-neutral */
165167
--error-netural: var(--red-900);
166168

0 commit comments

Comments
 (0)