@launch77-shared/plugin-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,242 @@
1
+ # @launch77-shared/plugin-ui
2
+
3
+ Launch77 UI library plugin - Setup Radix UI component library with design system integration.
4
+
5
+ ## Overview
6
+
7
+ This plugin installs and configures the `@launch77-shared/lib-ui` component library in your Launch77 application. It automatically:
8
+
9
+ - ✅ Installs `@launch77-shared/lib-ui` package
10
+ - ✅ Configures Tailwind to include UI library components
11
+ - ✅ Verifies design system integration
12
+ - ✅ Provides interactive component showcase
13
+ - ✅ Includes comprehensive documentation
14
+
15
+ ## Requirements
16
+
17
+ - **Design System Plugin**: This plugin requires the `design-system` plugin to be installed first
18
+ - **Tailwind CSS**: Your application must have Tailwind CSS configured
19
+ - **Next.js**: Compatible with Next.js App Router applications
20
+
21
+ ## Installation
22
+
23
+ From your Launch77 application directory:
24
+
25
+ ```bash
26
+ launch77 plugin:install ui
27
+ ```
28
+
29
+ The plugin will automatically:
30
+
31
+ 1. Check for design-system plugin dependency
32
+ 2. Install `@launch77-shared/lib-ui` package
33
+ 3. Update `tailwind.config.ts` to include UI library in content paths
34
+ 4. Copy example pages and documentation to your app
35
+
36
+ ## What Gets Installed
37
+
38
+ ### Package Dependencies
39
+
40
+ - `@launch77-shared/lib-ui` - UI component library
41
+
42
+ ### Configuration Changes
43
+
44
+ **tailwind.config.ts**
45
+
46
+ - Adds `node_modules/@launch77-shared/lib-ui/dist/**/*.js` to content array
47
+ - Ensures Tailwind processes UI component styles
48
+
49
+ ### Template Files
50
+
51
+ ```
52
+ src/
53
+ ├── app/
54
+ │ └── ui-examples/
55
+ │ └── page.tsx # Interactive component showcase
56
+ └── modules/
57
+ └── ui/
58
+ ├── README.md # Component documentation
59
+ └── index.ts # Convenience re-exports
60
+ ```
61
+
62
+ ## Usage
63
+
64
+ ### Importing Components
65
+
66
+ ```tsx
67
+ // Direct import from library
68
+ import { Button, Input, Card } from '@launch77-shared/lib-ui'
69
+
70
+ // Or from module re-exports
71
+ import { Button, Input, Card } from '@/modules/ui'
72
+
73
+ export default function MyComponent() {
74
+ return (
75
+ <Card className="p-6">
76
+ <h2>Hello World</h2>
77
+ <Input placeholder="Enter text..." />
78
+ <Button>Submit</Button>
79
+ </Card>
80
+ )
81
+ }
82
+ ```
83
+
84
+ ### Available Components
85
+
86
+ - **Form Controls**: Button, Input, Textarea, Select, Checkbox, Switch
87
+ - **Layout**: Card, Sidebar
88
+ - **Feedback**: Alert, Badge, Dialog
89
+ - **Display**: Avatar
90
+ - **Form Utilities**: FormField, FormError, FormHelperText
91
+
92
+ ### Component Showcase
93
+
94
+ Visit the interactive showcase to explore all components:
95
+
96
+ ```bash
97
+ npm run dev
98
+ # Navigate to http://localhost:3000/ui-examples
99
+ ```
100
+
101
+ ## Documentation
102
+
103
+ After installation, view detailed component documentation at:
104
+
105
+ - `src/modules/ui/README.md` - Full API reference and examples
106
+ - `/ui-examples` - Live interactive examples
107
+
108
+ ## Architecture
109
+
110
+ ### How It Works
111
+
112
+ 1. **Plugin Dependencies**: Declares `design-system` as a required plugin
113
+ 2. **Package Installation**: Adds `@launch77-shared/lib-ui` to your `package.json`
114
+ 3. **Tailwind Integration**: Updates content paths so Tailwind processes component styles
115
+ 4. **Template Copy**: Copies example pages and documentation to your app
116
+
117
+ ### Generator Logic
118
+
119
+ The plugin's generator ([src/generator.ts](./src/generator.ts)) extends `StandardGenerator` and:
120
+
121
+ 1. **`updateDependencies()`** - Merges library dependencies into your package.json
122
+ 2. **`installDependencies()`** - Runs `npm install` to fetch packages
123
+ 3. **`copyTemplates()`** - Copies example and documentation files
124
+ 4. **`injectCode()`** - Updates Tailwind config with UI library content path
125
+ 5. **`showNextSteps()`** - Displays usage instructions
126
+
127
+ ## Customization
128
+
129
+ ### Styling Components
130
+
131
+ All components support Tailwind utility classes via `className` prop:
132
+
133
+ ```tsx
134
+ <Button className="w-full bg-purple-600 hover:bg-purple-700">Custom Button</Button>
135
+ ```
136
+
137
+ ### Brand Customization
138
+
139
+ Customize the design system tokens that affect all UI components:
140
+
141
+ ```css
142
+ /* src/modules/design-system/config/brand.css */
143
+ :root {
144
+ --primary: 220 90% 56%;
145
+ --secondary: 240 5% 26%;
146
+ /* ... more tokens */
147
+ }
148
+ ```
149
+
150
+ ### Extending Components
151
+
152
+ Create custom variants by wrapping base components:
153
+
154
+ ```tsx
155
+ // src/components/PrimaryButton.tsx
156
+ import { Button } from '@launch77-shared/lib-ui'
157
+
158
+ export function PrimaryButton(props) {
159
+ return <Button className="bg-gradient-to-r from-blue-600 to-purple-600" {...props} />
160
+ }
161
+ ```
162
+
163
+ ## Troubleshooting
164
+
165
+ ### Styles Not Appearing
166
+
167
+ If component styles aren't applying:
168
+
169
+ 1. **Check Tailwind Config**: Verify `tailwind.config.ts` includes:
170
+
171
+ ```ts
172
+ content: [
173
+ // ... other paths
174
+ 'node_modules/@launch77-shared/lib-ui/dist/**/*.js',
175
+ ]
176
+ ```
177
+
178
+ 2. **Rebuild**: Restart your dev server:
179
+
180
+ ```bash
181
+ npm run dev
182
+ ```
183
+
184
+ 3. **Design System**: Ensure design-system plugin is installed:
185
+ ```bash
186
+ launch77 plugin:install design-system
187
+ ```
188
+
189
+ ### TypeScript Errors
190
+
191
+ If you see TypeScript errors importing components:
192
+
193
+ 1. **Install Dependencies**:
194
+
195
+ ```bash
196
+ npm install
197
+ ```
198
+
199
+ 2. **Check Package**: Verify `@launch77-shared/lib-ui` is in your `package.json`
200
+
201
+ ### Missing Components
202
+
203
+ If example page shows missing components:
204
+
205
+ 1. **Verify Installation**: Check `node_modules/@launch77-shared/lib-ui` exists
206
+ 2. **Reinstall Plugin**:
207
+ ```bash
208
+ launch77 plugin:install ui
209
+ ```
210
+
211
+ ## Development
212
+
213
+ ### Building the Plugin
214
+
215
+ ```bash
216
+ cd plugins/ui
217
+ npm run build
218
+ ```
219
+
220
+ ### Testing Locally
221
+
222
+ ```bash
223
+ # In your app directory
224
+ launch77 plugin:install ui
225
+ ```
226
+
227
+ ## Related Plugins
228
+
229
+ - **design-system** (required) - Provides design tokens and Tailwind preset
230
+ - **analytics-web** - Track user interactions with UI components
231
+
232
+ ## License
233
+
234
+ UNLICENSED - Internal use only
235
+
236
+ ## Support
237
+
238
+ For issues or questions:
239
+
240
+ 1. Check `src/modules/ui/README.md` for component documentation
241
+ 2. Review design system at `/design-system-test`
242
+ 3. Open an issue in the Launch77 CLI repository
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/generator.ts
4
+ import * as path from "path";
5
+ import chalk from "chalk";
6
+ import { StandardGenerator } from "@launch77/plugin-runtime";
7
+
8
+ // src/utils/config-modifier.ts
9
+ import fs from "fs/promises";
10
+ async function addTailwindContent(filePath, contentPath) {
11
+ try {
12
+ const fileExists = await fs.access(filePath).then(() => true).catch(() => false);
13
+ if (!fileExists) {
14
+ return {
15
+ success: false,
16
+ error: `File not found: ${filePath}`
17
+ };
18
+ }
19
+ const content = await fs.readFile(filePath, "utf-8");
20
+ if (content.includes(contentPath)) {
21
+ return {
22
+ success: true,
23
+ alreadyExists: true
24
+ };
25
+ }
26
+ const lines = content.split("\n");
27
+ let contentArrayStartIndex = -1;
28
+ let contentArrayEndIndex = -1;
29
+ for (let i = 0; i < lines.length; i++) {
30
+ const line = lines[i];
31
+ if (line.includes("content:") && line.includes("[")) {
32
+ contentArrayStartIndex = i;
33
+ if (line.includes("]")) {
34
+ contentArrayEndIndex = i;
35
+ break;
36
+ }
37
+ for (let j = i + 1; j < lines.length; j++) {
38
+ if (lines[j].includes("]")) {
39
+ contentArrayEndIndex = j;
40
+ break;
41
+ }
42
+ }
43
+ break;
44
+ }
45
+ }
46
+ if (contentArrayStartIndex === -1) {
47
+ return {
48
+ success: false,
49
+ error: "Could not find content array in Tailwind config"
50
+ };
51
+ }
52
+ let indentation = " ";
53
+ for (let i = contentArrayStartIndex + 1; i < contentArrayEndIndex; i++) {
54
+ const match = lines[i].match(/^(\s+)['"]/);
55
+ if (match) {
56
+ indentation = match[1];
57
+ break;
58
+ }
59
+ }
60
+ const newLine = `${indentation}'${contentPath}',`;
61
+ lines.splice(contentArrayEndIndex, 0, newLine);
62
+ const newContent = lines.join("\n");
63
+ await fs.writeFile(filePath, newContent, "utf-8");
64
+ return {
65
+ success: true
66
+ };
67
+ } catch (error) {
68
+ return {
69
+ success: false,
70
+ error: error instanceof Error ? error.message : String(error)
71
+ };
72
+ }
73
+ }
74
+
75
+ // src/generator.ts
76
+ var UiGenerator = class extends StandardGenerator {
77
+ constructor(context) {
78
+ super(context);
79
+ }
80
+ async injectCode() {
81
+ console.log(chalk.cyan("\u{1F527} Setting up UI library...\n"));
82
+ await this.updateTailwindConfig();
83
+ }
84
+ async updateTailwindConfig() {
85
+ const tailwindConfigPath = path.join(this.context.appPath, "tailwind.config.ts");
86
+ const result1 = await addTailwindContent(tailwindConfigPath, "node_modules/@launch77-shared/lib-ui/dist/**/*.js");
87
+ const result2 = await addTailwindContent(tailwindConfigPath, "../../node_modules/@launch77-shared/lib-ui/dist/**/*.js");
88
+ if (result1.success || result2.success) {
89
+ if (result1.alreadyExists && result2.alreadyExists) {
90
+ console.log(chalk.gray(" \u2713 UI library already configured in tailwind.config.ts"));
91
+ } else {
92
+ console.log(chalk.green(" \u2713 Added UI library to Tailwind content paths"));
93
+ }
94
+ } else {
95
+ console.log(chalk.yellow(` \u26A0\uFE0F Could not auto-configure tailwind.config.ts: ${result1.error}`));
96
+ console.log(chalk.gray(" You will need to add the content paths manually:"));
97
+ console.log(chalk.gray(" 'node_modules/@launch77-shared/lib-ui/dist/**/*.js'"));
98
+ console.log(chalk.gray(" '../../node_modules/@launch77-shared/lib-ui/dist/**/*.js'"));
99
+ }
100
+ }
101
+ showNextSteps() {
102
+ console.log(chalk.bold.green("\n\u2705 Plugin installed successfully!\n"));
103
+ console.log(chalk.bold("Next Steps:\n"));
104
+ console.log("1. Explore components:");
105
+ console.log(chalk.cyan(" Visit http://localhost:3000/ui-examples\n"));
106
+ console.log("2. Import components in your code:");
107
+ console.log(chalk.cyan(" import { Button, Input, Card } from '@launch77-shared/lib-ui'\n"));
108
+ console.log("3. View documentation:");
109
+ console.log(chalk.cyan(" See src/modules/ui/README.md\n"));
110
+ }
111
+ };
112
+ async function main() {
113
+ const args = process.argv.slice(2);
114
+ const appPath = args.find((arg) => arg.startsWith("--appPath="))?.split("=")[1];
115
+ const appName = args.find((arg) => arg.startsWith("--appName="))?.split("=")[1];
116
+ const workspaceName = args.find((arg) => arg.startsWith("--workspaceName="))?.split("=")[1];
117
+ const pluginPath = args.find((arg) => arg.startsWith("--pluginPath="))?.split("=")[1];
118
+ if (!appPath || !appName || !workspaceName || !pluginPath) {
119
+ console.error(chalk.red("Error: Missing required arguments"));
120
+ console.error("Usage: generate --appPath=<path> --appName=<name> --workspaceName=<workspace> --pluginPath=<path>");
121
+ process.exit(1);
122
+ }
123
+ const generator = new UiGenerator({ appPath, appName, workspaceName, pluginPath });
124
+ await generator.run();
125
+ }
126
+ if (import.meta.url === `file://${process.argv[1]}`) {
127
+ main().catch((error) => {
128
+ console.error(chalk.red("\n\u274C Error during UI library setup:"));
129
+ console.error(error);
130
+ process.exit(1);
131
+ });
132
+ }
133
+ export {
134
+ UiGenerator
135
+ };
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@launch77-shared/plugin-ui",
3
+ "version": "0.1.0",
4
+ "description": "Launch77 UI library plugin - Setup Radix UI component library with design system integration",
5
+ "license": "UNLICENSED",
6
+ "type": "module",
7
+ "main": "dist/generator.js",
8
+ "bin": {
9
+ "generate": "./dist/generator.js"
10
+ },
11
+ "files": [
12
+ "dist/",
13
+ "templates/",
14
+ "plugin.json"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsup",
18
+ "dev": "tsup --watch",
19
+ "typecheck": "tsc --noEmit",
20
+ "lint": "eslint src/**/*.ts",
21
+ "release:connect": "launch77-release-connect",
22
+ "release:verify": "launch77-release-verify"
23
+ },
24
+ "dependencies": {
25
+ "@launch77/plugin-runtime": "^0.3.0",
26
+ "@launch77-shared/lib-ui": "^0.1.0",
27
+ "chalk": "^5.3.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^20.10.0",
31
+ "tsup": "^8.0.0",
32
+ "typescript": "^5.3.0"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "launch77": {
38
+ "installedPlugins": {
39
+ "release": {
40
+ "package": "release",
41
+ "version": "1.0.1",
42
+ "installedAt": "2026-01-26T00:47:19.303Z",
43
+ "source": "local"
44
+ }
45
+ }
46
+ }
47
+ }
package/plugin.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "targets": ["app"],
3
+ "pluginDependencies": {
4
+ "design-system": "^2.1.0"
5
+ },
6
+ "libraryDependencies": {
7
+ "@launch77-shared/lib-ui": "^0.1.0"
8
+ }
9
+ }
@@ -0,0 +1,241 @@
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import { Alert, Avatar, Badge, Button, Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, Checkbox, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, FormField, FormHelperText, FormError, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Switch, Textarea } from '@launch77-shared/lib-ui'
5
+
6
+ export default function UiExamplesPage() {
7
+ const [checked, setChecked] = useState(false)
8
+ const [termsAccepted, setTermsAccepted] = useState(false)
9
+ const [termsError, setTermsError] = useState(false)
10
+ const [switchEnabled, setSwitchEnabled] = useState(false)
11
+ const [selectedValue, setSelectedValue] = useState('')
12
+ const [textareaValue, setTextareaValue] = useState('')
13
+ const [textareaError, setTextareaError] = useState(false)
14
+
15
+ return (
16
+ <div className="container mx-auto max-w-6xl py-12 px-4">
17
+ <div className="mb-12">
18
+ <h1 className="text-4xl font-bold mb-4">UI Component Library</h1>
19
+ <p className="text-muted-foreground text-lg">Explore the Launch77 UI component library built with Radix UI primitives</p>
20
+ </div>
21
+
22
+ <div className="space-y-12">
23
+ {/* Buttons */}
24
+ <section>
25
+ <h2 className="text-2xl font-semibold mb-6">Buttons</h2>
26
+ <div className="flex flex-wrap gap-4">
27
+ <Button>Default Button</Button>
28
+ <Button variant="secondary">Secondary</Button>
29
+ <Button variant="outline">Outline</Button>
30
+ <Button variant="ghost">Ghost</Button>
31
+ <Button variant="destructive">Destructive</Button>
32
+ <Button size="sm">Small</Button>
33
+ <Button size="lg">Large</Button>
34
+ <Button disabled>Disabled</Button>
35
+ </div>
36
+ </section>
37
+
38
+ {/* Inputs */}
39
+ <section>
40
+ <h2 className="text-2xl font-semibold mb-6">Form Controls</h2>
41
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-4xl">
42
+ <FormField label="Email Address" helperText="We'll never share your email" htmlFor="input-1">
43
+ <Input id="input-1" type="email" placeholder="Enter your email..." />
44
+ </FormField>
45
+
46
+ <FormField label="Password" error="Password must be at least 8 characters" required htmlFor="input-2">
47
+ <Input id="input-2" type="password" placeholder="Enter password..." />
48
+ </FormField>
49
+
50
+ <FormField label="Message" helperText="Enter a brief message (max 200 characters)" htmlFor="textarea">
51
+ <Textarea
52
+ id="textarea"
53
+ placeholder="Enter your message..."
54
+ rows={4}
55
+ value={textareaValue}
56
+ onChange={(e) => {
57
+ setTextareaValue(e.target.value)
58
+ setTextareaError(e.target.value.length > 200)
59
+ }}
60
+ error={textareaError}
61
+ />
62
+ </FormField>
63
+
64
+ <FormField label="Country" htmlFor="select" required>
65
+ <Select value={selectedValue} onValueChange={setSelectedValue}>
66
+ <SelectTrigger id="select">
67
+ <SelectValue placeholder="Choose a country" />
68
+ </SelectTrigger>
69
+ <SelectContent>
70
+ <SelectItem value="us">United States</SelectItem>
71
+ <SelectItem value="ca">Canada</SelectItem>
72
+ <SelectItem value="uk">United Kingdom</SelectItem>
73
+ </SelectContent>
74
+ </Select>
75
+ </FormField>
76
+ </div>
77
+ </section>
78
+
79
+ {/* Checkbox & Switch */}
80
+ <section>
81
+ <h2 className="text-2xl font-semibold mb-6">Toggle Controls</h2>
82
+ <div className="space-y-4">
83
+ <div className="flex items-center gap-3">
84
+ <Checkbox id="checkbox-example" checked={checked} onCheckedChange={(value) => setChecked(value as boolean)} />
85
+ <label htmlFor="checkbox-example" className="cursor-pointer">
86
+ Checkbox example
87
+ </label>
88
+ </div>
89
+
90
+ <div className="space-y-2">
91
+ <div className="flex items-center gap-3">
92
+ <Checkbox
93
+ id="terms-checkbox"
94
+ checked={termsAccepted}
95
+ onCheckedChange={(value) => {
96
+ setTermsAccepted(value as boolean)
97
+ setTermsError(false)
98
+ }}
99
+ error={termsError}
100
+ />
101
+ <label htmlFor="terms-checkbox" className="cursor-pointer">
102
+ I accept the terms and conditions (required)
103
+ </label>
104
+ </div>
105
+ {termsError && <FormError>You must accept the terms to continue</FormError>}
106
+ <Button
107
+ size="sm"
108
+ onClick={() => {
109
+ if (!termsAccepted) {
110
+ setTermsError(true)
111
+ }
112
+ }}
113
+ >
114
+ Test Validation
115
+ </Button>
116
+ </div>
117
+
118
+ <div className="flex items-center gap-3">
119
+ <Switch id="switch-example" checked={switchEnabled} onCheckedChange={setSwitchEnabled} />
120
+ <label htmlFor="switch-example" className="cursor-pointer">
121
+ Enable notifications
122
+ </label>
123
+ </div>
124
+ </div>
125
+ </section>
126
+
127
+ {/* Cards */}
128
+ <section>
129
+ <h2 className="text-2xl font-semibold mb-6">Cards</h2>
130
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
131
+ <Card>
132
+ <CardHeader>
133
+ <CardTitle>Simple Card</CardTitle>
134
+ <CardDescription>A basic card with header and content</CardDescription>
135
+ </CardHeader>
136
+ <CardContent>
137
+ <p className="text-sm text-muted-foreground">This is the main content area of the card.</p>
138
+ </CardContent>
139
+ </Card>
140
+
141
+ <Card>
142
+ <CardHeader>
143
+ <CardTitle>Card with Action</CardTitle>
144
+ <CardDescription>Cards can have footers with actions</CardDescription>
145
+ </CardHeader>
146
+ <CardContent>
147
+ <p className="text-sm text-muted-foreground">Use CardFooter for action buttons.</p>
148
+ </CardContent>
149
+ <CardFooter>
150
+ <Button size="sm">View Details</Button>
151
+ </CardFooter>
152
+ </Card>
153
+
154
+ <Card>
155
+ <CardHeader>
156
+ <CardTitle>Interactive Card</CardTitle>
157
+ <CardDescription>Multiple actions in footer</CardDescription>
158
+ </CardHeader>
159
+ <CardContent>
160
+ <p className="text-sm text-muted-foreground">Cards support multiple action buttons.</p>
161
+ </CardContent>
162
+ <CardFooter className="flex gap-2">
163
+ <Button size="sm" variant="outline">
164
+ Cancel
165
+ </Button>
166
+ <Button size="sm">Confirm</Button>
167
+ </CardFooter>
168
+ </Card>
169
+ </div>
170
+ </section>
171
+
172
+ {/* Alerts */}
173
+ <section>
174
+ <h2 className="text-2xl font-semibold mb-6">Alerts</h2>
175
+ <div className="space-y-4 max-w-2xl">
176
+ <Alert title="Information">This is a default alert with some information.</Alert>
177
+
178
+ <Alert variant="success" title="Success!">
179
+ Your changes have been saved successfully.
180
+ </Alert>
181
+
182
+ <Alert variant="warning" title="Warning">
183
+ Please review your information before proceeding.
184
+ </Alert>
185
+
186
+ <Alert variant="error" title="Error">
187
+ Something went wrong. Please try again.
188
+ </Alert>
189
+ </div>
190
+ </section>
191
+
192
+ {/* Badges */}
193
+ <section>
194
+ <h2 className="text-2xl font-semibold mb-6">Badges</h2>
195
+ <div className="flex flex-wrap gap-4">
196
+ <Badge>Default</Badge>
197
+ <Badge variant="secondary">Secondary</Badge>
198
+ <Badge variant="success">Success</Badge>
199
+ <Badge variant="warning">Warning</Badge>
200
+ <Badge variant="error">Error</Badge>
201
+ <Badge variant="outline">Outline</Badge>
202
+ </div>
203
+ </section>
204
+
205
+ {/* Avatar */}
206
+ <section>
207
+ <h2 className="text-2xl font-semibold mb-6">Avatars</h2>
208
+ <div className="flex flex-wrap gap-4 items-center">
209
+ <Avatar src="https://i.pravatar.cc/150?img=1" alt="User 1" />
210
+ <Avatar src="https://i.pravatar.cc/150?img=2" alt="User 2" size="lg" />
211
+ <Avatar fallback="JD" />
212
+ <Avatar fallback="AB" size="sm" />
213
+ </div>
214
+ </section>
215
+
216
+ {/* Dialog */}
217
+ <section>
218
+ <h2 className="text-2xl font-semibold mb-6">Dialog</h2>
219
+ <Dialog>
220
+ <DialogTrigger asChild>
221
+ <Button>Open Dialog</Button>
222
+ </DialogTrigger>
223
+ <DialogContent>
224
+ <DialogHeader>
225
+ <DialogTitle>Dialog Example</DialogTitle>
226
+ <DialogDescription>This is a modal dialog built with Radix UI Dialog primitive.</DialogDescription>
227
+ </DialogHeader>
228
+ <div className="py-4">
229
+ <p className="text-sm text-muted-foreground">Dialogs are great for getting user attention and requiring action before continuing.</p>
230
+ </div>
231
+ <DialogFooter>
232
+ <Button variant="outline">Cancel</Button>
233
+ <Button>Confirm</Button>
234
+ </DialogFooter>
235
+ </DialogContent>
236
+ </Dialog>
237
+ </section>
238
+ </div>
239
+ </div>
240
+ )
241
+ }
@@ -0,0 +1,229 @@
1
+ # UI Component Library
2
+
3
+ This module provides access to the Launch77 UI component library built with Radix UI primitives and integrated with the design system.
4
+
5
+ ## Available Components
6
+
7
+ ### Form Controls
8
+
9
+ - **Button** - Primary action buttons with multiple variants
10
+ - **Input** - Text input fields
11
+ - **Textarea** - Multi-line text input
12
+ - **Select** - Dropdown selection
13
+ - **Checkbox** - Toggle checkboxes
14
+ - **Switch** - Toggle switches
15
+ - **FormField** - Form field wrapper
16
+ - **FormHelperText** - Helper text for form fields
17
+ - **FormError** - Error messages for form fields
18
+
19
+ ### Layout & Display
20
+
21
+ - **Card** - Container component for content sections
22
+ - **Alert** - Alert messages with variants (success, warning, error)
23
+ - **Badge** - Small status indicators
24
+ - **Avatar** - User avatar images with fallbacks
25
+ - **Dialog** - Modal dialogs
26
+ - **Sidebar** - Navigation sidebar layout
27
+
28
+ ## Usage Examples
29
+
30
+ ### Basic Button
31
+
32
+ ```tsx
33
+ import { Button } from '@launch77-shared/lib-ui'
34
+
35
+ export default function MyComponent() {
36
+ return <Button onClick={() => console.log('clicked')}>Click me</Button>
37
+ }
38
+ ```
39
+
40
+ ### Button Variants
41
+
42
+ ```tsx
43
+ <Button variant="default">Default</Button>
44
+ <Button variant="secondary">Secondary</Button>
45
+ <Button variant="outline">Outline</Button>
46
+ <Button variant="ghost">Ghost</Button>
47
+ <Button variant="destructive">Destructive</Button>
48
+ ```
49
+
50
+ ### Form Field with Validation
51
+
52
+ ```tsx
53
+ import { Input, FormField } from '@launch77-shared/lib-ui'
54
+
55
+ export default function MyForm() {
56
+ const [email, setEmail] = useState('')
57
+ const [error, setError] = useState('')
58
+
59
+ return (
60
+ <FormField label="Email Address" error={error} helperText="We'll never share your email" required htmlFor="email">
61
+ <Input id="email" type="email" placeholder="Enter your email" value={email} onChange={(e) => setEmail(e.target.value)} />
62
+ </FormField>
63
+ )
64
+ }
65
+ ```
66
+
67
+ ### Select Dropdown
68
+
69
+ ```tsx
70
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@launch77-shared/lib-ui'
71
+
72
+ export default function MySelect() {
73
+ const [value, setValue] = useState('')
74
+
75
+ return (
76
+ <Select value={value} onValueChange={setValue}>
77
+ <SelectTrigger>
78
+ <SelectValue placeholder="Choose an option" />
79
+ </SelectTrigger>
80
+ <SelectContent>
81
+ <SelectItem value="option1">Option 1</SelectItem>
82
+ <SelectItem value="option2">Option 2</SelectItem>
83
+ <SelectItem value="option3">Option 3</SelectItem>
84
+ </SelectContent>
85
+ </Select>
86
+ )
87
+ }
88
+ ```
89
+
90
+ ### Dialog Modal
91
+
92
+ ```tsx
93
+ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, Button } from '@launch77-shared/lib-ui'
94
+
95
+ export default function MyDialog() {
96
+ return (
97
+ <Dialog>
98
+ <DialogTrigger asChild>
99
+ <Button>Open Dialog</Button>
100
+ </DialogTrigger>
101
+ <DialogContent>
102
+ <DialogHeader>
103
+ <DialogTitle>Confirm Action</DialogTitle>
104
+ <DialogDescription>Are you sure you want to continue?</DialogDescription>
105
+ </DialogHeader>
106
+ <DialogFooter>
107
+ <Button variant="outline">Cancel</Button>
108
+ <Button>Confirm</Button>
109
+ </DialogFooter>
110
+ </DialogContent>
111
+ </Dialog>
112
+ )
113
+ }
114
+ ```
115
+
116
+ ### Card Layout
117
+
118
+ ```tsx
119
+ import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, Button } from '@launch77-shared/lib-ui'
120
+
121
+ export default function MyCard() {
122
+ return (
123
+ <Card>
124
+ <CardHeader>
125
+ <CardTitle>Card Title</CardTitle>
126
+ <CardDescription>Optional description text</CardDescription>
127
+ </CardHeader>
128
+ <CardContent>
129
+ <p>Card content goes here.</p>
130
+ </CardContent>
131
+ <CardFooter>
132
+ <Button>Action</Button>
133
+ </CardFooter>
134
+ </Card>
135
+ )
136
+ }
137
+ ```
138
+
139
+ ### Alerts
140
+
141
+ ```tsx
142
+ import { Alert } from '@launch77-shared/lib-ui'
143
+
144
+ export default function MyAlerts() {
145
+ return (
146
+ <>
147
+ <Alert variant="success" title="Success!">
148
+ Operation completed successfully.
149
+ </Alert>
150
+
151
+ <Alert variant="error" title="Error">
152
+ Something went wrong.
153
+ </Alert>
154
+ </>
155
+ )
156
+ }
157
+ ```
158
+
159
+ ### Checkbox & Switch
160
+
161
+ ```tsx
162
+ import { Checkbox, Switch, FormError } from '@launch77-shared/lib-ui'
163
+
164
+ export default function MyToggles() {
165
+ const [checked, setChecked] = useState(false)
166
+ const [termsAccepted, setTermsAccepted] = useState(false)
167
+ const [termsError, setTermsError] = useState(false)
168
+ const [enabled, setEnabled] = useState(false)
169
+
170
+ return (
171
+ <>
172
+ <div className="flex items-center gap-2">
173
+ <Checkbox id="terms" checked={checked} onCheckedChange={(value) => setChecked(value as boolean)} />
174
+ <label htmlFor="terms">Accept terms</label>
175
+ </div>
176
+
177
+ {/* Checkbox with error state */}
178
+ <div className="space-y-2">
179
+ <div className="flex items-center gap-2">
180
+ <Checkbox
181
+ id="terms-required"
182
+ checked={termsAccepted}
183
+ onCheckedChange={(value) => {
184
+ setTermsAccepted(value as boolean)
185
+ setTermsError(false)
186
+ }}
187
+ error={termsError}
188
+ />
189
+ <label htmlFor="terms-required">I accept the terms (required)</label>
190
+ </div>
191
+ {termsError && <FormError>You must accept the terms</FormError>}
192
+ </div>
193
+
194
+ <div className="flex items-center gap-2">
195
+ <Switch id="notifications" checked={enabled} onCheckedChange={setEnabled} />
196
+ <label htmlFor="notifications">Enable notifications</label>
197
+ </div>
198
+ </>
199
+ )
200
+ }
201
+ ```
202
+
203
+ ## Styling
204
+
205
+ All components are styled using Tailwind CSS and the Launch77 design system tokens. You can customize component appearance using:
206
+
207
+ - **Tailwind classes** - Apply utility classes via `className` prop
208
+ - **Design tokens** - Use CSS variables from the design system
209
+ - **Brand customization** - Edit `src/modules/design-system/config/brand.css`
210
+
211
+ ## Live Examples
212
+
213
+ Visit [http://localhost:3000/ui-examples](http://localhost:3000/ui-examples) to see all components in action.
214
+
215
+ ## Documentation
216
+
217
+ For detailed component API documentation and advanced usage, refer to the Radix UI documentation:
218
+
219
+ - [Radix UI Primitives](https://www.radix-ui.com/primitives/docs/overview/introduction)
220
+
221
+ ## Utility Functions
222
+
223
+ The library also exports the `cn` utility function for merging Tailwind classes:
224
+
225
+ ```tsx
226
+ import { cn } from '@launch77-shared/lib-ui'
227
+
228
+ const className = cn('base-class', condition && 'conditional-class', 'another-class')
229
+ ```
@@ -0,0 +1,14 @@
1
+ /**
2
+ * UI Component Library
3
+ *
4
+ * Re-exports all components from @launch77-shared/lib-ui
5
+ * for convenient importing throughout the application.
6
+ *
7
+ * Usage:
8
+ * import { Button, Input, Card } from '@/modules/ui'
9
+ *
10
+ * Or import directly from the library:
11
+ * import { Button, Input, Card } from '@launch77-shared/lib-ui'
12
+ */
13
+
14
+ export * from '@launch77-shared/lib-ui'