├── .gitattributes
├── .gitignore
├── LICENSE
├── LLMModel.jsx
├── README.md
├── assets
└── img
│ └── demo_img.png
└── my-app
├── .eslintrc.cjs
├── .gitignore
├── README.md
├── components.json
├── index.html
├── jsconfig.json
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
└── vite.svg
├── src
├── App.css
├── App.jsx
├── assets
│ └── react.svg
├── components
│ ├── LLMModel.jsx
│ └── ui
│ │ ├── button.jsx
│ │ ├── card.jsx
│ │ └── input.jsx
├── index.css
├── lib
│ └── utils.js
└── main.jsx
├── tailwind.config.js
└── vite.config.js
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Benjamin Klieger
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/LLMModel.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
3 | import { Button } from "@/components/ui/button"
4 | import { Input } from "@/components/ui/input"
5 | import { Boxes, Cpu, Network, Lightbulb, ArrowRight } from 'lucide-react'
6 |
7 | const LLMModel = () => {
8 | const [input, setInput] = useState('');
9 | const [output, setOutput] = useState('');
10 | const [step, setStep] = useState(0);
11 |
12 | const steps = [
13 | {
14 | name: "Tokenization",
15 | icon: ,
16 | description: "The input text is broken down into tokens (words or subwords). This process converts the raw text into a format the model can understand.",
17 | example: input ? input.split(' ').map((word, i) => {word} ) : null
18 | },
19 | {
20 | name: "Embedding",
21 | icon: ,
22 | description: "Each token is converted into a numerical vector representation. This allows the model to process the text mathematically.",
23 | example:
24 | {input.split(' ').slice(0, 4).map((_, i) =>
25 |
26 | [0.2, -0.5, 0.8, ...]
27 |
28 | )}
29 |
30 | },
31 | {
32 | name: "Attention Mechanism",
33 | icon: ,
34 | description: "The model calculates attention scores to understand the relationships between different parts of the input.",
35 | example:
36 | {input.split(' ').slice(0, 4).map((word, i) =>
37 |
38 |
{word}
39 |
40 |
{(Math.random() * 0.5 + 0.5).toFixed(2)}
41 |
42 | )}
43 |
44 | },
45 | {
46 | name: "Feed Forward",
47 | icon: ,
48 | description: "The embedded and attention-weighted inputs are processed through multiple neural network layers.",
49 | example:
50 |
51 |
52 | },
53 | {
54 | name: "Output Generation",
55 | icon: ,
56 | description: "The model generates output tokens based on the processed input and the temperature setting.",
57 | example: output ? {output}
: null
58 | }
59 | ];
60 |
61 | const handleInputChange = (e) => {
62 | setInput(e.target.value);
63 | };
64 |
65 | const handleNextStep = () => {
66 | if (step < steps.length - 1) {
67 | setStep(step + 1);
68 | } else {
69 | setOutput(generateOutput(input));
70 | }
71 | };
72 |
73 | const handleReset = () => {
74 | setInput('');
75 | setOutput('');
76 | setStep(0);
77 | };
78 |
79 | const generateOutput = (input) => {
80 | // This is a simplified simulation of output generation
81 | const words = input.split(' ');
82 | const outputLength = Math.floor(Math.random() * 5) + words.length;
83 | let output = '';
84 | for (let i = 0; i < outputLength; i++) {
85 | output += words[Math.floor(Math.random() * words.length)] + ' ';
86 | }
87 | return output.trim();
88 | };
89 |
90 | return (
91 |
92 |
93 | Enhanced LLM Interactive Model
94 | Explore how LLMs process and generate text
95 |
96 |
97 |
98 |
99 | Input Text:
100 |
105 |
106 |
107 |
108 | {steps[step].icon}
109 |
{steps[step].name}
110 |
111 |
{steps[step].description}
112 |
113 | {steps[step].example}
114 |
115 |
116 |
117 |
118 |
119 |
120 | {step < steps.length - 1 ? 'Next Step' : 'Generate Output'}
121 |
122 | Reset
123 |
124 |
125 | );
126 | };
127 |
128 | export default LLMModel;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Claude React Artifact Tutorial
4 |
5 | Claude recently released Artifacts, which can compile code in a dedicated window. This tutorial helps beginners set up a React app to any React run code generated by Claude's Artifacts feature.
6 |
7 | [](https://www.youtube.com/watch?v=oRh_tVdgjB8)
8 |
9 | > Claude-React-Jumpstart: A step-by-step guide to running Claude-generated React code locally.
10 |
11 | ---
12 |
13 | ## Getting Started
14 | You can use the example provided to learn the process. Before beginning the following steps, remove the my-app folder so you can recreate it.
15 |
16 | ### Step 1: Create new React app with Vite
17 |
18 | ```bash
19 | npm create vite@latest my-app
20 | ✔ Select a framework: › React
21 | ✔ Select a variant: › JavaScript
22 | cd my-app
23 | npm install
24 | ```
25 |
26 | ### Step 2: Install Tailwindcss and Shadcn
27 |
28 | From instructions: https://ui.shadcn.com/docs/installation/vite
29 |
30 | ```bash
31 | npm install -D tailwindcss postcss autoprefixer
32 | npx tailwindcss init -p
33 | ```
34 |
35 | Update `vite.config.js`:
36 |
37 | ```javascript
38 | import { defineConfig } from 'vite'
39 | import react from '@vitejs/plugin-react'
40 | import path from 'path'
41 |
42 | export default defineConfig({
43 | plugins: [react()],
44 | resolve: {
45 | alias: {
46 | '@': path.resolve(__dirname, './src'),
47 | },
48 | },
49 | })
50 | ```
51 |
52 | Create `jsconfig.json`:
53 |
54 | ```json
55 | {
56 | "compilerOptions": {
57 | "baseUrl": ".",
58 | "paths": {
59 | "@/*": ["src/*"]
60 | }
61 | },
62 | "include": ["src/**/*"]
63 | }
64 | ```
65 |
66 | ```bash
67 | npx shadcn-ui@latest init
68 | ```
69 |
70 | ```
71 | ✔ Would you like to use TypeScript (recommended)? no
72 | ✔ Which style would you like to use? › Default
73 | ✔ Which color would you like to use as base color? › Slate
74 | ✔ Where is your global CSS file? … src/index.css
75 | ✔ Would you like to use CSS variables for colors? … yes
76 | ✔ Are you using a custom tailwind prefix eg. tw-? (Leave blank if not) …
77 | ✔ Where is your tailwind.config.js located? … tailwind.config.js
78 | ✔ Configure the import alias for components: … @/components
79 | ✔ Configure the import alias for utils: … @/lib/utils
80 | ✔ Are you using React Server Components? … no
81 | ✔ Write configuration to components.json. Proceed? … yes
82 | ```
83 |
84 | ### 3. Install Other Libraries and Components
85 | Choose your list of required components and libraries to download based upon the imports in your react file.
86 | ```bash
87 | npx shadcn-ui@latest add card button input
88 | npm install lucide-react
89 | ```
90 |
91 | ### 4. Add Your Artifact Code
92 |
93 | `LLMModel.jsx` is an included artifact example. You can move the file to `src/components/LLMModel.jsx`.
94 |
95 | Then add it to your app by updating `App.jsx`:
96 |
97 | ```jsx
98 | import './App.css'
99 | import LLMModel from './components/LLMModel'
100 |
101 | function App() {
102 | return (
103 | <>
104 |
105 | >
106 | )
107 | }
108 |
109 | export default App
110 | ```
111 |
112 | ### 5. Run the App
113 |
114 | ```bash
115 | npm run dev
116 | ```
117 |
118 | 
119 | Example App with LLMModel.jsx Online
--------------------------------------------------------------------------------
/assets/img/demo_img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bklieger/Claude-React-Jumpstart/ec7a179082892b92e97458fd9ba17fe3cb2f3323/assets/img/demo_img.png
--------------------------------------------------------------------------------
/my-app/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:react/recommended',
7 | 'plugin:react/jsx-runtime',
8 | 'plugin:react-hooks/recommended',
9 | ],
10 | ignorePatterns: ['dist', '.eslintrc.cjs'],
11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
12 | settings: { react: { version: '18.2' } },
13 | plugins: ['react-refresh'],
14 | rules: {
15 | 'react/jsx-no-target-blank': 'off',
16 | 'react-refresh/only-export-components': [
17 | 'warn',
18 | { allowConstantExport: true },
19 | ],
20 | },
21 | }
22 |
--------------------------------------------------------------------------------
/my-app/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/my-app/README.md:
--------------------------------------------------------------------------------
1 | # React + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
--------------------------------------------------------------------------------
/my-app/components.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://ui.shadcn.com/schema.json",
3 | "style": "default",
4 | "rsc": false,
5 | "tsx": false,
6 | "tailwind": {
7 | "config": "tailwind.config.js",
8 | "css": "src/index.css",
9 | "baseColor": "slate",
10 | "cssVariables": true,
11 | "prefix": ""
12 | },
13 | "aliases": {
14 | "components": "@/components",
15 | "utils": "@/lib/utils"
16 | }
17 | }
--------------------------------------------------------------------------------
/my-app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/my-app/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "paths": {
5 | "@/*": ["src/*"]
6 | }
7 | },
8 | "include": ["src/**/*"]
9 | }
--------------------------------------------------------------------------------
/my-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-app",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@radix-ui/react-slot": "^1.1.0",
14 | "class-variance-authority": "^0.7.0",
15 | "clsx": "^2.1.1",
16 | "lucide-react": "^0.396.0",
17 | "react": "^18.3.1",
18 | "react-dom": "^18.3.1",
19 | "tailwind-merge": "^2.3.0",
20 | "tailwindcss-animate": "^1.0.7"
21 | },
22 | "devDependencies": {
23 | "@types/react": "^18.3.3",
24 | "@types/react-dom": "^18.3.0",
25 | "@vitejs/plugin-react": "^4.3.1",
26 | "autoprefixer": "^10.4.19",
27 | "eslint": "^8.57.0",
28 | "eslint-plugin-react": "^7.34.2",
29 | "eslint-plugin-react-hooks": "^4.6.2",
30 | "eslint-plugin-react-refresh": "^0.4.7",
31 | "postcss": "^8.4.38",
32 | "tailwindcss": "^3.4.4",
33 | "vite": "^5.3.1"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/my-app/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/my-app/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/my-app/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | transition: filter 300ms;
13 | }
14 | .logo:hover {
15 | filter: drop-shadow(0 0 2em #646cffaa);
16 | }
17 | .logo.react:hover {
18 | filter: drop-shadow(0 0 2em #61dafbaa);
19 | }
20 |
21 | @keyframes logo-spin {
22 | from {
23 | transform: rotate(0deg);
24 | }
25 | to {
26 | transform: rotate(360deg);
27 | }
28 | }
29 |
30 | @media (prefers-reduced-motion: no-preference) {
31 | a:nth-of-type(2) .logo {
32 | animation: logo-spin infinite 20s linear;
33 | }
34 | }
35 |
36 | .card {
37 | padding: 2em;
38 | }
39 |
40 | .read-the-docs {
41 | color: #888;
42 | }
43 |
--------------------------------------------------------------------------------
/my-app/src/App.jsx:
--------------------------------------------------------------------------------
1 | import './App.css'
2 | import LLMModel from './components/LLMModel'
3 |
4 | function App() {
5 | return (
6 | <>
7 |
8 | >
9 | )
10 | }
11 |
12 | export default App
--------------------------------------------------------------------------------
/my-app/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/my-app/src/components/LLMModel.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
3 | import { Button } from "@/components/ui/button"
4 | import { Input } from "@/components/ui/input"
5 | import { Boxes, Cpu, Network, Lightbulb, ArrowRight } from 'lucide-react'
6 |
7 | const LLMModel = () => {
8 | const [input, setInput] = useState('');
9 | const [output, setOutput] = useState('');
10 | const [step, setStep] = useState(0);
11 |
12 | const steps = [
13 | {
14 | name: "Tokenization",
15 | icon: ,
16 | description: "The input text is broken down into tokens (words or subwords). This process converts the raw text into a format the model can understand.",
17 | example: input ? input.split(' ').map((word, i) => {word} ) : null
18 | },
19 | {
20 | name: "Embedding",
21 | icon: ,
22 | description: "Each token is converted into a numerical vector representation. This allows the model to process the text mathematically.",
23 | example:
24 | {input.split(' ').slice(0, 4).map((_, i) =>
25 |
26 | [0.2, -0.5, 0.8, ...]
27 |
28 | )}
29 |
30 | },
31 | {
32 | name: "Attention Mechanism",
33 | icon: ,
34 | description: "The model calculates attention scores to understand the relationships between different parts of the input.",
35 | example:
36 | {input.split(' ').slice(0, 4).map((word, i) =>
37 |
38 |
{word}
39 |
40 |
{(Math.random() * 0.5 + 0.5).toFixed(2)}
41 |
42 | )}
43 |
44 | },
45 | {
46 | name: "Feed Forward",
47 | icon: ,
48 | description: "The embedded and attention-weighted inputs are processed through multiple neural network layers.",
49 | example:
50 |
51 |
52 | },
53 | {
54 | name: "Output Generation",
55 | icon: ,
56 | description: "The model generates output tokens based on the processed input and the temperature setting.",
57 | example: output ? {output}
: null
58 | }
59 | ];
60 |
61 | const handleInputChange = (e) => {
62 | setInput(e.target.value);
63 | };
64 |
65 | const handleNextStep = () => {
66 | if (step < steps.length - 1) {
67 | setStep(step + 1);
68 | } else {
69 | setOutput(generateOutput(input));
70 | }
71 | };
72 |
73 | const handleReset = () => {
74 | setInput('');
75 | setOutput('');
76 | setStep(0);
77 | };
78 |
79 | const generateOutput = (input) => {
80 | // This is a simplified simulation of output generation
81 | const words = input.split(' ');
82 | const outputLength = Math.floor(Math.random() * 5) + words.length;
83 | let output = '';
84 | for (let i = 0; i < outputLength; i++) {
85 | output += words[Math.floor(Math.random() * words.length)] + ' ';
86 | }
87 | return output.trim();
88 | };
89 |
90 | return (
91 |
92 |
93 | Enhanced LLM Interactive Model
94 | Explore how LLMs process and generate text
95 |
96 |
97 |
98 |
99 | Input Text:
100 |
105 |
106 |
107 |
108 | {steps[step].icon}
109 |
{steps[step].name}
110 |
111 |
{steps[step].description}
112 |
113 | {steps[step].example}
114 |
115 |
116 |
117 |
118 |
119 |
120 | {step < steps.length - 1 ? 'Next Step' : 'Generate Output'}
121 |
122 | Reset
123 |
124 |
125 | );
126 | };
127 |
128 | export default LLMModel;
--------------------------------------------------------------------------------
/my-app/src/components/ui/button.jsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import { Slot } from "@radix-ui/react-slot"
3 | import { cva } from "class-variance-authority";
4 |
5 | import { cn } from "@/lib/utils"
6 |
7 | const buttonVariants = cva(
8 | "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",
9 | {
10 | variants: {
11 | variant: {
12 | default: "bg-primary text-primary-foreground hover:bg-primary/90",
13 | destructive:
14 | "bg-destructive text-destructive-foreground hover:bg-destructive/90",
15 | outline:
16 | "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
17 | secondary:
18 | "bg-secondary text-secondary-foreground hover:bg-secondary/80",
19 | ghost: "hover:bg-accent hover:text-accent-foreground",
20 | link: "text-primary underline-offset-4 hover:underline",
21 | },
22 | size: {
23 | default: "h-10 px-4 py-2",
24 | sm: "h-9 rounded-md px-3",
25 | lg: "h-11 rounded-md px-8",
26 | icon: "h-10 w-10",
27 | },
28 | },
29 | defaultVariants: {
30 | variant: "default",
31 | size: "default",
32 | },
33 | }
34 | )
35 |
36 | const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
37 | const Comp = asChild ? Slot : "button"
38 | return (
39 | ( )
43 | );
44 | })
45 | Button.displayName = "Button"
46 |
47 | export { Button, buttonVariants }
48 |
--------------------------------------------------------------------------------
/my-app/src/components/ui/card.jsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { cn } from "@/lib/utils"
4 |
5 | const Card = React.forwardRef(({ className, ...props }, ref) => (
6 |
10 | ))
11 | Card.displayName = "Card"
12 |
13 | const CardHeader = React.forwardRef(({ className, ...props }, ref) => (
14 |
18 | ))
19 | CardHeader.displayName = "CardHeader"
20 |
21 | const CardTitle = React.forwardRef(({ className, ...props }, ref) => (
22 |
26 | ))
27 | CardTitle.displayName = "CardTitle"
28 |
29 | const CardDescription = React.forwardRef(({ className, ...props }, ref) => (
30 |
34 | ))
35 | CardDescription.displayName = "CardDescription"
36 |
37 | const CardContent = React.forwardRef(({ className, ...props }, ref) => (
38 |
39 | ))
40 | CardContent.displayName = "CardContent"
41 |
42 | const CardFooter = React.forwardRef(({ className, ...props }, ref) => (
43 |
47 | ))
48 | CardFooter.displayName = "CardFooter"
49 |
50 | export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
51 |
--------------------------------------------------------------------------------
/my-app/src/components/ui/input.jsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { cn } from "@/lib/utils"
4 |
5 | const Input = React.forwardRef(({ className, type, ...props }, ref) => {
6 | return (
7 | ( )
15 | );
16 | })
17 | Input.displayName = "Input"
18 |
19 | export { Input }
20 |
--------------------------------------------------------------------------------
/my-app/src/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | @layer base {
6 | :root {
7 | --background: 0 0% 100%;
8 | --foreground: 222.2 84% 4.9%;
9 |
10 | --card: 0 0% 100%;
11 | --card-foreground: 222.2 84% 4.9%;
12 |
13 | --popover: 0 0% 100%;
14 | --popover-foreground: 222.2 84% 4.9%;
15 |
16 | --primary: 222.2 47.4% 11.2%;
17 | --primary-foreground: 210 40% 98%;
18 |
19 | --secondary: 210 40% 96.1%;
20 | --secondary-foreground: 222.2 47.4% 11.2%;
21 |
22 | --muted: 210 40% 96.1%;
23 | --muted-foreground: 215.4 16.3% 46.9%;
24 |
25 | --accent: 210 40% 96.1%;
26 | --accent-foreground: 222.2 47.4% 11.2%;
27 |
28 | --destructive: 0 84.2% 60.2%;
29 | --destructive-foreground: 210 40% 98%;
30 |
31 | --border: 214.3 31.8% 91.4%;
32 | --input: 214.3 31.8% 91.4%;
33 | --ring: 222.2 84% 4.9%;
34 |
35 | --radius: 0.5rem;
36 | }
37 |
38 | .dark {
39 | --background: 222.2 84% 4.9%;
40 | --foreground: 210 40% 98%;
41 |
42 | --card: 222.2 84% 4.9%;
43 | --card-foreground: 210 40% 98%;
44 |
45 | --popover: 222.2 84% 4.9%;
46 | --popover-foreground: 210 40% 98%;
47 |
48 | --primary: 210 40% 98%;
49 | --primary-foreground: 222.2 47.4% 11.2%;
50 |
51 | --secondary: 217.2 32.6% 17.5%;
52 | --secondary-foreground: 210 40% 98%;
53 |
54 | --muted: 217.2 32.6% 17.5%;
55 | --muted-foreground: 215 20.2% 65.1%;
56 |
57 | --accent: 217.2 32.6% 17.5%;
58 | --accent-foreground: 210 40% 98%;
59 |
60 | --destructive: 0 62.8% 30.6%;
61 | --destructive-foreground: 210 40% 98%;
62 |
63 | --border: 217.2 32.6% 17.5%;
64 | --input: 217.2 32.6% 17.5%;
65 | --ring: 212.7 26.8% 83.9%;
66 | }
67 | }
68 |
69 | @layer base {
70 | * {
71 | @apply border-border;
72 | }
73 | body {
74 | @apply bg-background text-foreground;
75 | }
76 | }
--------------------------------------------------------------------------------
/my-app/src/lib/utils.js:
--------------------------------------------------------------------------------
1 | import { clsx } from "clsx"
2 | import { twMerge } from "tailwind-merge"
3 |
4 | export function cn(...inputs) {
5 | return twMerge(clsx(inputs))
6 | }
7 |
--------------------------------------------------------------------------------
/my-app/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App.jsx'
4 | import './index.css'
5 |
6 | ReactDOM.createRoot(document.getElementById('root')).render(
7 |
8 |
9 | ,
10 | )
11 |
--------------------------------------------------------------------------------
/my-app/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | darkMode: ["class"],
4 | content: [
5 | './pages/**/*.{js,jsx}',
6 | './components/**/*.{js,jsx}',
7 | './app/**/*.{js,jsx}',
8 | './src/**/*.{js,jsx}',
9 | ],
10 | prefix: "",
11 | theme: {
12 | container: {
13 | center: true,
14 | padding: "2rem",
15 | screens: {
16 | "2xl": "1400px",
17 | },
18 | },
19 | extend: {
20 | colors: {
21 | border: "hsl(var(--border))",
22 | input: "hsl(var(--input))",
23 | ring: "hsl(var(--ring))",
24 | background: "hsl(var(--background))",
25 | foreground: "hsl(var(--foreground))",
26 | primary: {
27 | DEFAULT: "hsl(var(--primary))",
28 | foreground: "hsl(var(--primary-foreground))",
29 | },
30 | secondary: {
31 | DEFAULT: "hsl(var(--secondary))",
32 | foreground: "hsl(var(--secondary-foreground))",
33 | },
34 | destructive: {
35 | DEFAULT: "hsl(var(--destructive))",
36 | foreground: "hsl(var(--destructive-foreground))",
37 | },
38 | muted: {
39 | DEFAULT: "hsl(var(--muted))",
40 | foreground: "hsl(var(--muted-foreground))",
41 | },
42 | accent: {
43 | DEFAULT: "hsl(var(--accent))",
44 | foreground: "hsl(var(--accent-foreground))",
45 | },
46 | popover: {
47 | DEFAULT: "hsl(var(--popover))",
48 | foreground: "hsl(var(--popover-foreground))",
49 | },
50 | card: {
51 | DEFAULT: "hsl(var(--card))",
52 | foreground: "hsl(var(--card-foreground))",
53 | },
54 | },
55 | borderRadius: {
56 | lg: "var(--radius)",
57 | md: "calc(var(--radius) - 2px)",
58 | sm: "calc(var(--radius) - 4px)",
59 | },
60 | keyframes: {
61 | "accordion-down": {
62 | from: { height: "0" },
63 | to: { height: "var(--radix-accordion-content-height)" },
64 | },
65 | "accordion-up": {
66 | from: { height: "var(--radix-accordion-content-height)" },
67 | to: { height: "0" },
68 | },
69 | },
70 | animation: {
71 | "accordion-down": "accordion-down 0.2s ease-out",
72 | "accordion-up": "accordion-up 0.2s ease-out",
73 | },
74 | },
75 | },
76 | plugins: [require("tailwindcss-animate")],
77 | }
--------------------------------------------------------------------------------
/my-app/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 | import path from 'path'
4 |
5 | export default defineConfig({
6 | plugins: [react()],
7 | resolve: {
8 | alias: {
9 | '@': path.resolve(__dirname, './src'),
10 | },
11 | },
12 | })
--------------------------------------------------------------------------------