Skip to content

Commit 6315e4b

Browse files
committed
feat: shadcn based alert component
1 parent 7f4c8d7 commit 6315e4b

14 files changed

+359
-0
lines changed

apps/docs/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"lint": "eslint . --ext ./stories/*.stories.tsx --fix && prettier --write ."
1212
},
1313
"dependencies": {
14+
"@signozhq/alert": "workspace:*",
1415
"@signozhq/button": "workspace:*",
1516
"@signozhq/input": "workspace:*",
1617
"@signozhq/tailwind-config": "workspace:*",

apps/docs/stories/alert.stories.tsx

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { Meta, StoryObj } from "@storybook/react";
2+
import { Alert, AlertTitle, AlertDescription } from "@signozhq/alert";
3+
4+
const meta: Meta<typeof Alert> = {
5+
title: "Components/Alert",
6+
component: Alert,
7+
tags: ["autodocs"],
8+
argTypes: {
9+
variant: {
10+
control: "select",
11+
options: ["default", "destructive"],
12+
},
13+
title: {
14+
control: "text",
15+
},
16+
},
17+
};
18+
19+
export default meta;
20+
type Story = StoryObj<typeof Alert>;
21+
22+
const Template: Story = {
23+
render: ({ variant, title, children }) => (
24+
<Alert variant={variant}>
25+
{title && <AlertTitle>{title}</AlertTitle>}
26+
<AlertDescription>{children}</AlertDescription>
27+
</Alert>
28+
),
29+
};
30+
31+
export const Default: Story = {
32+
...Template,
33+
args: {
34+
variant: "default",
35+
title: "Heads up!",
36+
children:
37+
"You can add components and dependencies to your app using the cli.",
38+
},
39+
};
40+
41+
export const Destructive: Story = {
42+
...Template,
43+
args: {
44+
variant: "destructive",
45+
title: "Error",
46+
children: "Your session has expired. Please log in again.",
47+
},
48+
};
49+
50+
export const TitleOnly: Story = {
51+
...Template,
52+
args: {
53+
title: "Note",
54+
children: null,
55+
},
56+
};
57+
58+
export const DescriptionOnly: Story = {
59+
...Template,
60+
args: {
61+
title: "",
62+
children: "This is a description-only alert.",
63+
},
64+
};

packages/alert/.eslintrc.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/** @type {import("eslint").Linter.Config} */
2+
module.exports = {
3+
extends: ["@repo/eslint-config/react.js"],
4+
};

packages/alert/components.json

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"style": "new-york",
3+
"rsc": false,
4+
"tsx": true,
5+
"tailwind": {
6+
"config": "@signozhq/tailwind-config/tailwind.config.js",
7+
"css": "src/index.css",
8+
"baseColor": "zinc",
9+
"cssVariables": true,
10+
"prefix": ""
11+
},
12+
"aliases": {
13+
"components": "@/components",
14+
"utils": "@/lib/utils",
15+
"ui": "src",
16+
"lib": "@/lib",
17+
"hooks": "@/hooks"
18+
}
19+
}

packages/alert/package.json

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"name": "@signozhq/alert",
3+
"version": "0.0.0",
4+
"sideEffects": false,
5+
"license": "MIT",
6+
"type": "module",
7+
"exports": {
8+
".": {
9+
"types": "./dist/alert.d.ts",
10+
"import": "./dist/alert.js"
11+
}
12+
},
13+
"main": "./dist/alert.js",
14+
"module": "./dist/alert.js",
15+
"types": "./dist/alert.d.ts",
16+
"files": [
17+
"dist"
18+
],
19+
"scripts": {
20+
"build": "vite build",
21+
"dev": "vite build --watch",
22+
"lint": "eslint . --max-warnings 0",
23+
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
24+
},
25+
"devDependencies": {
26+
"@repo/eslint-config": "workspace:*",
27+
"@repo/typescript-config": "workspace:*",
28+
"@signozhq/tailwind-config": "workspace:*",
29+
"@types/node": "^22.5.5",
30+
"@types/react": "^18.2.61",
31+
"@types/react-dom": "^18.2.19",
32+
"@vitejs/plugin-react": "^4.2.1",
33+
"autoprefixer": "^10.4.20",
34+
"eslint": "^9.11.0",
35+
"postcss": "^8.4.47",
36+
"react-dom": "^18.2.0",
37+
"tailwindcss": "^3.4.12",
38+
"typescript": "^5.3.3",
39+
"vite": "^5.0.0",
40+
"vite-plugin-lib-inject-css": "^2.1.1",
41+
"vite-plugin-dts": "^4.2.1"
42+
},
43+
"dependencies": {
44+
"@radix-ui/react-icons": "^1.3.0",
45+
"@radix-ui/react-slot": "^1.1.0",
46+
"class-variance-authority": "^0.7.0",
47+
"clsx": "^2.1.1",
48+
"lucide-react": "^0.445.0",
49+
"react": "^18.2.0",
50+
"tailwind-merge": "^2.5.2",
51+
"tailwindcss-animate": "^1.0.7"
52+
},
53+
"publishConfig": {
54+
"access": "public"
55+
},
56+
"description": "Shadcn based alert component"
57+
}

packages/alert/postcss.config.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default {
2+
plugins: {
3+
tailwindcss: {},
4+
autoprefixer: {},
5+
},
6+
}

packages/alert/src/alert.tsx

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import "./index.css"
2+
import * as React from "react"
3+
import { cva, type VariantProps } from "class-variance-authority"
4+
5+
import { cn } from "@/lib/utils"
6+
7+
const alertVariants = cva(
8+
"relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
9+
{
10+
variants: {
11+
variant: {
12+
default: "bg-background text-foreground",
13+
destructive:
14+
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
15+
},
16+
},
17+
defaultVariants: {
18+
variant: "default",
19+
},
20+
}
21+
)
22+
23+
const Alert = React.forwardRef<
24+
HTMLDivElement,
25+
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
26+
>(({ className, variant, ...props }, ref) => (
27+
<div
28+
ref={ref}
29+
role="alert"
30+
className={cn(alertVariants({ variant }), className)}
31+
{...props}
32+
/>
33+
))
34+
Alert.displayName = "Alert"
35+
36+
const AlertTitle = React.forwardRef<
37+
HTMLParagraphElement,
38+
React.HTMLAttributes<HTMLHeadingElement>
39+
>(({ className, ...props }, ref) => (
40+
<h5
41+
ref={ref}
42+
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
43+
{...props}
44+
/>
45+
))
46+
AlertTitle.displayName = "AlertTitle"
47+
48+
const AlertDescription = React.forwardRef<
49+
HTMLParagraphElement,
50+
React.HTMLAttributes<HTMLParagraphElement>
51+
>(({ className, ...props }, ref) => (
52+
<div
53+
ref={ref}
54+
className={cn("text-sm [&_p]:leading-relaxed", className)}
55+
{...props}
56+
/>
57+
))
58+
AlertDescription.displayName = "AlertDescription"
59+
60+
export { Alert, AlertTitle, AlertDescription }

packages/alert/src/index.css

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;

packages/alert/src/lib/utils.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { clsx, type ClassValue } from "clsx"
2+
import { twMerge } from "tailwind-merge"
3+
4+
export function cn(...inputs: ClassValue[]) {
5+
return twMerge(clsx(inputs))
6+
}

packages/alert/tailwind.config.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const sharedConfig = require("@signozhq/tailwind-config/tailwind.config.js");
2+
3+
/** @type {import('tailwindcss').Config} */
4+
module.exports = {
5+
...sharedConfig,
6+
content: [...sharedConfig.content, "./src/**/*.{js,ts,jsx,tsx}"],
7+
};

packages/alert/tsconfig.app.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"compilerOptions": {
3+
"baseUrl": ".",
4+
"paths": {
5+
"@/*": ["./src/*"]
6+
},
7+
"forceConsistentCasingInFileNames": true,
8+
"strict": true
9+
}
10+
}

packages/alert/tsconfig.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"extends": "@repo/typescript-config/react-library.json",
3+
"include": ["src"],
4+
"exclude": ["dist", "build", "node_modules"],
5+
"compilerOptions": {
6+
"outDir": "dist",
7+
"baseUrl": ".",
8+
"paths": {
9+
"@/*": ["./src/*"]
10+
}
11+
}
12+
}

packages/alert/vite.config.ts

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import path from "path";
2+
import { defineConfig } from "vite";
3+
import dts from "vite-plugin-dts";
4+
import react from "@vitejs/plugin-react";
5+
import { resolve } from "path";
6+
import { libInjectCss } from "vite-plugin-lib-inject-css";
7+
8+
export default defineConfig({
9+
build: {
10+
lib: {
11+
entry: resolve(__dirname, "src/alert.tsx"),
12+
name: "Button",
13+
fileName: "alert",
14+
},
15+
rollupOptions: {
16+
external: ["react"],
17+
output: {
18+
globals: {
19+
react: "React",
20+
},
21+
},
22+
treeshake: true,
23+
},
24+
},
25+
plugins: [dts(), react(), libInjectCss()],
26+
resolve: {
27+
alias: {
28+
"@": path.resolve(__dirname, "./src"),
29+
},
30+
},
31+
});

pnpm-lock.yaml

+79
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)