modula-ui 1.0.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.
Files changed (66) hide show
  1. package/README.md +36 -0
  2. package/bin/run.js +86 -0
  3. package/package.json +71 -0
  4. package/public/avatars/avatar1.png +0 -0
  5. package/public/avatars/avatar2.png +0 -0
  6. package/public/avatars/avatar3.png +0 -0
  7. package/public/avatars/avatar4.png +0 -0
  8. package/public/avatars/sources.md +34 -0
  9. package/public/file.svg +1 -0
  10. package/public/globe.svg +1 -0
  11. package/public/next.svg +1 -0
  12. package/public/vercel.svg +1 -0
  13. package/public/window.svg +1 -0
  14. package/registry.json +12 -0
  15. package/src/app/favicon.ico +0 -0
  16. package/src/app/globals.css +126 -0
  17. package/src/app/layout.js +29 -0
  18. package/src/app/page.js +50 -0
  19. package/src/app/patterns/page.js +50 -0
  20. package/src/components/CodeCard.jsx +16 -0
  21. package/src/components/CopyButton.jsx +31 -0
  22. package/src/components/Header.jsx +24 -0
  23. package/src/components/Logo.jsx +64 -0
  24. package/src/components/MobileOverlay.jsx +10 -0
  25. package/src/components/PreviewCard.jsx +98 -0
  26. package/src/components/Sidebar.jsx +47 -0
  27. package/src/components/ui/avatar.jsx +47 -0
  28. package/src/components/ui/badge.jsx +44 -0
  29. package/src/components/ui/button.jsx +56 -0
  30. package/src/components/ui/calendar.jsx +178 -0
  31. package/src/components/ui/card.jsx +101 -0
  32. package/src/components/ui/chart.jsx +314 -0
  33. package/src/components/ui/checkbox.jsx +30 -0
  34. package/src/components/ui/dropdown-menu.jsx +223 -0
  35. package/src/components/ui/input.jsx +24 -0
  36. package/src/components/ui/navigation-menu.jsx +152 -0
  37. package/src/components/ui/popover.jsx +47 -0
  38. package/src/components/ui/progress.jsx +29 -0
  39. package/src/components/ui/scroll-area.jsx +51 -0
  40. package/src/components/ui/select.jsx +168 -0
  41. package/src/components/ui/separator.jsx +27 -0
  42. package/src/components/ui/sheet.jsx +140 -0
  43. package/src/components/ui/sidebar.jsx +682 -0
  44. package/src/components/ui/skeleton.jsx +15 -0
  45. package/src/components/ui/slider.jsx +56 -0
  46. package/src/components/ui/tooltip.jsx +55 -0
  47. package/src/data/componentData.js +12 -0
  48. package/src/hooks/use-mobile.js +19 -0
  49. package/src/lib/utils.js +6 -0
  50. package/src/library/components/Alert.jsx +27 -0
  51. package/src/library/components/Badge.jsx +19 -0
  52. package/src/library/components/Button.jsx +31 -0
  53. package/src/library/components/Card.jsx +25 -0
  54. package/src/library/components/Input.jsx +35 -0
  55. package/src/library/components/Modal.jsx +26 -0
  56. package/src/library/components/Textarea.jsx +15 -0
  57. package/src/library/components/Toggle.jsx +16 -0
  58. package/src/library/pages/FitnessPage/FitnessPage.jsx +519 -0
  59. package/src/library/pages/FitnessPage/index.jsx +12 -0
  60. package/src/library/pages/GroupChat/GroupChat.jsx +275 -0
  61. package/src/library/pages/GroupChat/data.js +203 -0
  62. package/src/library/pages/GroupChat/index.jsx +12 -0
  63. package/src/library/pages/ReservationsOverview/ReservationsOverviewPage.jsx +225 -0
  64. package/src/library/pages/ReservationsOverview/index.jsx +12 -0
  65. package/src/library/pages/VideoConference/VideoConferencePage.jsx +334 -0
  66. package/src/library/pages/VideoConference/index.jsx +12 -0
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2
+
3
+ ## Getting Started
4
+ https://grok.com/c/8a8910e9-3c12-4eb9-8136-d8650eadb428
5
+ First, run the development server:
6
+
7
+ ```bash
8
+ npm run dev
9
+ # or
10
+ yarn dev
11
+ # or
12
+ pnpm dev
13
+ # or
14
+ bun dev
15
+ ```
16
+
17
+ Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18
+
19
+ You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
20
+
21
+ This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
22
+
23
+ ## Learn More
24
+
25
+ To learn more about Next.js, take a look at the following resources:
26
+
27
+ - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28
+ - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29
+
30
+ You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
31
+
32
+ ## Deploy on Vercel
33
+
34
+ The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35
+
36
+ Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
package/bin/run.js ADDED
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { createServer } from 'http';
4
+ import next from 'next';
5
+ import { parse } from 'url';
6
+ import fs from 'fs/promises';
7
+ import path from 'path';
8
+ import { fileURLToPath } from 'url';
9
+
10
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
+ const packageRoot = path.join(__dirname, '..');
12
+
13
+ const args = process.argv.slice(2);
14
+ const command = args[0];
15
+
16
+ if (command === 'add') {
17
+ const componentName = args[1];
18
+
19
+ if (!componentName) {
20
+ console.error('Please specify a component name: npx nora-ui add <component-name>');
21
+ process.exit(1);
22
+ }
23
+
24
+ try {
25
+ const registryPath = path.join(packageRoot, 'registry.json');
26
+ const registryContent = await fs.readFile(registryPath, 'utf-8');
27
+ const registry = JSON.parse(registryContent);
28
+
29
+ const component = registry[componentName];
30
+
31
+ if (!component) {
32
+ console.error(`Component "${componentName}" not found in registry.`);
33
+ console.log('Available components:', Object.keys(registry).join(', '));
34
+ process.exit(1);
35
+ }
36
+
37
+ const sourcePath = path.join(packageRoot, component.path);
38
+
39
+ // Determine destination path
40
+ // Check if src directory exists in the user's project
41
+ const userProjectRoot = process.cwd();
42
+ const hasSrc = await fs.access(path.join(userProjectRoot, 'src')).then(() => true).catch(() => false);
43
+
44
+ const destDir = hasSrc
45
+ ? path.join(userProjectRoot, 'src', 'library', component.type)
46
+ : path.join(userProjectRoot, 'library', component.type);
47
+
48
+ const destPath = path.join(destDir, path.basename(sourcePath));
49
+
50
+ // Ensure destination directory exists
51
+ await fs.mkdir(destDir, { recursive: true });
52
+
53
+ // Read and write file
54
+ const content = await fs.readFile(sourcePath, 'utf-8');
55
+ await fs.writeFile(destPath, content);
56
+
57
+ console.log(`✓ Component ${component.name} added to ${path.relative(userProjectRoot, destPath)}`);
58
+
59
+ } catch (error) {
60
+ console.error('Error adding component:', error);
61
+ process.exit(1);
62
+ }
63
+
64
+ } else {
65
+ // Default behavior: Start the Next.js server
66
+ const port = 3177;
67
+ const dev = false;
68
+ const app = next({ dev, dir: packageRoot });
69
+ const handle = app.getRequestHandler();
70
+
71
+ await app.prepare();
72
+
73
+ createServer((req, res) => {
74
+ const parsedUrl = parse(req.url, true);
75
+ handle(req, res, parsedUrl);
76
+ }).listen(port, () => {
77
+ console.log(`
78
+ Your UI Library is LIVE!
79
+ Open → http://localhost:${port}
80
+
81
+ Click any component → Copy code → Paste into your project!
82
+
83
+ Press Ctrl+C to stop
84
+ `);
85
+ });
86
+ }
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "modula-ui",
3
+ "version": "1.0.0",
4
+ "description": "A library of modern interfaces with great UX built with Shadcn",
5
+ "keywords": [
6
+ "tailwind",
7
+ "components",
8
+ "copy-paste",
9
+ "ui",
10
+ "nextjs",
11
+ "free"
12
+ ],
13
+ "author": "Mary Ojo",
14
+ "license": "MIT",
15
+ "type": "module",
16
+ "bin": {
17
+ "maryojo": "./bin/run.js",
18
+ "nora-ui": "./bin/run.js"
19
+ },
20
+ "files": [
21
+ "src",
22
+ "bin",
23
+ "public",
24
+ "next.config.js",
25
+ "tailwind.config.js",
26
+ "postcss.config.js",
27
+ "components-data.js",
28
+ "registry.json"
29
+ ],
30
+ "scripts": {
31
+ "dev": "next dev -p 3177",
32
+ "build": "next build",
33
+ "start": "next start -p 3177"
34
+ },
35
+ "dependencies": {
36
+ "@radix-ui/react-avatar": "^1.1.11",
37
+ "@radix-ui/react-checkbox": "^1.3.3",
38
+ "@radix-ui/react-dialog": "^1.1.15",
39
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
40
+ "@radix-ui/react-navigation-menu": "^1.2.14",
41
+ "@radix-ui/react-popover": "^1.1.15",
42
+ "@radix-ui/react-progress": "^1.1.8",
43
+ "@radix-ui/react-scroll-area": "^1.2.10",
44
+ "@radix-ui/react-select": "^2.2.6",
45
+ "@radix-ui/react-separator": "^1.1.8",
46
+ "@radix-ui/react-slider": "^1.3.6",
47
+ "@radix-ui/react-slot": "^1.2.4",
48
+ "@radix-ui/react-tooltip": "^1.2.8",
49
+ "class-variance-authority": "^0.7.1",
50
+ "clsx": "^2.1.1",
51
+ "date-fns": "^4.1.0",
52
+ "framer-motion": "^12.23.24",
53
+ "lucide-react": "^0.553.0",
54
+ "next": "16.0.7",
55
+ "react": "19.2.0",
56
+ "react-day-picker": "^9.11.2",
57
+ "react-dom": "19.2.0",
58
+ "recharts": "^2.15.4",
59
+ "tailwind-merge": "^3.4.0"
60
+ },
61
+ "devDependencies": {
62
+ "@shadcn/ui": "^0.0.4",
63
+ "@tailwindcss/postcss": "^4",
64
+ "baseline-browser-mapping": "^2.8.30",
65
+ "tailwindcss": "^4",
66
+ "tw-animate-css": "^1.4.0"
67
+ },
68
+ "engines": {
69
+ "node": ">=18.17.0"
70
+ }
71
+ }
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,34 @@
1
+ # 3D Avatar Sources
2
+
3
+ Since the image generation quota was reached, here are some excellent resources for free, commercial-use 3D avatars to complete your collection:
4
+
5
+ ## Free 3D Avatar Libraries (PNG/GLTF)
6
+
7
+ 1. **IconScout 3D Avatars**
8
+ - link: https://iconscout.com/3d-illustrations/avatar
9
+ - Format: PNG, GLTF, BLEND
10
+ - License: Check individual assets (many are free)
11
+
12
+ 2. **Freepik 3D Characters**
13
+ - Link: https://www.freepik.com/search?format=search&query=3d%20avatar%20render%20dark%20background
14
+ - Format: JPG, PSD
15
+ - Note: Excellent for high-quality renders on dark backgrounds.
16
+
17
+ 3. **Shapefest**
18
+ - Link: https://www.shapefest.com/
19
+ - Description: A massive library of free 3D shapes and hands, often has character elements.
20
+
21
+ 4. **Saly by Alzea**
22
+ - Link: https://www.figma.com/community/file/890095002328610853
23
+ - Description: High-quality 3D illustration pack (Figma resource).
24
+
25
+ 5. **Notion Avatar Maker (3D Style)**
26
+ - Link: https://notion-avatar.vercel.app/
27
+ - Note: Mostly 2D but has a distinct style.
28
+
29
+ ## Generated Avatars
30
+ The following avatars in this folder were generated by AI:
31
+ - `avatar1.png`: Professional Woman (Dark Background)
32
+ - `avatar2.png`: Casual Man (Dark Background)
33
+ - `avatar3.png`: Duplicate of avatar1 (Placeholder)
34
+ - `avatar4.png`: Duplicate of avatar2 (Placeholder)
@@ -0,0 +1 @@
1
+ <svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
@@ -0,0 +1 @@
1
+ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
@@ -0,0 +1 @@
1
+ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
@@ -0,0 +1 @@
1
+ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
package/registry.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "video-conference": {
3
+ "name": "VideoConference",
4
+ "type": "pages",
5
+ "path": "src/library/pages/VideoConference/VideoConferencePage.jsx"
6
+ },
7
+ "group-chat": {
8
+ "name": "GroupChat",
9
+ "type": "pages",
10
+ "path": "src/library/pages/GroupChat/GroupChatPage.jsx"
11
+ }
12
+ }
Binary file
@@ -0,0 +1,126 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+
4
+ @custom-variant dark (&:is(.dark *));
5
+
6
+ @theme inline {
7
+ --color-background: var(--background);
8
+ --color-foreground: var(--foreground);
9
+ --font-sans: var(--font-lexend);
10
+ --font-mono: var(--font-geist-mono);
11
+ --color-sidebar-ring: var(--sidebar-ring);
12
+ --color-sidebar-border: var(--sidebar-border);
13
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
14
+ --color-sidebar-accent: var(--sidebar-accent);
15
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
16
+ --color-sidebar-primary: var(--sidebar-primary);
17
+ --color-sidebar-foreground: var(--sidebar-foreground);
18
+ --color-sidebar: var(--sidebar);
19
+ --color-chart-5: var(--chart-5);
20
+ --color-chart-4: var(--chart-4);
21
+ --color-chart-3: var(--chart-3);
22
+ --color-chart-2: var(--chart-2);
23
+ --color-chart-1: var(--chart-1);
24
+ --color-ring: var(--ring);
25
+ --color-input: var(--input);
26
+ --color-border: var(--border);
27
+ --color-destructive: var(--destructive);
28
+ --color-accent-foreground: var(--accent-foreground);
29
+ --color-accent: var(--accent);
30
+ --color-muted-foreground: var(--muted-foreground);
31
+ --color-muted: var(--muted);
32
+ --color-secondary-foreground: var(--secondary-foreground);
33
+ --color-secondary: var(--secondary);
34
+ --color-primary-foreground: var(--primary-foreground);
35
+ --color-primary: var(--primary);
36
+ --color-popover-foreground: var(--popover-foreground);
37
+ --color-popover: var(--popover);
38
+ --color-card-foreground: var(--card-foreground);
39
+ --color-card: var(--card);
40
+ --radius-sm: calc(var(--radius) - 4px);
41
+ --radius-md: calc(var(--radius) - 2px);
42
+ --radius-lg: var(--radius);
43
+ --radius-xl: calc(var(--radius) + 4px);
44
+ }
45
+
46
+ :root {
47
+ --radius: 0.625rem;
48
+ --background: oklch(1 0 0);
49
+ --foreground: oklch(0.145 0 0);
50
+ --card: oklch(1 0 0);
51
+ --card-foreground: oklch(0.145 0 0);
52
+ --popover: oklch(1 0 0);
53
+ --popover-foreground: oklch(0.145 0 0);
54
+ --primary: oklch(0.205 0 0);
55
+ --primary-foreground: oklch(0.985 0 0);
56
+ --secondary: oklch(0.97 0 0);
57
+ --secondary-foreground: oklch(0.205 0 0);
58
+ --muted: oklch(0.97 0 0);
59
+ --muted-foreground: oklch(0.556 0 0);
60
+ --accent: oklch(0.97 0 0);
61
+ --accent-foreground: oklch(0.205 0 0);
62
+ --destructive: oklch(0.577 0.245 27.325);
63
+ --border: oklch(0.922 0 0);
64
+ --input: oklch(0.922 0 0);
65
+ --ring: oklch(0.708 0 0);
66
+ --chart-1: oklch(0.646 0.222 41.116);
67
+ --chart-2: oklch(0.6 0.118 184.704);
68
+ --chart-3: oklch(0.398 0.07 227.392);
69
+ --chart-4: oklch(0.828 0.189 84.429);
70
+ --chart-5: oklch(0.769 0.188 70.08);
71
+ --sidebar: oklch(0.985 0 0);
72
+ --sidebar-foreground: oklch(0.145 0 0);
73
+ --sidebar-primary: oklch(0.205 0 0);
74
+ --sidebar-primary-foreground: oklch(0.985 0 0);
75
+ --sidebar-accent: oklch(0.97 0 0);
76
+ --sidebar-accent-foreground: oklch(0.205 0 0);
77
+ --sidebar-border: oklch(0.922 0 0);
78
+ --sidebar-ring: oklch(0.708 0 0);
79
+ }
80
+
81
+ .dark {
82
+ --background: oklch(0.145 0 0);
83
+ --foreground: oklch(0.985 0 0);
84
+ --card: oklch(0.205 0 0);
85
+ --card-foreground: oklch(0.985 0 0);
86
+ --popover: oklch(0.205 0 0);
87
+ --popover-foreground: oklch(0.985 0 0);
88
+ --primary: oklch(0.922 0 0);
89
+ --primary-foreground: oklch(0.205 0 0);
90
+ --secondary: oklch(0.269 0 0);
91
+ --secondary-foreground: oklch(0.985 0 0);
92
+ --muted: oklch(0.269 0 0);
93
+ --muted-foreground: oklch(0.708 0 0);
94
+ --accent: oklch(0.269 0 0);
95
+ --accent-foreground: oklch(0.985 0 0);
96
+ --destructive: oklch(0.704 0.191 22.216);
97
+ --border: oklch(1 0 0 / 10%);
98
+ --input: oklch(1 0 0 / 15%);
99
+ --ring: oklch(0.556 0 0);
100
+ --chart-1: oklch(0.488 0.243 264.376);
101
+ --chart-2: oklch(0.696 0.17 162.48);
102
+ --chart-3: oklch(0.769 0.188 70.08);
103
+ --chart-4: oklch(0.627 0.265 303.9);
104
+ --chart-5: oklch(0.645 0.246 16.439);
105
+ --sidebar: oklch(0.205 0 0);
106
+ --sidebar-foreground: oklch(0.985 0 0);
107
+ --sidebar-primary: oklch(0.488 0.243 264.376);
108
+ --sidebar-primary-foreground: oklch(0.985 0 0);
109
+ --sidebar-accent: oklch(0.269 0 0);
110
+ --sidebar-accent-foreground: oklch(0.985 0 0);
111
+ --sidebar-border: oklch(1 0 0 / 10%);
112
+ --sidebar-ring: oklch(0.556 0 0);
113
+ }
114
+
115
+ @layer base {
116
+ * {
117
+ @apply border-border outline-ring/50;
118
+ }
119
+ body {
120
+ @apply bg-background text-foreground;
121
+ }
122
+
123
+ .lexend {
124
+ font-family: var(--font-lexend), sans-serif;
125
+ }
126
+ }
@@ -0,0 +1,29 @@
1
+ import { Lexend, Geist_Mono } from "next/font/google";
2
+ import "./globals.css";
3
+
4
+ const lexend = Lexend({
5
+ variable: "--font-lexend",
6
+ subsets: ["latin"],
7
+ });
8
+
9
+ const geistMono = Geist_Mono({
10
+ variable: "--font-geist-mono",
11
+ subsets: ["latin"],
12
+ });
13
+
14
+ export const metadata = {
15
+ title: "Nora UI",
16
+ description: "A library of modern interfaces with great UX built with Shadcn",
17
+ };
18
+
19
+ export default function RootLayout({ children }) {
20
+ return (
21
+ <html lang="en">
22
+ <body
23
+ className={`${lexend.variable} ${geistMono.variable} antialiased`}
24
+ >
25
+ {children}
26
+ </body>
27
+ </html>
28
+ );
29
+ }
@@ -0,0 +1,50 @@
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+ import Header from '@/components/Header';
5
+ import MobileOverlay from '@/components/MobileOverlay';
6
+ import Sidebar from '@/components/Sidebar';
7
+ import PreviewCard from '@/components/PreviewCard';
8
+ import CodeCard from '@/components/CodeCard';
9
+ import { components } from '@/data/componentData';
10
+
11
+ export default function Home() {
12
+ const [selected, setSelected] = useState('VideoConference');
13
+ const [sidebarOpen, setSidebarOpen] = useState(false);
14
+
15
+ const current = components[selected];
16
+
17
+ return (
18
+ <div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100">
19
+
20
+ <Header
21
+ sidebarOpen={sidebarOpen}
22
+ toggleSidebar={() => setSidebarOpen(!sidebarOpen)}
23
+ />
24
+
25
+ <MobileOverlay open={sidebarOpen} onClose={() => setSidebarOpen(false)} />
26
+
27
+ <div className="w-full mx-auto px-6 flex gap-6">
28
+
29
+ <Sidebar
30
+ selected={selected}
31
+ onSelect={setSelected}
32
+ open={sidebarOpen}
33
+ onClose={() => setSidebarOpen(false)}
34
+ />
35
+
36
+ <main className="space-y-6 w-full">
37
+ <PreviewCard>{current?.preview}</PreviewCard>
38
+
39
+ <CodeCard code={current?.code} />
40
+
41
+ {/* add use case and tags to this */}
42
+
43
+ <div className='m-10'>
44
+
45
+ </div>
46
+ </main>
47
+ </div>
48
+ </div>
49
+ );
50
+ }
@@ -0,0 +1,50 @@
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+ import Header from '@/components/Header';
5
+ import MobileOverlay from '@/components/MobileOverlay';
6
+ import Sidebar from '@/components/Sidebar';
7
+ import PreviewCard from '@/components/PreviewCard';
8
+ import CodeCard from '@/components/CodeCard';
9
+ import { components } from '@/data/componentData';
10
+
11
+ export default function Patterns() {
12
+ const [selected, setSelected] = useState('button');
13
+ const [sidebarOpen, setSidebarOpen] = useState(false);
14
+
15
+ const current = components[selected];
16
+
17
+ return (
18
+ <div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100">
19
+
20
+ <Header
21
+ sidebarOpen={sidebarOpen}
22
+ toggleSidebar={() => setSidebarOpen(!sidebarOpen)}
23
+ />
24
+
25
+ <MobileOverlay open={sidebarOpen} onClose={() => setSidebarOpen(false)} />
26
+
27
+ <div className="w-full mx-auto px-6 flex gap-6">
28
+
29
+ {sidebarOpen && <Sidebar
30
+ selected={selected}
31
+ onSelect={setSelected}
32
+ open={sidebarOpen}
33
+ onClose={() => setSidebarOpen(false)}
34
+ />}
35
+
36
+ <main className="space-y-6 w-full">
37
+ <PreviewCard>{current?.preview}</PreviewCard>
38
+
39
+ <CodeCard code={current?.code} />
40
+
41
+ <div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
42
+ <p className="text-sm text-blue-800">
43
+ <strong>Note:</strong> These components use Tailwind CSS utility classes. Make sure you have Tailwind CSS installed in your project.
44
+ </p>
45
+ </div>
46
+ </main>
47
+ </div>
48
+ </div>
49
+ );
50
+ }
@@ -0,0 +1,16 @@
1
+ import CopyButton from './CopyButton';
2
+
3
+ export default function CodeCard({ code }) {
4
+ return (
5
+ <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
6
+ <div className="flex items-center justify-between mb-4">
7
+ <h2 className="text-xl font-semibold text-gray-900">Code</h2>
8
+ <CopyButton text={code} />
9
+ </div>
10
+
11
+ <pre className="bg-gray-900 text-gray-100 rounded-lg p-4 overflow-x-auto text-xs md:text-sm">
12
+ <code>{code?.trim()}</code>
13
+ </pre>
14
+ </div>
15
+ );
16
+ }
@@ -0,0 +1,31 @@
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+ import { Copy, Check } from 'lucide-react';
5
+
6
+ export default function CopyButton({ text }) {
7
+ const [copied, setCopied] = useState(false);
8
+
9
+ const copy = () => {
10
+ navigator.clipboard.writeText(text);
11
+ setCopied(true);
12
+ setTimeout(() => setCopied(false), 2000);
13
+ };
14
+
15
+ return (
16
+ <button
17
+ onClick={copy}
18
+ className="flex items-center gap-2 px-4 py-2 bg-gray-900 text-white rounded-lg hover:bg-gray-800 transition-colors text-sm"
19
+ >
20
+ {copied ? (
21
+ <>
22
+ <Check size={18} /> Copied!
23
+ </>
24
+ ) : (
25
+ <>
26
+ <Copy size={18} /> Copy Code
27
+ </>
28
+ )}
29
+ </button>
30
+ );
31
+ }
@@ -0,0 +1,24 @@
1
+ 'use client';
2
+
3
+ import { Menu, X } from 'lucide-react';
4
+ import Logo from './Logo';
5
+
6
+ export default function Header({ sidebarOpen, toggleSidebar }) {
7
+ return (
8
+ <div className="max-w-7xl mx-auto p-6">
9
+ <div className="mb-8 flex items-center justify-between">
10
+ <div>
11
+ <Logo />
12
+ <p className="text-gray-600">A library of modern interfaces with great UX built with Shadcn</p>
13
+ </div>
14
+
15
+ <button
16
+ onClick={toggleSidebar}
17
+ className="p-2 bg-white rounded-lg shadow-sm border border-gray-200 hover:bg-gray-50"
18
+ >
19
+ {sidebarOpen ? <X size={24} /> : <Menu size={24} />}
20
+ </button>
21
+ </div>
22
+ </div>
23
+ );
24
+ }
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+
3
+ const Logo = ({ className = '' }) => {
4
+ return (
5
+ <svg
6
+ width="180"
7
+ height="50"
8
+ viewBox="0 0 180 50"
9
+ fill="none"
10
+ xmlns="http://www.w3.org/2000/svg"
11
+ className={className}
12
+ >
13
+ {/* Icon Element - Abstract 'N' or Tech shape */}
14
+ <circle cx="25" cy="25" r="20" fill="url(#grad1)" opacity="0.2" />
15
+ <path
16
+ d="M15 35V15L35 35V15"
17
+ stroke="url(#grad2)"
18
+ strokeWidth="4"
19
+ strokeLinecap="round"
20
+ strokeLinejoin="round"
21
+ />
22
+
23
+ {/* Text 'nora' */}
24
+ <text
25
+ x="55"
26
+ y="32"
27
+ fontFamily="system-ui, -apple-system, sans-serif"
28
+ fontWeight="800"
29
+ fontSize="28"
30
+ fill="#111827"
31
+ letterSpacing="-1"
32
+ >
33
+ nora
34
+ </text>
35
+
36
+ {/* Text '-ui' with different style */}
37
+ <text
38
+ x="115"
39
+ y="32"
40
+ fontFamily="system-ui, -apple-system, sans-serif"
41
+ fontWeight="800"
42
+ fontSize="28"
43
+ fill="#111827"
44
+ letterSpacing="-1"
45
+ >
46
+ ui
47
+ </text>
48
+
49
+ {/* Gradients */}
50
+ <defs>
51
+ <radialGradient id="grad1" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(25 25) rotate(90) scale(20)">
52
+ <stop stopColor="#4F46E5" />
53
+ <stop offset="1" stopColor="#A5B4FC" stopOpacity="0" />
54
+ </radialGradient>
55
+ <linearGradient id="grad2" x1="15" y1="15" x2="35" y2="35" gradientUnits="userSpaceOnUse">
56
+ <stop stopColor="#4F46E5" />
57
+ <stop offset="1" stopColor="#EC4899" />
58
+ </linearGradient>
59
+ </defs>
60
+ </svg>
61
+ );
62
+ };
63
+
64
+ export default Logo;