Skip to content

Commit 01340e5

Browse files
committed
feat: add callout component
1 parent 4ea1a6c commit 01340e5

File tree

6 files changed

+146
-1
lines changed

6 files changed

+146
-1
lines changed

packages/ui-react/.storybook/preview.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Preview } from "@storybook/react";
22

33
import "../src/style.css";
4+
import "./style.css";
45

56
const preview = {
67
parameters: {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@import "tailwindcss/preflight.css" layer(base);
2+
@import "../src/theme.css";
3+
4+
@layer base {
5+
html {
6+
/* @apply text-gray-dark; */
7+
@apply text-red;
8+
}
9+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import type { Meta, Preview } from "@storybook/react";
2+
import { TentTreeIcon } from "lucide-react";
3+
import * as Callout from "./callout.js";
4+
5+
export default {
6+
title: "Components/Callout",
7+
component: Callout.Callout,
8+
argTypes: {
9+
children: {
10+
control: false,
11+
},
12+
icon: {
13+
control: false,
14+
},
15+
},
16+
} satisfies Meta;
17+
18+
export const Simple = {
19+
args: {
20+
children: "This is a callout component.",
21+
},
22+
} satisfies Preview;
23+
24+
export const LongContent = {
25+
args: {
26+
children: `
27+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum eget
28+
urna in nulla finibus feugiat. Nulla facilisi. Sed varius eros at felis
29+
eleifend, nec venenatis risus tincidunt. Praesent ullamcorper arcu at
30+
ligula feugiat, in lacinia turpis consequat. Cras commodo enim sit amet
31+
justo ultrices, non fringilla felis dignissim. Donec pulvinar lectus non
32+
turpis eleifend, non lacinia magna accumsan. Nullam in elit magna. Ut ut
33+
urna sit amet nunc faucibus commodo.
34+
`,
35+
},
36+
} satisfies Preview;
37+
38+
export const WithCustomIcon = {
39+
args: {
40+
children: "This callout has a custom icon.",
41+
icon: TentTreeIcon,
42+
},
43+
} satisfies Preview;
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { Slot } from "@radix-ui/react-slot";
2+
import { type VariantProps, cva } from "class-variance-authority";
3+
import {
4+
CheckIcon,
5+
CircleAlertIcon,
6+
InfoIcon,
7+
type LucideIcon,
8+
TriangleAlertIcon,
9+
} from "lucide-react";
10+
import { forwardRef } from "react";
11+
import { cn } from "../../lib/utils.js";
12+
13+
const calloutVariants = cva(
14+
`
15+
flex gap-2
16+
p-4
17+
border
18+
rounded-lg
19+
`,
20+
{
21+
variants: {
22+
variant: {
23+
default: `
24+
[--callout-icon-color:var(--color-gray-dark)]
25+
bg-gray-light text-gray-dark
26+
border-gray-300
27+
`,
28+
info: `
29+
[--callout-icon-color:var(--color-blue-00)]
30+
bg-blue-100 text-blue-800
31+
border-blue-200
32+
`,
33+
warning: `
34+
[--callout-icon-color:var(--color-orange-800)]
35+
bg-orange-100 text-orange-800
36+
border-orange-200
37+
`,
38+
error: `
39+
[--callout-icon-color:var(--color-red-800)]
40+
bg-red-100 text-red-800
41+
border-red-200
42+
`,
43+
success: `
44+
[--callout-icon-color:var(--color-trackergreen-800)]
45+
bg-trackergreen-100 text-trackergreen-800
46+
border-trackergreen-200
47+
`,
48+
},
49+
},
50+
},
51+
);
52+
53+
type Variants = NonNullable<VariantProps<typeof calloutVariants>["variant"]>;
54+
const variantIcons: Record<Variants, LucideIcon> = {
55+
default: InfoIcon,
56+
info: InfoIcon,
57+
warning: CircleAlertIcon,
58+
error: TriangleAlertIcon,
59+
success: CheckIcon,
60+
};
61+
62+
export type CalloutProps = React.HTMLAttributes<HTMLDivElement> &
63+
VariantProps<typeof calloutVariants> & {
64+
asChild?: boolean;
65+
icon?: LucideIcon;
66+
};
67+
68+
const Callout = forwardRef<HTMLDivElement, CalloutProps>(
69+
({ className, asChild = false, variant, children, ...props }, ref) => {
70+
const Comp = asChild ? Slot : "div";
71+
72+
variant = variant || "default";
73+
const Icon = props.icon || variantIcons[variant];
74+
75+
return (
76+
<Comp
77+
className={cn(calloutVariants({ variant, className }))}
78+
ref={ref}
79+
{...props}
80+
>
81+
<div>
82+
<Icon className="h-6 w-6 text-(--callout-icon-color)" />
83+
</div>
84+
{children}
85+
</Comp>
86+
);
87+
},
88+
);
89+
Callout.displayName = "Callout";
90+
91+
export { Callout };

packages/ui-react/src/components/form-field/form-field.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const Field = forwardRef<HTMLDivElement, FieldProps>(
1717
const Comp = asChild ? Slot : "div";
1818

1919
return (
20-
<Comp className={cn("")} ref={ref} {...props}>
20+
<Comp className={cn("", className)} ref={ref} {...props}>
2121
{children}
2222
</Comp>
2323
);

packages/ui-react/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ export * as FormField from "./components/form-field/form-field.js";
44
export * as Input from "./components/input/input.js";
55
export * as Select from "./components/select/select.js";
66
export * as Toast from "./components/toast/toast.js";
7+
export * as Callout from "./components/callout/callout.js";

0 commit comments

Comments
 (0)