-
-
- examples/with-tailwind -
- web
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {LINKS.map(({ title, href, description }) => (
-
- {description}
-
- ))}
-
+
+
);
}
diff --git a/apps/web/package.json b/apps/web/package.json
index 66bb0f0..021d626 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -18,7 +18,6 @@
},
"devDependencies": {
"@repo/eslint-config": "workspace:*",
- "@repo/tailwind-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@types/node": "catalog:",
"@types/react": "catalog:",
diff --git a/apps/web/postcss.config.mjs b/apps/web/postcss.config.mjs
new file mode 100644
index 0000000..111255a
--- /dev/null
+++ b/apps/web/postcss.config.mjs
@@ -0,0 +1 @@
+export { default } from '@repo/ui/postcss.config';
diff --git a/apps/web/public/circles.svg b/apps/web/public/circles.svg
deleted file mode 100644
index 6533be5..0000000
--- a/apps/web/public/circles.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
\ No newline at end of file
diff --git a/apps/web/public/turborepo.svg b/apps/web/public/turborepo.svg
deleted file mode 100644
index 2f9aa1f..0000000
--- a/apps/web/public/turborepo.svg
+++ /dev/null
@@ -1,32 +0,0 @@
-
diff --git a/apps/web/public/vercel.svg b/apps/web/public/vercel.svg
deleted file mode 100644
index d2f8422..0000000
--- a/apps/web/public/vercel.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/apps/web/tailwind.config.ts b/apps/web/tailwind.config.ts
index 39830ef..b4e7e7b 100644
--- a/apps/web/tailwind.config.ts
+++ b/apps/web/tailwind.config.ts
@@ -1,12 +1 @@
-import sharedConfig from '@repo/tailwind-config';
-import { type Config } from 'tailwindcss';
-
-export default {
- content: [
- './pages/**/*.{js,ts,jsx,tsx,mdx}',
- './components/**/*.{js,ts,jsx,tsx,mdx}',
- './app/**/*.{js,ts,jsx,tsx,mdx}',
- ],
- plugins: [],
- presets: [sharedConfig],
-} satisfies Config;
+export * from '@repo/ui/tailwind.config';
diff --git a/packages/tailwind-config/package.json b/packages/tailwind-config/package.json
deleted file mode 100644
index 8b67b34..0000000
--- a/packages/tailwind-config/package.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name": "@repo/tailwind-config",
- "version": "0.0.0",
- "private": true,
- "exports": {
- ".": "./tailwind.config.ts"
- },
- "devDependencies": {
- "@repo/typescript-config": "workspace:*",
- "tailwindcss": "catalog:"
- }
-}
diff --git a/packages/tailwind-config/tailwind.config.ts b/packages/tailwind-config/tailwind.config.ts
deleted file mode 100644
index c6d5534..0000000
--- a/packages/tailwind-config/tailwind.config.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import type { Config } from 'tailwindcss';
-
-// We want each package to be responsible for its own content.
-const config: Omit = {
- theme: {
- extend: {
- backgroundImage: {
- 'glow-conic':
- 'conic-gradient(from 180deg at 50% 50%, #2a8af6 0deg, #a853ba 180deg, #e92a67 360deg)',
- },
- colors: {
- background: 'var(--background)',
- foreground: 'var(--foreground)',
- },
- },
- },
- plugins: [],
-};
-export default config;
diff --git a/packages/tailwind-config/tsconfig.json b/packages/tailwind-config/tsconfig.json
deleted file mode 100644
index 940bd69..0000000
--- a/packages/tailwind-config/tsconfig.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "extends": "@repo/typescript-config/base.json",
- "include": ["."],
- "exclude": ["dist", "build", "node_modules"]
-}
diff --git a/packages/ui/components.json b/packages/ui/components.json
new file mode 100644
index 0000000..66c6c4a
--- /dev/null
+++ b/packages/ui/components.json
@@ -0,0 +1,20 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "aliases": {
+ "components": "@repo/ui/components",
+ "hooks": "@repo/ui/hooks",
+ "lib": "@repo/ui/lib",
+ "ui": "@repo/ui/components/ui",
+ "utils": "@repo/ui/lib/utils"
+ },
+ "rsc": true,
+ "style": "default",
+ "tailwind": {
+ "baseColor": "violet",
+ "config": "tailwind.config.ts",
+ "css": "src/globals.css",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "tsx": true
+}
diff --git a/packages/ui/eslint.config.js b/packages/ui/eslint.config.js
index 590a13c..b77e40e 100644
--- a/packages/ui/eslint.config.js
+++ b/packages/ui/eslint.config.js
@@ -2,4 +2,12 @@ import { reactConfig } from '@repo/eslint-config/react-internal';
import { tailwindConfig } from '@repo/eslint-config/tailwind';
/** @type {import("eslint").Linter.Config} */
-export default [...reactConfig, ...tailwindConfig];
+export default [
+ ...reactConfig,
+ ...tailwindConfig,
+ {
+ rules: {
+ 'react/forbid-component-props': 'off',
+ },
+ },
+];
diff --git a/packages/ui/package.json b/packages/ui/package.json
index ff39c6f..12b06fb 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -9,19 +9,25 @@
"dist"
],
"exports": {
- "./styles.css": "./dist/index.css",
- "./card": "./src/card.tsx"
+ "./globals.css": "./src/globals.css",
+ "./postcss.config": "./postcss.config.mjs",
+ "./tailwind.config": "./tailwind.config.ts",
+ "./lib/*": "./src/lib/*.ts",
+ "./hooks/*": [
+ "./src/hooks/*.ts",
+ "./src/hooks/*.tsx"
+ ],
+ "./components/*": "./src/components/*.tsx"
},
"license": "MIT",
"scripts": {
- "build": "tailwindcss -i ./src/styles.css -o ./dist/index.css",
+ "ui": "pnpm dlx shadcn@latest",
"lint": "eslint src/",
- "dev": "tailwindcss -i ./src/styles.css -o ./dist/index.css --watch",
"type-check": "tsc --noEmit"
},
"devDependencies": {
+ "@radix-ui/react-slot": "^1.1.0",
"@repo/eslint-config": "workspace:*",
- "@repo/tailwind-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@types/react": "catalog:",
"autoprefixer": "catalog:",
@@ -29,6 +35,7 @@
"clsx": "catalog:",
"lucide-react": "catalog:",
"postcss": "catalog:",
+ "postcss-load-config": "^6.0.1",
"tailwind-merge": "catalog:",
"tailwindcss": "catalog:",
"tailwindcss-animate": "catalog:",
diff --git a/packages/ui/postcss.config.js b/packages/ui/postcss.config.js
deleted file mode 100644
index 07aa434..0000000
--- a/packages/ui/postcss.config.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// If you want to use other PostCSS plugins, see the following:
-// https://tailwindcss.com/docs/using-with-preprocessors
-
-module.exports = {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
-};
diff --git a/apps/web/postcss.config.js b/packages/ui/postcss.config.mjs
similarity index 100%
rename from apps/web/postcss.config.js
rename to packages/ui/postcss.config.mjs
diff --git a/packages/ui/src/card.tsx b/packages/ui/src/card.tsx
deleted file mode 100644
index cc0991c..0000000
--- a/packages/ui/src/card.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import { type ReactNode } from "react";
-
-export function Card({
- title,
- children,
- href,
-}: {
- title: string;
- children: ReactNode;
- href: string;
-}): JSX.Element {
- return (
-
-
- {title}{" "}
-
- ->
-
-
-
- {children}
-
-
- );
-}
diff --git a/packages/ui/src/components/ui/button.tsx b/packages/ui/src/components/ui/button.tsx
new file mode 100644
index 0000000..c8d2dcb
--- /dev/null
+++ b/packages/ui/src/components/ui/button.tsx
@@ -0,0 +1,54 @@
+import { Slot } from '@radix-ui/react-slot';
+import { cn } from '@repo/ui/lib/utils';
+import { cva, type VariantProps } from 'class-variance-authority';
+import * as React from 'react';
+
+const buttonVariants = cva(
+ 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
+ {
+ defaultVariants: {
+ size: 'default',
+ variant: 'default',
+ },
+ variants: {
+ size: {
+ default: 'h-10 px-4 py-2',
+ icon: 'size-10',
+ lg: 'h-11 rounded-md px-8',
+ sm: 'h-9 rounded-md px-3',
+ },
+ variant: {
+ default: 'bg-primary text-primary-foreground hover:bg-primary/90',
+ destructive:
+ 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
+ ghost: 'hover:bg-accent hover:text-accent-foreground',
+ link: 'text-primary underline-offset-4 hover:underline',
+ outline:
+ 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
+ secondary:
+ 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
+ },
+ },
+ },
+);
+
+export type ButtonProps = React.ButtonHTMLAttributes &
+ VariantProps & {
+ readonly asChild?: boolean;
+ };
+
+const Button = React.forwardRef(
+ ({ asChild = false, className, size, variant, ...props }, ref) => {
+ const Comp = asChild ? Slot : 'button';
+ return (
+
+ );
+ },
+);
+Button.displayName = 'Button';
+
+export { Button, buttonVariants };
diff --git a/packages/ui/src/globals.css b/packages/ui/src/globals.css
new file mode 100644
index 0000000..be31070
--- /dev/null
+++ b/packages/ui/src/globals.css
@@ -0,0 +1,69 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ :root {
+ --background: 0 0% 100%;
+ --foreground: 240 10% 3.9%;
+ --card: 0 0% 100%;
+ --card-foreground: 240 10% 3.9%;
+ --popover: 0 0% 100%;
+ --popover-foreground: 240 10% 3.9%;
+ --primary: 240 5.9% 10%;
+ --primary-foreground: 0 0% 98%;
+ --secondary: 240 4.8% 95.9%;
+ --secondary-foreground: 240 5.9% 10%;
+ --muted: 240 4.8% 95.9%;
+ --muted-foreground: 240 3.8% 46.1%;
+ --accent: 240 4.8% 95.9%;
+ --accent-foreground: 240 5.9% 10%;
+ --destructive: 0 84.2% 60.2%;
+ --destructive-foreground: 0 0% 98%;
+ --border: 240 5.9% 90%;
+ --input: 240 5.9% 90%;
+ --ring: 240 5.9% 10%;
+ --radius: 0.5rem;
+ --chart-1: 12 76% 61%;
+ --chart-2: 173 58% 39%;
+ --chart-3: 197 37% 24%;
+ --chart-4: 43 74% 66%;
+ --chart-5: 27 87% 67%;
+ }
+
+ .dark {
+ --background: 240 10% 3.9%;
+ --foreground: 0 0% 98%;
+ --card: 240 10% 3.9%;
+ --card-foreground: 0 0% 98%;
+ --popover: 240 10% 3.9%;
+ --popover-foreground: 0 0% 98%;
+ --primary: 0 0% 98%;
+ --primary-foreground: 240 5.9% 10%;
+ --secondary: 240 3.7% 15.9%;
+ --secondary-foreground: 0 0% 98%;
+ --muted: 240 3.7% 15.9%;
+ --muted-foreground: 240 5% 64.9%;
+ --accent: 240 3.7% 15.9%;
+ --accent-foreground: 0 0% 98%;
+ --destructive: 0 62.8% 30.6%;
+ --destructive-foreground: 0 0% 98%;
+ --border: 240 3.7% 15.9%;
+ --input: 240 3.7% 15.9%;
+ --ring: 240 4.9% 83.9%;
+ --chart-1: 220 70% 50%;
+ --chart-2: 160 60% 45%;
+ --chart-3: 30 80% 55%;
+ --chart-4: 280 65% 60%;
+ --chart-5: 340 75% 55%;
+ }
+}
+
+@layer base {
+ * {
+ @apply border-border;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
diff --git a/packages/ui/src/lib/utils.ts b/packages/ui/src/lib/utils.ts
new file mode 100644
index 0000000..365058c
--- /dev/null
+++ b/packages/ui/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { type ClassValue, clsx } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/packages/ui/src/styles.css b/packages/ui/src/styles.css
deleted file mode 100644
index b5c61c9..0000000
--- a/packages/ui/src/styles.css
+++ /dev/null
@@ -1,3 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
diff --git a/packages/ui/tailwind.config.ts b/packages/ui/tailwind.config.ts
index a4777bf..9821c34 100644
--- a/packages/ui/tailwind.config.ts
+++ b/packages/ui/tailwind.config.ts
@@ -1,10 +1,82 @@
-import type { Config } from "tailwindcss";
-import sharedConfig from "@repo/tailwind-config";
+import { type Config } from 'tailwindcss';
+import tailwindcssAnimate from 'tailwindcss-animate';
-const config: Pick = {
- content: ["./src/**/*.tsx"],
- prefix: "ui-",
- presets: [sharedConfig],
-};
+const config = {
+ content: [
+ './pages/**/*.{ts,tsx}',
+ './components/**/*.{ts,tsx}',
+ './app/**/*.{ts,tsx}',
+ './src/**/*.{ts,tsx}',
+ '../../packages/ui/src/**/*.{ts,tsx}',
+ ],
+ darkMode: ['class'],
+ plugins: [tailwindcssAnimate],
+ prefix: '',
+ theme: {
+ container: {
+ center: true,
+ padding: '2rem',
+ screens: {
+ '2xl': '1400px',
+ },
+ },
+ extend: {
+ animation: {
+ 'accordion-down': 'accordion-down 0.2s ease-out',
+ 'accordion-up': 'accordion-up 0.2s ease-out',
+ },
+ borderRadius: {
+ lg: 'var(--radius)',
+ md: 'calc(var(--radius) - 2px)',
+ sm: 'calc(var(--radius) - 4px)',
+ },
+ colors: {
+ accent: {
+ DEFAULT: 'hsl(var(--accent))',
+ foreground: 'hsl(var(--accent-foreground))',
+ },
+ background: 'hsl(var(--background))',
+ border: 'hsl(var(--border))',
+ card: {
+ DEFAULT: 'hsl(var(--card))',
+ foreground: 'hsl(var(--card-foreground))',
+ },
+ destructive: {
+ DEFAULT: 'hsl(var(--destructive))',
+ foreground: 'hsl(var(--destructive-foreground))',
+ },
+ foreground: 'hsl(var(--foreground))',
+ input: 'hsl(var(--input))',
+ muted: {
+ DEFAULT: 'hsl(var(--muted))',
+ foreground: 'hsl(var(--muted-foreground))',
+ },
+ popover: {
+ DEFAULT: 'hsl(var(--popover))',
+ foreground: 'hsl(var(--popover-foreground))',
+ },
+ primary: {
+ DEFAULT: 'hsl(var(--primary))',
+ foreground: 'hsl(var(--primary-foreground))',
+ },
+ ring: 'hsl(var(--ring))',
+ secondary: {
+ DEFAULT: 'hsl(var(--secondary))',
+ foreground: 'hsl(var(--secondary-foreground))',
+ },
+ },
+ keyframes: {
+ 'accordion-down': {
+ from: { height: '0' },
+ to: { height: 'var(--radix-accordion-content-height)' },
+ },
+ 'accordion-up': {
+ from: { height: 'var(--radix-accordion-content-height)' },
+ to: { height: '0' },
+ },
+ },
+ },
+ },
+} satisfies Config;
export default config;
diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json
index 1a0e3e8..3799017 100644
--- a/packages/ui/tsconfig.json
+++ b/packages/ui/tsconfig.json
@@ -1,5 +1,11 @@
{
"extends": "@repo/typescript-config/react-library.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./*"]
+ }
+ },
"include": ["."],
"exclude": ["dist", "build", "node_modules"]
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6b35672..b40a961 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -102,9 +102,6 @@ importers:
'@repo/eslint-config':
specifier: workspace:*
version: link:../../packages/eslint-config
- '@repo/tailwind-config':
- specifier: workspace:*
- version: link:../../packages/tailwind-config
'@repo/typescript-config':
specifier: workspace:*
version: link:../../packages/typescript-config
@@ -145,15 +142,6 @@ importers:
specifier: 'catalog:'
version: 2.3.2(eslint@9.15.0(jiti@1.21.6))
- packages/tailwind-config:
- devDependencies:
- '@repo/typescript-config':
- specifier: workspace:*
- version: link:../typescript-config
- tailwindcss:
- specifier: 'catalog:'
- version: 3.4.15
-
packages/typescript-config: {}
packages/ui:
@@ -165,12 +153,12 @@ importers:
specifier: 'catalog:'
version: 19.0.0-rc-5c56b873-20241107(react@19.0.0-rc-5c56b873-20241107)
devDependencies:
+ '@radix-ui/react-slot':
+ specifier: ^1.1.0
+ version: 1.1.0(@types/react@18.3.1)(react@19.0.0-rc-5c56b873-20241107)
'@repo/eslint-config':
specifier: workspace:*
version: link:../eslint-config
- '@repo/tailwind-config':
- specifier: workspace:*
- version: link:../tailwind-config
'@repo/typescript-config':
specifier: workspace:*
version: link:../typescript-config
@@ -192,6 +180,9 @@ importers:
postcss:
specifier: 'catalog:'
version: 8.4.49
+ postcss-load-config:
+ specifier: ^6.0.1
+ version: 6.0.1(jiti@1.21.6)(postcss@8.4.49)(yaml@2.6.1)
tailwind-merge:
specifier: 'catalog:'
version: 2.5.5
@@ -1244,6 +1235,24 @@ packages:
resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+ '@radix-ui/react-compose-refs@1.1.0':
+ resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-slot@1.1.0':
+ resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
'@repeaterjs/repeater@3.0.4':
resolution: {integrity: sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA==}
@@ -3022,6 +3031,24 @@ packages:
ts-node:
optional: true
+ postcss-load-config@6.0.1:
+ resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ jiti: '>=1.21.0'
+ postcss: '>=8.0.9'
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ jiti:
+ optional: true
+ postcss:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
postcss-nested@6.2.0:
resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==}
engines: {node: '>=12.0'}
@@ -4963,6 +4990,19 @@ snapshots:
'@pkgr/core@0.1.1': {}
+ '@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.1)(react@19.0.0-rc-5c56b873-20241107)':
+ dependencies:
+ react: 19.0.0-rc-5c56b873-20241107
+ optionalDependencies:
+ '@types/react': 18.3.1
+
+ '@radix-ui/react-slot@1.1.0(@types/react@18.3.1)(react@19.0.0-rc-5c56b873-20241107)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.1)(react@19.0.0-rc-5c56b873-20241107)
+ react: 19.0.0-rc-5c56b873-20241107
+ optionalDependencies:
+ '@types/react': 18.3.1
+
'@repeaterjs/repeater@3.0.4': {}
'@repeaterjs/repeater@3.0.6': {}
@@ -7125,6 +7165,14 @@ snapshots:
optionalDependencies:
postcss: 8.4.49
+ postcss-load-config@6.0.1(jiti@1.21.6)(postcss@8.4.49)(yaml@2.6.1):
+ dependencies:
+ lilconfig: 3.1.2
+ optionalDependencies:
+ jiti: 1.21.6
+ postcss: 8.4.49
+ yaml: 2.6.1
+
postcss-nested@6.2.0(postcss@8.4.49):
dependencies:
postcss: 8.4.49