├── ROADMAP.md ├── public ├── favicon.ico ├── og-image.png ├── media │ ├── logo.webp │ ├── meadow.webp │ ├── surreal.webp │ ├── gaiaui_logo.png │ ├── logo_black.webp │ ├── text_w_logo_white.webp │ ├── wallpapers │ │ ├── meadow.webp │ │ └── surreal.webp │ └── experience logo.svg ├── favicon-16x16.png ├── favicon-32x32.png ├── apple-touch-icon.png ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── site.webmanifest └── r │ ├── goal-card.json │ ├── todo-item.json │ ├── cli-command.json │ ├── file-dropzone.json │ ├── twitter-card.json │ ├── model-selector.json │ ├── code-block.json │ ├── component-preview-tooltip.json │ ├── file-preview.json │ ├── workflow-card.json │ ├── notification-card.json │ ├── calendar-event-card.json │ ├── github-stars-button.json │ └── author-tooltip.json ├── .npmrc ├── postcss.config.mjs ├── components ├── previews │ ├── navbar-menu │ │ ├── default.tsx │ │ ├── static-links.tsx │ │ └── basic.tsx │ ├── github-stars-button │ │ ├── default.tsx │ │ ├── sizes.tsx │ │ └── variants.tsx │ ├── raised-button │ │ ├── sizes.tsx │ │ └── default.tsx │ ├── code-block │ │ ├── default.tsx │ │ ├── line-numbers.tsx │ │ └── languages.tsx │ ├── author-tooltip │ │ ├── default.tsx │ │ └── sizes.tsx │ ├── file-dropzone │ │ └── default.tsx │ ├── message-bubble │ │ ├── simple.tsx │ │ ├── grouped.tsx │ │ ├── default.tsx │ │ └── grouped-rounded.tsx │ ├── email-compose-card │ │ └── default.tsx │ ├── twitter-card │ │ └── default.tsx │ ├── file-preview │ │ ├── uploading.tsx │ │ └── default.tsx │ ├── todo-item │ │ ├── priorities.tsx │ │ └── default.tsx │ ├── component-preview-tooltip │ │ └── default.tsx │ ├── index.tsx │ ├── calendar-event-card │ │ ├── default.tsx │ │ └── actions.tsx │ ├── weather-card │ │ ├── default.tsx │ │ ├── units.tsx │ │ └── with-forecast.tsx │ ├── holo-card │ │ ├── default.tsx │ │ └── colors.tsx │ ├── search-results-tabs │ │ ├── with-image-click.tsx │ │ ├── web-only.tsx │ │ ├── news.tsx │ │ └── default.tsx │ ├── link-preview │ │ └── default.tsx │ ├── composer │ │ ├── with-files.tsx │ │ └── default.tsx │ ├── model-selector │ │ └── default.tsx │ ├── goal-card │ │ └── default.tsx │ ├── notification-card │ │ └── default.tsx │ ├── slash-command-dropdown │ │ └── default.tsx │ └── nested-menu │ │ └── default.tsx ├── icons │ ├── index.ts │ └── github.tsx ├── core │ ├── navbar-wrapper.tsx │ ├── docs-sidebar.tsx │ ├── command-menu.tsx │ ├── page-navigation.tsx │ ├── copy-button.tsx │ ├── code-block.tsx │ ├── component-preview.tsx │ ├── fullscreen-button.tsx │ ├── source-code.tsx │ ├── table-of-contents.tsx │ ├── component-preview-client.tsx │ ├── doc-page-layout.tsx │ └── page-navigation-client.tsx └── ui │ ├── skeleton.tsx │ ├── label.tsx │ ├── separator.tsx │ ├── kbd.tsx │ ├── theme-toggle.tsx │ ├── input.tsx │ ├── avatar.tsx │ ├── toggle.tsx │ ├── badge.tsx │ ├── popover.tsx │ ├── scroll-area.tsx │ ├── tooltip.tsx │ ├── tabs.tsx │ ├── card.tsx │ ├── button.tsx │ └── footer.tsx ├── lib ├── utils.ts ├── source.ts ├── siteConfig.ts ├── mdx.ts └── navigation.ts ├── types └── nav-item.ts ├── .env.example ├── registry └── new-york │ └── ui │ ├── icons.tsx │ ├── weather-detail-item.tsx │ ├── todo-item.tsx │ ├── github-stars-button.tsx │ ├── message-bubble.tsx │ ├── message-bubble.css │ ├── raised-button.tsx │ └── author-tooltip.tsx ├── content └── docs │ ├── contributors.mdx │ ├── roadmap.mdx │ ├── components.mdx │ ├── index.mdx │ ├── components │ ├── raised-button.mdx │ ├── file-dropzone.mdx │ ├── twitter-card.mdx │ ├── goal-card.mdx │ ├── email-compose-card.mdx │ ├── component-preview-tooltip.mdx │ ├── model-selector.mdx │ ├── calendar-event-card.mdx │ ├── file-preview.mdx │ ├── notification-card.mdx │ ├── todo-item.mdx │ ├── github-stars-button.mdx │ ├── workflow-card.mdx │ └── author-tooltip.mdx │ └── installation.mdx ├── app ├── docs │ └── layout.tsx ├── robots.ts ├── manifest.ts ├── layout.tsx └── sitemap.ts ├── components.json ├── .gitignore ├── tsconfig.json ├── biome.json ├── next.config.ts ├── package.json └── README.md /ROADMAP.md: -------------------------------------------------------------------------------- 1 | [Roadmap](https://ui.heygaia.io/docs/roadmap) -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/og-image.png -------------------------------------------------------------------------------- /public/media/logo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/media/logo.webp -------------------------------------------------------------------------------- /public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/favicon-32x32.png -------------------------------------------------------------------------------- /public/media/meadow.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/media/meadow.webp -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/media/surreal.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/media/surreal.webp -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | @hugeicons-pro:registry=https://npm.hugeicons.com/ 2 | //npm.hugeicons.com/:_authToken=${HUGEICONS_LICENSE_KEY} -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | const config = { 2 | plugins: ["@tailwindcss/postcss"], 3 | }; 4 | 5 | export default config; 6 | -------------------------------------------------------------------------------- /public/media/gaiaui_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/media/gaiaui_logo.png -------------------------------------------------------------------------------- /public/media/logo_black.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/media/logo_black.webp -------------------------------------------------------------------------------- /components/previews/navbar-menu/default.tsx: -------------------------------------------------------------------------------- 1 | import BasicNavbar from "./basic"; 2 | 3 | export default BasicNavbar; 4 | -------------------------------------------------------------------------------- /public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/media/text_w_logo_white.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/media/text_w_logo_white.webp -------------------------------------------------------------------------------- /public/media/wallpapers/meadow.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/media/wallpapers/meadow.webp -------------------------------------------------------------------------------- /public/media/wallpapers/surreal.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theexperiencecompany/ui/HEAD/public/media/wallpapers/surreal.webp -------------------------------------------------------------------------------- /lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } 7 | -------------------------------------------------------------------------------- /types/nav-item.ts: -------------------------------------------------------------------------------- 1 | export interface NavItem { 2 | title: string; 3 | href: string; 4 | icon?: string; 5 | } 6 | 7 | export interface NavSection { 8 | title: string; 9 | items: NavItem[]; 10 | } 11 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # ===== Hugeicons ===== 2 | # Set to "true" to use Pro (solid) icons instead of Free (stroke) icons 3 | # Requires HUGEICONS_LICENSE_KEY to be set in .npmrc for Pro package installation 4 | USE_PRO_ICONS=false -------------------------------------------------------------------------------- /registry/new-york/ui/icons.tsx: -------------------------------------------------------------------------------- 1 | // registry/new-york/ui/icons.tsx 2 | // Free icons - upgrade to Pro by changing the import below 3 | export * from "@hugeicons/core-free-icons"; 4 | export { HugeiconsIcon } from "@hugeicons/react"; 5 | -------------------------------------------------------------------------------- /content/docs/contributors.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Contributors" 3 | description: "Thank you to everyone who has contributed to GAIA UI!" 4 | --- 5 | 6 | import { ContributorsPage } from "@/components/core/contributors-page" 7 | 8 | 9 | -------------------------------------------------------------------------------- /components/icons/index.ts: -------------------------------------------------------------------------------- 1 | // components/icons/index.ts 2 | // Uses free icons by default 3 | // When USE_PRO_ICONS=true, webpack swaps to Pro icons at build time 4 | 5 | export * from "@hugeicons/core-free-icons"; 6 | export { HugeiconsIcon } from "@hugeicons/react"; 7 | -------------------------------------------------------------------------------- /components/core/navbar-wrapper.tsx: -------------------------------------------------------------------------------- 1 | import { Navbar } from "@/components/ui/navbar"; 2 | import { getNavigation } from "@/lib/navigation"; 3 | 4 | export function NavbarWrapper() { 5 | const navigation = getNavigation(); 6 | 7 | return ; 8 | } 9 | -------------------------------------------------------------------------------- /components/core/docs-sidebar.tsx: -------------------------------------------------------------------------------- 1 | import { getNavigation } from "@/lib/navigation"; 2 | import { DocsSidebarClient } from "./docs-sidebar-client"; 3 | 4 | export function DocsSidebar() { 5 | const navigation = getNavigation(); 6 | 7 | return ; 8 | } 9 | -------------------------------------------------------------------------------- /components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | 3 | function Skeleton({ className, ...props }: React.ComponentProps<"div">) { 4 | return ( 5 |
10 | ); 11 | } 12 | 13 | export { Skeleton }; 14 | -------------------------------------------------------------------------------- /components/previews/github-stars-button/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { GitHubStarsButton } from "@/registry/new-york/ui/github-stars-button"; 4 | 5 | export default function GitHubStarsButtonDefault() { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /components/previews/raised-button/sizes.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { RaisedButton } from "@/registry/new-york/ui/raised-button"; 4 | 5 | export default function RaisedButtonSizes() { 6 | return ( 7 | <> 8 | Small 9 | Default 10 | Large 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /components/previews/navbar-menu/static-links.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { NavbarWithMenu } from "@/registry/new-york/ui/navbar-menu"; 4 | 5 | export default function NavbarMenuStaticLinks() { 6 | return ( 7 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /public/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /components/core/command-menu.tsx: -------------------------------------------------------------------------------- 1 | import type { NavSection } from "@/types/nav-item"; 2 | import { CommandMenuClient } from "./command-menu-client"; 3 | 4 | interface CommandMenuProps { 5 | open: boolean; 6 | setOpen: (open: boolean) => void; 7 | navigation: NavSection[]; 8 | } 9 | 10 | export function CommandMenu({ open, setOpen, navigation }: CommandMenuProps) { 11 | return ( 12 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /components/previews/github-stars-button/sizes.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { GitHubStarsButton } from "@/registry/new-york/ui/github-stars-button"; 4 | 5 | export default function GitHubStarsButtonSizes() { 6 | return ( 7 |
8 | 9 | 10 | 11 |
12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /public/r/goal-card.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema/registry-item.json", 3 | "name": "goal-card", 4 | "type": "registry:ui", 5 | "title": "Goal Card", 6 | "description": "A card component for displaying goal progress with status indicators and step tracking.", 7 | "dependencies": ["lucide-react"], 8 | "registryDependencies": [], 9 | "files": [ 10 | { 11 | "path": "registry/new-york/ui/goal-card.tsx", 12 | "type": "registry:ui" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /public/r/todo-item.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema/registry-item.json", 3 | "name": "todo-item", 4 | "type": "registry:ui", 5 | "title": "Todo Item", 6 | "description": "An interactive todo item with priority colors, due dates, labels, and subtask support.", 7 | "dependencies": ["lucide-react"], 8 | "registryDependencies": [], 9 | "files": [ 10 | { 11 | "path": "registry/new-york/ui/todo-item.tsx", 12 | "type": "registry:ui" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /app/docs/layout.tsx: -------------------------------------------------------------------------------- 1 | import { DocsSidebar } from "@/components/core/docs-sidebar"; 2 | 3 | export default function DocsLayout({ 4 | children, 5 | }: { 6 | children: React.ReactNode; 7 | }) { 8 | return ( 9 |
10 |
11 | 12 | {children} 13 |
14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /public/r/cli-command.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema/registry-item.json", 3 | "name": "cli-command", 4 | "type": "registry:ui", 5 | "title": "CLI Command", 6 | "description": "A command display with tabs for different package managers and copy functionality.", 7 | "dependencies": ["lucide-react"], 8 | "registryDependencies": [], 9 | "files": [ 10 | { 11 | "path": "registry/new-york/ui/cli-command.tsx", 12 | "type": "registry:ui" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /public/r/file-dropzone.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema/registry-item.json", 3 | "name": "file-dropzone", 4 | "type": "registry:ui", 5 | "title": "File Dropzone", 6 | "description": "A drag-and-drop file upload zone with preview, validation, and file management.", 7 | "dependencies": ["lucide-react"], 8 | "registryDependencies": [], 9 | "files": [ 10 | { 11 | "path": "registry/new-york/ui/file-dropzone.tsx", 12 | "type": "registry:ui" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /public/r/twitter-card.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema/registry-item.json", 3 | "name": "twitter-card", 4 | "type": "registry:ui", 5 | "title": "Twitter Card", 6 | "description": "A Twitter/X-style post card with author info, engagement metrics, and media support.", 7 | "dependencies": ["lucide-react"], 8 | "registryDependencies": [], 9 | "files": [ 10 | { 11 | "path": "registry/new-york/ui/twitter-card.tsx", 12 | "type": "registry:ui" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "app/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } 22 | -------------------------------------------------------------------------------- /public/r/model-selector.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema/registry-item.json", 3 | "name": "model-selector", 4 | "type": "registry:ui", 5 | "title": "Model Selector", 6 | "description": "A dropdown selector for choosing AI models with provider information and pro badges.", 7 | "dependencies": ["lucide-react"], 8 | "registryDependencies": [], 9 | "files": [ 10 | { 11 | "path": "registry/new-york/ui/model-selector.tsx", 12 | "type": "registry:ui" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /public/r/code-block.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema/registry-item.json", 3 | "name": "code-block", 4 | "type": "registry:ui", 5 | "title": "Code Block", 6 | "description": "A syntax-highlighted code block with copy and download functionality, perfect for displaying code snippets.", 7 | "dependencies": ["lucide-react"], 8 | "registryDependencies": [], 9 | "files": [ 10 | { 11 | "path": "registry/new-york/ui/code-block.tsx", 12 | "type": "registry:ui" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /public/r/component-preview-tooltip.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema/registry-item.json", 3 | "name": "component-preview-tooltip", 4 | "type": "registry:ui", 5 | "title": "Component Preview Tooltip", 6 | "description": "A hover tooltip that shows a live preview of any component.", 7 | "dependencies": [], 8 | "registryDependencies": [], 9 | "files": [ 10 | { 11 | "path": "registry/new-york/ui/component-preview-tooltip.tsx", 12 | "type": "registry:ui" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /public/r/file-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema/registry-item.json", 3 | "name": "file-preview", 4 | "type": "registry:ui", 5 | "title": "File Preview", 6 | "description": "Display uploaded files with smart type detection, file icons, image thumbnails, and upload progress.", 7 | "dependencies": ["lucide-react"], 8 | "registryDependencies": [], 9 | "files": [ 10 | { 11 | "path": "registry/new-york/ui/file-preview.tsx", 12 | "type": "registry:ui" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /components/previews/raised-button/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { RaisedButton } from "@/registry/new-york/ui/raised-button"; 4 | 5 | export default function RaisedButtonDefault() { 6 | return ( 7 | <> 8 | Default 9 | Blue 10 | Red 11 | Green 12 | Purple 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /public/r/workflow-card.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema/registry-item.json", 3 | "name": "workflow-card", 4 | "type": "registry:ui", 5 | "title": "Workflow Card", 6 | "description": "A card for displaying workflow automations with rotated tool icons, execution stats, and action buttons.", 7 | "dependencies": ["lucide-react"], 8 | "registryDependencies": [], 9 | "files": [ 10 | { 11 | "path": "registry/new-york/ui/workflow-card.tsx", 12 | "type": "registry:ui" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /public/r/notification-card.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema/registry-item.json", 3 | "name": "notification-card", 4 | "type": "registry:ui", 5 | "title": "Notification Card", 6 | "description": "An enhanced notification card with action buttons, read/unread states, and timestamp display.", 7 | "dependencies": ["lucide-react"], 8 | "registryDependencies": [], 9 | "files": [ 10 | { 11 | "path": "registry/new-york/ui/notification-card.tsx", 12 | "type": "registry:ui" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /public/r/calendar-event-card.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema/registry-item.json", 3 | "name": "calendar-event-card", 4 | "type": "registry:ui", 5 | "title": "Calendar Event Card", 6 | "description": "A styled card for displaying calendar events with color indicators, status states, and action buttons.", 7 | "dependencies": ["lucide-react"], 8 | "registryDependencies": [], 9 | "files": [ 10 | { 11 | "path": "registry/new-york/ui/calendar-event-card.tsx", 12 | "type": "registry:ui" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /components/previews/code-block/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { CodeBlock } from "@/registry/new-york/ui/code-block"; 4 | 5 | export default function CodeBlockDefault() { 6 | const code = `function greet(name) { 7 | console.log(\`Hello, \${name}!\`); 8 | return \`Welcome to GAIA UI\`; 9 | } 10 | 11 | greet("Developer");`; 12 | 13 | return ( 14 |
15 | 16 | {code} 17 | 18 |
19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /components/previews/author-tooltip/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { AuthorTooltip } from "@/registry/new-york/ui/author-tooltip"; 4 | 5 | export default function AuthorTooltipDefault() { 6 | return ( 7 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /components/core/page-navigation.tsx: -------------------------------------------------------------------------------- 1 | import type { NavSection } from "@/types/nav-item"; 2 | import { PageNavigationClient } from "./page-navigation-client"; 3 | 4 | interface PageNavigationProps { 5 | position?: "top" | "bottom"; 6 | markdownContent?: string; 7 | navigation: NavSection[]; 8 | } 9 | 10 | export function PageNavigation({ 11 | position = "top", 12 | markdownContent, 13 | navigation, 14 | }: PageNavigationProps) { 15 | return ( 16 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /components/previews/file-dropzone/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { 4 | type DroppedFile, 5 | FileDropzone, 6 | } from "@/registry/new-york/ui/file-dropzone"; 7 | 8 | export default function FileDropzoneDefault() { 9 | const handleFilesDropped = (files: DroppedFile[]) => { 10 | console.log("Files dropped:", files); 11 | }; 12 | 13 | return ( 14 |
15 | 21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /components/previews/github-stars-button/variants.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { GitHubStarsButton } from "@/registry/new-york/ui/github-stars-button"; 4 | 5 | export default function GitHubStarsButtonVariants() { 6 | return ( 7 |
8 |
9 |

With Label

10 | 11 |
12 |
13 |

Without Label

14 | 15 |
16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # env files (can opt-in for committing if needed) 34 | .env 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | -------------------------------------------------------------------------------- /components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as LabelPrimitive from "@radix-ui/react-label"; 4 | import type * as React from "react"; 5 | 6 | import { cn } from "@/lib/utils"; 7 | 8 | function Label({ 9 | className, 10 | ...props 11 | }: React.ComponentProps) { 12 | return ( 13 | 21 | ); 22 | } 23 | 24 | export { Label }; 25 | -------------------------------------------------------------------------------- /components/previews/message-bubble/simple.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { MessageBubble } from "@/registry/new-york/ui/message-bubble"; 4 | 5 | export default function MessageBubbleSimple() { 6 | return ( 7 |
8 | 9 | 13 | 14 | 18 | 22 |
23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "react-jsx", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": [ 26 | "next-env.d.ts", 27 | "**/*.ts", 28 | "**/*.tsx", 29 | ".next/types/**/*.ts", 30 | ".next/dev/types/**/*.ts" 31 | ], 32 | "exclude": ["node_modules"] 33 | } 34 | -------------------------------------------------------------------------------- /lib/source.ts: -------------------------------------------------------------------------------- 1 | import path from "node:path"; 2 | import fs from "fs"; 3 | 4 | /** 5 | * Read source code from a file in the project 6 | * @param filePath - Path relative to project root (e.g., "registry/new-york/ui/raised-button.tsx") 7 | * @returns The file contents as a string 8 | */ 9 | export function getSourceCode(filePath: string): string { 10 | const fullPath = path.join(process.cwd(), filePath); 11 | 12 | if (!fs.existsSync(fullPath)) { 13 | console.warn(`Source file not found: ${filePath}`); 14 | return `// File not found: ${filePath}`; 15 | } 16 | 17 | try { 18 | return fs.readFileSync(fullPath, "utf8"); 19 | } catch (error) { 20 | console.error(`Error reading source file: ${filePath}`, error); 21 | return `// Error reading file: ${filePath}`; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/2.3.7/schema.json", 3 | "vcs": { 4 | "enabled": true, 5 | "clientKind": "git", 6 | "useIgnoreFile": true 7 | }, 8 | "files": { 9 | "ignoreUnknown": false 10 | }, 11 | "formatter": { 12 | "enabled": true, 13 | "indentStyle": "tab" 14 | }, 15 | "linter": { 16 | "domains": { 17 | "next": "recommended" 18 | }, 19 | "enabled": true, 20 | "rules": { 21 | "recommended": true 22 | } 23 | }, 24 | "javascript": { 25 | "formatter": { 26 | "quoteStyle": "double" 27 | } 28 | }, 29 | "css": { 30 | "parser": { 31 | "tailwindDirectives": true 32 | } 33 | }, 34 | "assist": { 35 | "enabled": true, 36 | "actions": { 37 | "source": { 38 | "organizeImports": "on" 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /components/previews/email-compose-card/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { EmailComposeCard } from "@/registry/new-york/ui/email-compose-card"; 4 | 5 | export default function EmailPreviewDefault() { 6 | return ( 7 |
8 | { 15 | await new Promise((resolve) => setTimeout(resolve, 2000)); 16 | console.log("Sent email:", data); 17 | alert("Email sent! Check console for data."); 18 | }} 19 | /> 20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /components/ui/separator.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as SeparatorPrimitive from "@radix-ui/react-separator"; 4 | import type * as React from "react"; 5 | 6 | import { cn } from "@/lib/utils"; 7 | 8 | function Separator({ 9 | className, 10 | orientation = "horizontal", 11 | decorative = true, 12 | ...props 13 | }: React.ComponentProps) { 14 | return ( 15 | 25 | ); 26 | } 27 | 28 | export { Separator }; 29 | -------------------------------------------------------------------------------- /components/previews/code-block/line-numbers.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { CodeBlock } from "@/registry/new-york/ui/code-block"; 4 | 5 | export default function CodeBlockLineNumbers() { 6 | const code = `import React from "react"; 7 | import { cn } from "@/lib/utils"; 8 | 9 | export function Component({ className }) { 10 | const [count, setCount] = React.useState(0); 11 | 12 | return ( 13 |
14 |

Count: {count}

15 | 18 |
19 | ); 20 | }`; 21 | 22 | return ( 23 |
24 | 25 | {code} 26 | 27 |
28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /components/previews/twitter-card/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { TwitterCard } from "@/registry/new-york/ui/twitter-card"; 4 | 5 | // Static date for demo purposes - avoids React purity rules 6 | const DEMO_TIMESTAMP = new Date("2025-12-15T08:55:00Z"); 7 | 8 | export default function TwitterCardDefault() { 9 | return ( 10 |
11 | 24 |
25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /components/previews/file-preview/uploading.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { FilePreview } from "@/registry/new-york/ui/file-preview"; 4 | 5 | export default function FilePreviewUploading() { 6 | const files = [ 7 | { 8 | id: "1", 9 | url: "#", 10 | name: "large-video.mp4", 11 | type: "video/mp4", 12 | isUploading: true, 13 | }, 14 | { 15 | id: "2", 16 | url: "#", 17 | name: "completed.pdf", 18 | type: "application/pdf", 19 | isUploading: false, 20 | }, 21 | { 22 | id: "3", 23 | url: "#", 24 | name: "audio-file.mp3", 25 | type: "audio/mpeg", 26 | isUploading: true, 27 | }, 28 | ]; 29 | 30 | return ( 31 |
32 | console.log("Remove file:", id)} 35 | /> 36 |
37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /components/previews/author-tooltip/sizes.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { AuthorTooltip } from "@/registry/new-york/ui/author-tooltip"; 4 | 5 | export default function AuthorTooltipSizes() { 6 | return ( 7 | <> 8 | 16 | 24 | 32 | 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /content/docs/roadmap.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Roadmap" 3 | description: "Planned features and component development progress for GAIA UI" 4 | --- 5 | 6 | # Roadmap 7 | 8 | - [x] Composer with SlashCommandDropdown 9 | - [x] CLI command tab for different package managers 10 | - [x] Code Block 11 | - [x] Model Selector 12 | - [x] File Upload (as File Preview) 13 | - [x] Twitter Card 14 | - [ ] Email Preview 15 | - [x] Email Compose Card 16 | - [x] Calendar Event Card 17 | - [x] Todo task item 18 | - [x] Goal Graph (as Goal Card) 19 | - [x] File DropZone 20 | - [x] Workflow Card with Rotated Icons 21 | - [x] Notification Stack Card (as Notification Card) 22 | - [ ] Multi Step Navigation in Settings Menu 23 | - [x] Component Preview Tooltip (for sidebar hover previews) 24 | - [ ] Profile Holo Card 25 | 26 | --- 27 | 28 | **Have an idea?** [Submit a feature request](https://terrific-address-fab.notion.site/2c0023640e7b80c8b0f0ffba5046e852?pvs=105) 29 | -------------------------------------------------------------------------------- /components/ui/kbd.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | 3 | function Kbd({ className, ...props }: React.ComponentProps<"kbd">) { 4 | return ( 5 | 15 | ); 16 | } 17 | 18 | function KbdGroup({ className, ...props }: React.ComponentProps<"div">) { 19 | return ( 20 | 25 | ); 26 | } 27 | 28 | export { Kbd, KbdGroup }; 29 | -------------------------------------------------------------------------------- /components/previews/todo-item/priorities.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { TodoItem } from "@/registry/new-york/ui/TodoItem"; 4 | 5 | export default function TodoItemPriorities() { 6 | const todos = [ 7 | { 8 | id: "1", 9 | title: "Fix critical bug in production", 10 | priority: "high" as const, 11 | completed: false, 12 | }, 13 | { 14 | id: "2", 15 | title: "Update documentation", 16 | priority: "medium" as const, 17 | completed: false, 18 | }, 19 | { 20 | id: "3", 21 | title: "Refactor legacy code", 22 | priority: "low" as const, 23 | completed: false, 24 | }, 25 | { 26 | id: "4", 27 | title: "Review team submissions", 28 | priority: "none" as const, 29 | completed: false, 30 | }, 31 | ]; 32 | 33 | return ( 34 |
35 | {todos.map((todo) => ( 36 | 37 | ))} 38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /components/previews/component-preview-tooltip/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { ComponentPreviewTooltip } from "@/registry/new-york/ui/component-preview-tooltip"; 4 | 5 | export default function ComponentPreviewTooltipDefault() { 6 | return ( 7 |
8 | 9 | 15 | 16 | 17 | 18 | 24 | 25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /components/ui/theme-toggle.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useTheme } from "next-themes"; 4 | import * as React from "react"; 5 | import { HugeiconsIcon, Moon02Icon, Sun03Icon } from "@/components/icons"; 6 | import { Toggle } from "@/components/ui/toggle"; 7 | 8 | export function ThemeToggle() { 9 | const { theme, setTheme } = useTheme(); 10 | const [mounted, setMounted] = React.useState(false); 11 | 12 | React.useEffect(() => { 13 | setMounted(true); 14 | }, []); 15 | 16 | if (!mounted) { 17 | return null; 18 | } 19 | 20 | const isDark = theme === "dark"; 21 | 22 | return ( 23 | setTheme(pressed ? "dark" : "light")} 28 | > 29 | {isDark ? ( 30 | 31 | ) : ( 32 | 33 | )} 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /components/previews/todo-item/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { TodoItem } from "@/registry/new-york/ui/TodoItem"; 4 | 5 | // Static date for demo purposes - avoids React purity rules 6 | const DEMO_TOMORROW = new Date("2025-12-16T00:00:00Z"); 7 | 8 | export default function TodoItemDefault() { 9 | return ( 10 |
11 | 28 |
29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /components/previews/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Preview Components Registry 3 | * Auto-registers all preview components using dynamic imports 4 | */ 5 | 6 | import type { ComponentType } from "react"; 7 | 8 | type PreviewComponent = ComponentType; 9 | 10 | /** 11 | * Get a preview component by its name 12 | * Handles nested folder structure with path format: component/variant 13 | * Examples: "navbar-menu/basic" -> previews/navbar-menu/basic.tsx 14 | * "raised-button/default" -> previews/raised-button/default.tsx 15 | */ 16 | export async function getPreviewComponent( 17 | name: string, 18 | ): Promise { 19 | try { 20 | // Dynamic import based on path (folder/file) 21 | // Next.js will bundle all files in the previews directory 22 | const component_module = await import(`@/components/previews/${name}`); 23 | return component_module.default; 24 | } catch (error) { 25 | console.error(`Error loading preview component: ${name}`, error); 26 | return null; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /components/ui/input.tsx: -------------------------------------------------------------------------------- 1 | import type * as React from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | function Input({ className, type, ...props }: React.ComponentProps<"input">) { 6 | return ( 7 | 18 | ); 19 | } 20 | 21 | export { Input }; 22 | -------------------------------------------------------------------------------- /components/previews/calendar-event-card/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { 4 | CalendarEventCard, 5 | EventLocation, 6 | EventTime, 7 | EventTitle, 8 | } from "@/registry/new-york/ui/calendar-event-card"; 9 | 10 | export default function CalendarEventCardDefault() { 11 | return ( 12 |
13 | 14 | Team Standup 15 | 16 | Google Meet 17 | 18 | 19 | 20 | Product Review 21 | 22 | Conference Room A 23 | 24 | 25 | 26 | Client Call 27 | 28 | Zoom 29 | 30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /components/previews/weather-card/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { WeatherCard } from "@/registry/new-york/ui/weather-card"; 4 | 5 | const sampleWeatherData = { 6 | coord: { 7 | lon: -122.4194, 8 | lat: 37.7749, 9 | }, 10 | weather: [ 11 | { 12 | id: 800, 13 | main: "Clear", 14 | description: "clear sky", 15 | icon: "01d", 16 | }, 17 | ], 18 | main: { 19 | temp: 22, 20 | feels_like: 21, 21 | temp_min: 18, 22 | temp_max: 25, 23 | pressure: 1013, 24 | humidity: 60, 25 | }, 26 | visibility: 10000, 27 | wind: { 28 | speed: 3.5, 29 | deg: 180, 30 | }, 31 | dt: 1699641600, 32 | sys: { 33 | country: "US", 34 | sunrise: 1699622400, 35 | sunset: 1699660800, 36 | }, 37 | timezone: -28800, 38 | name: "San Francisco", 39 | location: { 40 | city: "San Francisco", 41 | country: "United States", 42 | region: "California", 43 | }, 44 | }; 45 | 46 | export default function WeatherCardDefault() { 47 | return ( 48 |
49 | 50 |
51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /components/previews/holo-card/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { HoloCard } from "@/registry/new-york/ui/holo-card"; 4 | 5 | const sampleProfileData = { 6 | name: "Elena Starweaver", 7 | subtitle: "The Curious Explorer", 8 | description: 9 | "Passionate about building beautiful user interfaces and exploring the intersection of design and technology. Always learning, always creating.", 10 | primaryId: "00042", 11 | secondaryInfo: "December 2024", 12 | badge: "Bluehaven", 13 | backgroundImage: 14 | "https://i.pinimg.com/1200x/27/0a/74/270a74bdc412f9eeae4d2403ebc9bd63.jpg", 15 | overlayColor: "#4f46e5", 16 | overlayOpacity: 30, 17 | }; 18 | 19 | const sampleBranding = { 20 | logo: "/media/text_w_logo_white.webp", 21 | logoAlt: "GAIA Logo", 22 | icon: "/media/experience logo.svg", 23 | iconAlt: "Experience Icon", 24 | }; 25 | 26 | export default function HoloCardDefault() { 27 | return ( 28 |
29 | 34 |
35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /components/previews/search-results-tabs/with-image-click.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useState } from "react"; 4 | 5 | import { SearchResultsTabs } from "@/registry/new-york/ui/search-results-tabs"; 6 | 7 | export default function SearchResultsTabsWithImageClick() { 8 | const [clickedImage, setClickedImage] = useState(null); 9 | 10 | const searchResults = { 11 | images: [ 12 | "https://images.unsplash.com/photo-1633356122544-f134324a6cee?w=800", 13 | "https://images.unsplash.com/photo-1677442136019-21780ecad995?w=800", 14 | "https://images.unsplash.com/photo-1620712943543-bcc4688e7485?w=800", 15 | ], 16 | }; 17 | 18 | return ( 19 |
20 | 24 | {clickedImage && ( 25 |
26 |

27 | Clicked: {clickedImage} 28 |

29 |
30 | )} 31 |
32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /components/previews/file-preview/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { FilePreview } from "@/registry/new-york/ui/file-preview"; 4 | 5 | export default function FilePreviewDefault() { 6 | const files = [ 7 | { 8 | id: "1", 9 | url: "https://images.unsplash.com/photo-1560807707-8cc77767d783?w=100&h=100&fit=crop", 10 | name: "photo.jpg", 11 | type: "image/jpeg", 12 | }, 13 | { 14 | id: "2", 15 | url: "#", 16 | name: "document.pdf", 17 | type: "application/pdf", 18 | }, 19 | { 20 | id: "3", 21 | url: "#", 22 | name: "spreadsheet.xlsx", 23 | type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", 24 | }, 25 | { 26 | id: "4", 27 | url: "#", 28 | name: "script.tsx", 29 | type: "text/typescript", 30 | }, 31 | { 32 | id: "5", 33 | url: "#", 34 | name: "archive.zip", 35 | type: "application/zip", 36 | }, 37 | ]; 38 | 39 | return ( 40 |
41 | console.log("Remove file:", id)} 44 | /> 45 |
46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /app/robots.ts: -------------------------------------------------------------------------------- 1 | import type { MetadataRoute } from "next"; 2 | import { siteConfig } from "@/lib/siteConfig"; 3 | 4 | /** 5 | * Generate robots.txt for search engine crawlers 6 | * Configures crawl rules, sitemaps, and special directives for major search engines 7 | */ 8 | export default function robots(): MetadataRoute.Robots { 9 | return { 10 | rules: [ 11 | { 12 | userAgent: "*", 13 | allow: "/", 14 | disallow: ["/api/", "/private/", "/_next/"], 15 | crawlDelay: 0, 16 | }, 17 | { 18 | userAgent: "Googlebot", 19 | allow: "/", 20 | disallow: ["/api/", "/private/"], 21 | }, 22 | { 23 | userAgent: "Googlebot-Image", 24 | allow: "/", 25 | }, 26 | { 27 | userAgent: "Bingbot", 28 | allow: "/", 29 | disallow: ["/api/", "/private/"], 30 | }, 31 | { 32 | userAgent: "Slurp", // Yahoo 33 | allow: "/", 34 | disallow: ["/api/", "/private/"], 35 | }, 36 | { 37 | userAgent: "DuckDuckBot", 38 | allow: "/", 39 | disallow: ["/api/", "/private/"], 40 | }, 41 | ], 42 | sitemap: `${siteConfig.url}/sitemap.xml`, 43 | host: siteConfig.url, 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /components/previews/code-block/languages.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { CodeBlock } from "@/registry/new-york/ui/code-block"; 4 | 5 | export default function CodeBlockLanguages() { 6 | const pythonCode = `def fibonacci(n): 7 | if n <= 1: 8 | return n 9 | return fibonacci(n-1) + fibonacci(n-2) 10 | 11 | print(fibonacci(10))`; 12 | 13 | const typescriptCode = `interface User { 14 | id: string; 15 | name: string; 16 | email: string; 17 | } 18 | 19 | const createUser = (data: User): User => { 20 | return { ...data }; 21 | };`; 22 | 23 | const bashCode = `#!/bin/bash 24 | # Deploy script 25 | echo "Building application..." 26 | npm run build 27 | echo "Deploying to production..." 28 | npm run deploy`; 29 | 30 | return ( 31 |
32 | 33 | {pythonCode} 34 | 35 | 36 | 37 | {typescriptCode} 38 | 39 | 40 | 41 | {bashCode} 42 | 43 |
44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /components/previews/message-bubble/grouped.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { MessageBubble } from "@/registry/new-york/ui/message-bubble"; 4 | 5 | export default function MessageBubbleGrouped() { 6 | return ( 7 |
8 | 13 | 18 | 23 | 28 | 29 | 34 | 39 |
40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /components/icons/github.tsx: -------------------------------------------------------------------------------- 1 | import type { SVGProps } from "react"; 2 | 3 | const GitHub = (props: SVGProps) => ( 4 | 5 | GitHub 6 | 13 | 14 | ); 15 | 16 | export { GitHub }; 17 | -------------------------------------------------------------------------------- /components/previews/link-preview/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { LinkPreview } from "@/registry/new-york/ui/link-preview"; 4 | 5 | export default function LinkPreviewDefault() { 6 | return ( 7 |
8 |

9 | GAIA is an open-source AI assistant designed to help you manage your 10 | digital life. Built with modern web technologies, it provides a seamless 11 | experience for task automation, email management, and calendar 12 | integration. Visit{" "} 13 | GAIA to learn more 14 | about the platform, or check out{" "} 15 | 16 | The Experience Company 17 | {" "} 18 | to see who's behind the project. The platform is actively 19 | maintained and welcomes contributions from developers around the world. 20 |
21 |
22 | Check out{" "} 23 | 24 | GAIA on GitHub 25 | {" "} 26 |

27 |
28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /components/previews/composer/with-files.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useState } from "react"; 4 | import { Composer, type UploadedFile } from "@/registry/new-york/ui/composer"; 5 | 6 | export default function ComposerWithFiles() { 7 | const [files, setFiles] = useState([ 8 | { 9 | id: "1", 10 | name: "document.pdf", 11 | type: "application/pdf", 12 | url: "", 13 | }, 14 | { 15 | id: "2", 16 | name: "screenshot.png", 17 | type: "image/png", 18 | url: "https://github.com/aryanranderiya.png", 19 | }, 20 | { 21 | id: "3", 22 | name: "data.json", 23 | type: "application/json", 24 | url: "", 25 | }, 26 | ]); 27 | 28 | const handleRemoveFile = (id: string) => { 29 | setFiles((prev) => prev.filter((f) => f.id !== id)); 30 | }; 31 | 32 | return ( 33 |
34 | { 39 | console.log("Message:", message); 40 | console.log("Files:", attachedFiles); 41 | }} 42 | /> 43 |
44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /components/core/copy-button.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import { Copy01Icon, HugeiconsIcon, Tick02Icon } from "@/components/icons"; 5 | import { Button } from "@/components/ui/button"; 6 | import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; 7 | 8 | interface CopyButtonProps { 9 | value: string; 10 | } 11 | 12 | export function CopyButton({ value }: CopyButtonProps) { 13 | const [copied, setCopied] = React.useState(false); 14 | 15 | const copy = async () => { 16 | await navigator.clipboard.writeText(value); 17 | setCopied(true); 18 | setTimeout(() => setCopied(false), 2000); 19 | }; 20 | 21 | return ( 22 | 23 | 24 | 36 | 37 | Copy Code to Clipboard 38 | 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /lib/siteConfig.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Site configuration - comprehensive site metadata 3 | */ 4 | export const siteConfig = { 5 | name: "GAIA UI", 6 | url: "https://ui.heygaia.io", 7 | ogImage: "https://ui.heygaia.io/og-image.png", 8 | description: 9 | "Beautiful, accessible React components from the GAIA AI assistant project. Free and open source UI library built with Radix UI and Tailwind CSS for building modern chatbots and AI interfaces.", 10 | tagline: "Open Source Components for AI Assistants", 11 | links: { 12 | github: "https://github.com/heygaia/ui", 13 | experienceCompany: "https://experience.heygaia.io", 14 | twitter: "https://twitter.com/trygaia", 15 | discord: "https://discord.heygaia.io", 16 | "feature-request": 17 | "https://terrific-address-fab.notion.site/2c0023640e7b80c8b0f0ffba5046e852?pvs=105", 18 | }, 19 | keywords: [ 20 | "GAIA UI", 21 | "React Components", 22 | "UI Library", 23 | "Component Library", 24 | "AI Assistant UI", 25 | "Chatbot Components", 26 | "Radix UI", 27 | "Tailwind CSS", 28 | "TypeScript", 29 | "Accessible Components", 30 | "Open Source", 31 | "Free Components", 32 | "Modern UI", 33 | "Design System", 34 | ], 35 | }; 36 | -------------------------------------------------------------------------------- /components/core/code-block.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import type * as React from "react"; 4 | import { CopyButton } from "@/components/core/copy-button"; 5 | import { cn } from "@/lib/utils"; 6 | 7 | interface CodeBlockProps extends React.HTMLAttributes { 8 | children: React.ReactNode; 9 | raw?: string; 10 | } 11 | 12 | export function CodeBlock({ 13 | className, 14 | children, 15 | raw, 16 | ...props 17 | }: CodeBlockProps) { 18 | const textContent = 19 | raw || 20 | (typeof children === "object" && 21 | children && 22 | "props" in children && 23 | typeof children.props === "object" && 24 | children.props && 25 | "children" in children.props 26 | ? String(children.props.children) 27 | : ""); 28 | 29 | return ( 30 |
31 |
38 | 				{children}
39 | 			
40 |
41 | 42 |
43 |
44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /content/docs/components.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Components" 3 | description: "Here you can find all the components available in the library. We are working on adding more components." 4 | --- 5 | 6 | import { ComponentPreviewTooltip } from "@/registry/new-york/ui/component-preview-tooltip"; 7 | import { getNavigation } from "@/lib/navigation"; 8 | import Link from "next/link"; 9 | 10 | export const ComponentsList = () => { 11 | const navigation = getNavigation(); 12 | const componentsSection = navigation.find( 13 | (section) => section.title === "Components" 14 | ); 15 | const components = componentsSection?.items || []; 16 | 17 | return ( 18 | 19 |
20 | {components.map((component, index) => { 21 | const componentName = component.href.split("/").pop(); 22 | return ( 23 | 24 | 25 |
26 | {component.title} 27 |
28 |
29 | 30 | ); 31 | })} 32 |
33 | ); }; 34 | 35 | 36 | -------------------------------------------------------------------------------- /components/previews/search-results-tabs/web-only.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { SearchResultsTabs } from "@/registry/new-york/ui/search-results-tabs"; 4 | 5 | export default function SearchResultsTabsWebOnly() { 6 | const searchResults = { 7 | web: [ 8 | { 9 | title: "TypeScript: JavaScript With Syntax For Types", 10 | url: "https://www.typescriptlang.org", 11 | content: 12 | "TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.", 13 | }, 14 | { 15 | title: "Tailwind CSS - Rapidly build modern websites", 16 | url: "https://tailwindcss.com", 17 | content: 18 | "A utility-first CSS framework packed with classes that can be composed to build any design, directly in your markup.", 19 | }, 20 | { 21 | title: "Vercel: Build and deploy the best web experiences", 22 | url: "https://vercel.com", 23 | content: 24 | "Vercel is the platform for frontend developers, providing the speed and reliability innovators need to create at the moment of inspiration.", 25 | }, 26 | ], 27 | }; 28 | 29 | return ( 30 |
31 | 32 |
33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /app/manifest.ts: -------------------------------------------------------------------------------- 1 | import type { MetadataRoute } from "next"; 2 | import { siteConfig } from "@/lib/siteConfig"; 3 | 4 | /** 5 | * Generate Web App Manifest for PWA support and better mobile experience 6 | * Includes shortcuts, categories, and proper theme handling 7 | */ 8 | export default function manifest(): MetadataRoute.Manifest { 9 | return { 10 | name: siteConfig.name, 11 | short_name: "GAIA UI", 12 | description: siteConfig.description, 13 | start_url: "/", 14 | scope: "/", 15 | display: "standalone", 16 | background_color: "#ffffff", 17 | theme_color: "#000000", 18 | orientation: "portrait-primary", 19 | categories: ["development", "productivity", "utilities", "design"], 20 | lang: "en", 21 | dir: "ltr", 22 | icons: [ 23 | { 24 | src: "/android-chrome-192x192.png", 25 | sizes: "192x192", 26 | type: "image/png", 27 | purpose: "any", 28 | }, 29 | { 30 | src: "/android-chrome-512x512.png", 31 | sizes: "512x512", 32 | type: "image/png", 33 | purpose: "any", 34 | }, 35 | { 36 | src: "/favicon-16x16.png", 37 | sizes: "16x16", 38 | type: "image/png", 39 | }, 40 | { 41 | src: "/favicon-32x32.png", 42 | sizes: "32x32", 43 | type: "image/png", 44 | }, 45 | ], 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /components/core/component-preview.tsx: -------------------------------------------------------------------------------- 1 | import type * as React from "react"; 2 | import { getPreviewComponent } from "@/components/previews"; 3 | import { getSourceCode } from "@/lib/source"; 4 | import { ComponentPreviewClient } from "./component-preview-client"; 5 | 6 | interface ComponentPreviewProps extends React.HTMLAttributes { 7 | name?: string; 8 | code?: string; 9 | children?: React.ReactNode; 10 | } 11 | 12 | /** 13 | * Server component for component preview 14 | * Reads source code and dynamically loads preview component 15 | */ 16 | export async function ComponentPreview({ 17 | name, 18 | code, 19 | children, 20 | ...props 21 | }: ComponentPreviewProps) { 22 | let sourceCode = code || ""; 23 | let PreviewComponent = null; 24 | 25 | // If name is provided, read code and dynamically load component 26 | // Name format: component/variant (e.g., "navbar-menu/basic") 27 | if (name) { 28 | const previewPath = `components/previews/${name}.tsx`; 29 | sourceCode = getSourceCode(previewPath); 30 | PreviewComponent = await getPreviewComponent(name); 31 | } 32 | 33 | return ( 34 | 35 | {PreviewComponent ? : children} 36 | 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /components/ui/avatar.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as AvatarPrimitive from "@radix-ui/react-avatar"; 4 | import type * as React from "react"; 5 | 6 | import { cn } from "@/lib/utils"; 7 | 8 | function Avatar({ 9 | className, 10 | ...props 11 | }: React.ComponentProps) { 12 | return ( 13 | 21 | ); 22 | } 23 | 24 | function AvatarImage({ 25 | className, 26 | ...props 27 | }: React.ComponentProps) { 28 | return ( 29 | 34 | ); 35 | } 36 | 37 | function AvatarFallback({ 38 | className, 39 | ...props 40 | }: React.ComponentProps) { 41 | return ( 42 | 50 | ); 51 | } 52 | 53 | export { Avatar, AvatarImage, AvatarFallback }; 54 | -------------------------------------------------------------------------------- /components/core/fullscreen-button.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import type * as React from "react"; 4 | import { FullScreenIcon, HugeiconsIcon } from "@/components/icons"; 5 | import { Button } from "@/components/ui/button"; 6 | import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog"; 7 | import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; 8 | 9 | interface FullscreenButtonProps { 10 | children: React.ReactNode; 11 | } 12 | 13 | export function FullscreenButton({ children }: FullscreenButtonProps) { 14 | return ( 15 | 16 | 17 | 18 | 19 | 26 | 27 | 28 | Open in Full Screen 29 | 30 | 31 |
32 | {children} 33 |
34 |
35 |
36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /components/previews/weather-card/units.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { WeatherCard } from "@/registry/new-york/ui/weather-card"; 4 | 5 | const sampleWeatherData = { 6 | coord: { lon: 2.3522, lat: 48.8566 }, 7 | weather: [ 8 | { 9 | id: 800, 10 | main: "Clear", 11 | description: "clear sky", 12 | icon: "01d", 13 | }, 14 | ], 15 | main: { 16 | temp: 20, 17 | feels_like: 19, 18 | temp_min: 18, 19 | temp_max: 22, 20 | pressure: 1013, 21 | humidity: 65, 22 | }, 23 | visibility: 10000, 24 | wind: { 25 | speed: 3.0, 26 | deg: 180, 27 | }, 28 | dt: 1699641600, 29 | sys: { 30 | country: "FR", 31 | sunrise: 1699600800, 32 | sunset: 1699636800, 33 | }, 34 | timezone: 3600, 35 | name: "Paris", 36 | location: { 37 | city: "Paris", 38 | country: "France", 39 | region: "Île-de-France", 40 | }, 41 | }; 42 | 43 | export default function WeatherCardUnits() { 44 | return ( 45 |
46 | 52 | 58 |
59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /components/previews/message-bubble/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { ChatMessage } from "@/registry/new-york/ui/message-bubble"; 4 | 5 | export default function MessageBubbleDefault() { 6 | const messages = [ 7 | { 8 | id: "1", 9 | variant: "received" as const, 10 | messages: ["Hey! How are you doing?"], 11 | timestamp: "10:30 AM", 12 | }, 13 | { 14 | id: "2", 15 | variant: "sent" as const, 16 | messages: ["I'm doing great! Just working on some new features."], 17 | timestamp: "10:31 AM", 18 | }, 19 | { 20 | id: "3", 21 | variant: "received" as const, 22 | messages: [ 23 | "That sounds exciting!", 24 | "What are you building?", 25 | "I'd love to hear more about it.", 26 | ], 27 | timestamp: "10:32 AM", 28 | }, 29 | { 30 | id: "4", 31 | variant: "sent" as const, 32 | messages: [ 33 | "I'm building a new UI component library!", 34 | "It has beautiful iOS-style message bubbles just like these 😊", 35 | ], 36 | timestamp: "10:33 AM", 37 | }, 38 | ]; 39 | 40 | return ( 41 |
42 | {messages.map((message) => ( 43 | 49 | ))} 50 |
51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /components/core/source-code.tsx: -------------------------------------------------------------------------------- 1 | import { getSourceCode } from "@/lib/source"; 2 | import { SourceCodeClient } from "./source-code-client"; 3 | 4 | interface SourceCodeProps { 5 | filePath: string; 6 | title?: string; 7 | language?: string; 8 | } 9 | 10 | /** 11 | * Generate a display title from the file path 12 | * Examples: 13 | * - "registry/new-york/ui/author-tooltip.tsx" -> "components/ui/author-tooltip.tsx" 14 | * - "lib/utils/colorUtils.ts" -> "lib/utils/colorUtils.ts" (unchanged) 15 | */ 16 | function generateTitle(filePath: string): string { 17 | // Convert registry paths to components paths 18 | return filePath.replace(/^registry\/[^/]+\//, "components/"); 19 | } 20 | 21 | /** 22 | * Server component to display source code from a file 23 | * Automatically reads the file and displays it with syntax highlighting 24 | * Title is auto-generated from filePath if not provided 25 | */ 26 | export function SourceCode({ filePath, title, language }: SourceCodeProps) { 27 | const code = getSourceCode(filePath); 28 | 29 | // Infer language from file extension if not provided 30 | const lang = language || filePath.split(".").pop() || "tsx"; 31 | 32 | // Auto-generate title from filePath if not provided 33 | const displayTitle = title || generateTitle(filePath); 34 | 35 | return ; 36 | } 37 | -------------------------------------------------------------------------------- /content/docs/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | description: Beautiful, accessible components built with Radix UI and Tailwind CSS. 4 | logo: /media/gaiaui_logo.png 5 | --- 6 | 7 | Welcome to GAIA UI - a collection of beautifully designed, accessible components that you can copy and paste into your apps. 8 | 9 | ## Philosophy 10 | 11 | GAIA UI is built on the following principles: 12 | 13 | - **Accessible** - Built with accessibility in mind, using Radix UI primitives. 14 | - **Customizable** - Styled with Tailwind CSS. Easily customize to match your brand. 15 | - **Copy and paste** - No complex installation. Just copy the code into your project. 16 | - **Modern** - Built with the latest React patterns and best practices. 17 | 18 | ## Features 19 | 20 | - Beautiful design with attention to detail 21 | - WCAG compliant components built with Radix UI 22 | - Built with TypeScript for type safety 23 | - Dark mode support out of the box 24 | - Mobile-first responsive design 25 | - Optimized for performance with minimal bundle size 26 | 27 | ## Tech Stack 28 | 29 | GAIA UI is built using: 30 | 31 | - [React](https://react.dev/) - UI library 32 | - [Tailwind CSS](https://tailwindcss.com/) - Styling 33 | - [Radix UI](https://www.radix-ui.com/) - Accessible component primitives 34 | - [TypeScript](https://www.typescriptlang.org/) - Type safety 35 | - [Next.js](https://nextjs.org/) - React framework 36 | -------------------------------------------------------------------------------- /registry/new-york/ui/weather-detail-item.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import type React from "react"; 4 | import type { ReactNode } from "react"; 5 | import { 6 | Tooltip, 7 | TooltipContent, 8 | TooltipProvider, 9 | TooltipTrigger, 10 | } from "@/components/ui/tooltip"; 11 | 12 | export interface WeatherDetailItemProps { 13 | icon: ReactNode; 14 | label: string; 15 | value: string; 16 | tooltipText?: string; 17 | highlight: string; 18 | } 19 | 20 | export const WeatherDetailItem: React.FC = ({ 21 | icon, 22 | label, 23 | value, 24 | tooltipText, 25 | highlight, 26 | }) => { 27 | return ( 28 |
29 | 30 | 31 | 32 |
33 |
34 |
{label}
35 |
{value}
36 |
37 |
{icon}
38 |
39 |
40 | {tooltipText && ( 41 | 42 |

{tooltipText}

43 |
44 | )} 45 |
46 |
47 |
48 | ); 49 | }; 50 | -------------------------------------------------------------------------------- /components/previews/model-selector/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useState } from "react"; 4 | import { 5 | type AIModel, 6 | ModelSelector, 7 | } from "@/registry/new-york/ui/model-selector"; 8 | 9 | const models: AIModel[] = [ 10 | { 11 | id: "gpt-4o", 12 | name: "GPT-4o", 13 | provider: "OpenAI", 14 | icon: "https://upload.wikimedia.org/wikipedia/commons/0/04/ChatGPT_logo.svg", 15 | isPro: true, 16 | description: "Most capable model for complex tasks", 17 | }, 18 | { 19 | id: "claude-3.5", 20 | name: "Claude 3.5 Sonnet", 21 | provider: "Anthropic", 22 | icon: "https://www.anthropic.com/favicon.ico", 23 | isPro: true, 24 | description: "Advanced reasoning and analysis", 25 | }, 26 | { 27 | id: "gemini-pro", 28 | name: "Gemini Pro", 29 | provider: "Google", 30 | icon: "https://www.gstatic.com/lamda/images/gemini_sparkle_v002_d4735304ff6292a690345.svg", 31 | description: "Fast and efficient for most tasks", 32 | }, 33 | { 34 | id: "llama-3", 35 | name: "Llama 3", 36 | provider: "Meta", 37 | description: "Open source and customizable", 38 | }, 39 | ]; 40 | 41 | export default function ModelSelectorDefault() { 42 | const [selectedModel, setSelectedModel] = useState(models[0]); 43 | 44 | return ( 45 |
46 | 51 |
52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /components/previews/message-bubble/grouped-rounded.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { MessageBubble } from "@/registry/new-york/ui/message-bubble"; 4 | 5 | export default function MessageBubbleGroupedRounded() { 6 | return ( 7 |
8 | 21 | 22 | 27 | 32 | 37 | 42 | 43 | 44 | 49 | 54 |
55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /registry/new-york/ui/todo-item.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | export type TodoPriority = "high" | "medium" | "low" | "none"; 4 | 5 | export interface TodoLabel { 6 | id: string; 7 | name: string; 8 | color?: string; 9 | } 10 | 11 | export interface TodoSubtask { 12 | id: string; 13 | title: string; 14 | completed: boolean; 15 | } 16 | 17 | export interface TodoProject { 18 | id: string; 19 | name: string; 20 | color?: string; 21 | } 22 | 23 | export interface TodoItemProps { 24 | id: string; 25 | title: string; 26 | description?: string; 27 | completed: boolean; 28 | priority: TodoPriority; 29 | dueDate?: string | Date; 30 | labels?: TodoLabel[]; 31 | subtasks?: TodoSubtask[]; 32 | project?: TodoProject; 33 | onToggleComplete?: (id: string, completed: boolean) => void; 34 | onClick?: (id: string) => void; 35 | isSelected?: boolean; 36 | className?: string; 37 | } 38 | 39 | export const priorityConfig = { 40 | high: { 41 | textColor: "text-red-500 dark:text-red-400", 42 | bgColor: "bg-red-500/10 dark:bg-red-400/10", 43 | borderColor: "border-red-500", 44 | }, 45 | medium: { 46 | textColor: "text-yellow-600 dark:text-yellow-400", 47 | bgColor: "bg-yellow-500/10 dark:bg-yellow-400/10", 48 | borderColor: "border-yellow-500", 49 | }, 50 | low: { 51 | textColor: "text-blue-500 dark:text-blue-400", 52 | bgColor: "bg-blue-500/10 dark:bg-blue-400/10", 53 | borderColor: "border-blue-500", 54 | }, 55 | none: { 56 | textColor: "text-zinc-500 dark:text-zinc-500", 57 | bgColor: "bg-zinc-500/10 dark:bg-zinc-500/10", 58 | borderColor: "border-zinc-400 dark:border-zinc-500", 59 | }, 60 | } as const; 61 | -------------------------------------------------------------------------------- /components/previews/navbar-menu/basic.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { 4 | CreditCardIcon, 5 | HugeiconsIcon, 6 | Idea01Icon, 7 | MapsIcon, 8 | Message01Icon, 9 | } from "@/components/icons"; 10 | import { NavbarWithMenu } from "@/registry/new-york/ui/navbar-menu"; 11 | 12 | export default function NavbarMenuBasic() { 13 | const sections = [ 14 | { 15 | id: "pages", 16 | gridLayout: "grid w-full grid-cols-2 gap-4", 17 | links: [ 18 | { 19 | label: "Get Started", 20 | href: "/login", 21 | description: "Sign Up / Login", 22 | icon: ( 23 | 28 | ), 29 | }, 30 | { 31 | label: "Use Cases", 32 | href: "/use-cases", 33 | description: "Discover workflows", 34 | icon: ( 35 | 36 | ), 37 | }, 38 | { 39 | label: "Pricing", 40 | href: "/pricing", 41 | description: "Choose your plan", 42 | icon: ( 43 | 48 | ), 49 | }, 50 | { 51 | label: "Roadmap", 52 | href: "/roadmap", 53 | description: "What's coming next", 54 | icon: ( 55 | 56 | ), 57 | }, 58 | ], 59 | }, 60 | ]; 61 | 62 | return ( 63 | 67 | ); 68 | } 69 | -------------------------------------------------------------------------------- /components/ui/toggle.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as TogglePrimitive from "@radix-ui/react-toggle"; 4 | import { cva, type VariantProps } from "class-variance-authority"; 5 | import type * as React from "react"; 6 | 7 | import { cn } from "@/lib/utils"; 8 | 9 | const toggleVariants = cva( 10 | "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap cursor-pointer", 11 | { 12 | variants: { 13 | variant: { 14 | default: "bg-transparent", 15 | outline: 16 | "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground", 17 | }, 18 | size: { 19 | default: "h-9 px-2 min-w-9", 20 | sm: "h-8 px-1.5 min-w-8", 21 | lg: "h-10 px-2.5 min-w-10", 22 | }, 23 | }, 24 | defaultVariants: { 25 | variant: "default", 26 | size: "default", 27 | }, 28 | }, 29 | ); 30 | 31 | function Toggle({ 32 | className, 33 | variant, 34 | size, 35 | ...props 36 | }: React.ComponentProps & 37 | VariantProps) { 38 | return ( 39 | 44 | ); 45 | } 46 | 47 | export { Toggle, toggleVariants }; 48 | -------------------------------------------------------------------------------- /components/ui/badge.tsx: -------------------------------------------------------------------------------- 1 | import { Slot } from "@radix-ui/react-slot"; 2 | import { cva, type VariantProps } from "class-variance-authority"; 3 | import type * as React from "react"; 4 | 5 | import { cn } from "@/lib/utils"; 6 | 7 | const badgeVariants = cva( 8 | "inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", 9 | { 10 | variants: { 11 | variant: { 12 | default: 13 | "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", 14 | secondary: 15 | "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", 16 | destructive: 17 | "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", 18 | outline: 19 | "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", 20 | }, 21 | }, 22 | defaultVariants: { 23 | variant: "default", 24 | }, 25 | }, 26 | ); 27 | 28 | function Badge({ 29 | className, 30 | variant, 31 | asChild = false, 32 | ...props 33 | }: React.ComponentProps<"span"> & 34 | VariantProps & { asChild?: boolean }) { 35 | const Comp = asChild ? Slot : "span"; 36 | 37 | return ( 38 | 43 | ); 44 | } 45 | 46 | export { Badge, badgeVariants }; 47 | -------------------------------------------------------------------------------- /components/previews/calendar-event-card/actions.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useState } from "react"; 4 | import { 5 | CalendarEventCard, 6 | type EventStatus, 7 | EventTime, 8 | EventTitle, 9 | } from "@/registry/new-york/ui/calendar-event-card"; 10 | 11 | export default function CalendarEventCardActions() { 12 | const [status1, setStatus1] = useState("idle"); 13 | const [status2] = useState("completed"); 14 | const [status3, setStatus3] = useState("idle"); 15 | 16 | const handleConfirm = (setStatus: (s: EventStatus) => void) => { 17 | setStatus("loading"); 18 | setTimeout(() => setStatus("completed"), 1500); 19 | }; 20 | 21 | return ( 22 |
23 | handleConfirm(setStatus1)} 28 | label="New Event" 29 | isDotted 30 | > 31 | Schedule Meeting 32 | 33 | 34 | 35 | {}} 40 | completedLabel="Confirmed" 41 | > 42 | Already Confirmed Event 43 | 44 | 45 | 46 | handleConfirm(setStatus3)} 52 | > 53 | Cancel Appointment 54 | 55 | 56 |
57 | ); 58 | } 59 | -------------------------------------------------------------------------------- /components/ui/popover.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as PopoverPrimitive from "@radix-ui/react-popover"; 4 | import type * as React from "react"; 5 | 6 | import { cn } from "@/lib/utils"; 7 | 8 | function Popover({ 9 | ...props 10 | }: React.ComponentProps) { 11 | return ; 12 | } 13 | 14 | function PopoverTrigger({ 15 | ...props 16 | }: React.ComponentProps) { 17 | return ; 18 | } 19 | 20 | function PopoverContent({ 21 | className, 22 | align = "center", 23 | sideOffset = 4, 24 | ...props 25 | }: React.ComponentProps) { 26 | return ( 27 | 28 | 38 | 39 | ); 40 | } 41 | 42 | function PopoverAnchor({ 43 | ...props 44 | }: React.ComponentProps) { 45 | return ; 46 | } 47 | 48 | export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }; 49 | -------------------------------------------------------------------------------- /components/ui/scroll-area.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"; 4 | import type * as React from "react"; 5 | 6 | import { cn } from "@/lib/utils"; 7 | 8 | function ScrollArea({ 9 | className, 10 | children, 11 | ...props 12 | }: React.ComponentProps) { 13 | return ( 14 | 19 | 23 | {children} 24 | 25 | 26 | 27 | 28 | ); 29 | } 30 | 31 | function ScrollBar({ 32 | className, 33 | orientation = "vertical", 34 | ...props 35 | }: React.ComponentProps) { 36 | return ( 37 | 50 | 54 | 55 | ); 56 | } 57 | 58 | export { ScrollArea, ScrollBar }; 59 | -------------------------------------------------------------------------------- /content/docs/components/raised-button.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Raised Button 3 | description: A beautiful 3D raised button with customizable colors and dynamic text contrast. 4 | --- 5 | 6 | 7 | 8 | ### Sizes 9 | 10 | 11 | 12 | ## Installation 13 | 14 | 15 | 16 | Automatic 17 | Manual 18 | 19 | 20 | {" "} 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Copy and paste the following code into your project. 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | ## Usage 38 | 39 | ```tsx 40 | import { RaisedButton } from "@/components/ui/raised-button"; 41 | 42 | export default function Example() { 43 | return Click me; 44 | } 45 | ``` 46 | 47 | ## Props 48 | 49 | | Prop | Type | Default | Description | 50 | | --------- | ----------------------------------- | --------- | ------------------------------------- | 51 | | size | "sm" \| "default" \| "lg" \| "icon" | "default" | Size of the button | 52 | | color | string | undefined | Custom color (hex, rgb, or CSS color) | 53 | | disabled | boolean | false | Whether the button is disabled | 54 | | className | string | undefined | Additional CSS classes | 55 | -------------------------------------------------------------------------------- /next.config.ts: -------------------------------------------------------------------------------- 1 | import createMDX from "@next/mdx"; 2 | import type { NextConfig } from "next"; 3 | 4 | const useProIcons = process.env.USE_PRO_ICONS === "true"; 5 | console.log( 6 | "🎨 USE_PRO_ICONS:", 7 | process.env.USE_PRO_ICONS, 8 | "→ Using", 9 | useProIcons ? "PRO" : "FREE", 10 | "icons", 11 | ); 12 | 13 | const nextConfig: NextConfig = { 14 | pageExtensions: ["js", "jsx", "md", "mdx", "ts", "tsx"], 15 | images: { 16 | dangerouslyAllowSVG: true, 17 | remotePatterns: [ 18 | { 19 | protocol: "https", 20 | hostname: "**", 21 | }, 22 | { 23 | protocol: "http", 24 | hostname: "**", 25 | }, 26 | ], 27 | }, 28 | // Turbopack config for icon alias 29 | ...(useProIcons && { 30 | turbopack: { 31 | resolveAlias: { 32 | "@hugeicons/core-free-icons": "@hugeicons-pro/core-solid-rounded", 33 | }, 34 | }, 35 | }), 36 | // Webpack config for icon alias (fallback if not using Turbopack) 37 | webpack: (config) => { 38 | if (useProIcons) { 39 | config.resolve.alias["@hugeicons/core-free-icons"] = 40 | "@hugeicons-pro/core-solid-rounded"; 41 | } 42 | return config; 43 | }, 44 | }; 45 | 46 | // MDX config with serializable plugin references (for Turbopack compatibility) 47 | const withMDX = createMDX({ 48 | options: { 49 | remarkPlugins: ["remark-gfm", "remark-frontmatter"], 50 | rehypePlugins: [ 51 | "rehype-slug", 52 | [ 53 | "rehype-pretty-code", 54 | { 55 | theme: { 56 | dark: "github-dark", 57 | light: "github-light", 58 | }, 59 | keepBackground: false, 60 | }, 61 | ], 62 | [ 63 | "rehype-autolink-headings", 64 | { 65 | properties: { 66 | className: ["anchor"], 67 | ariaLabel: "Link to section", 68 | }, 69 | }, 70 | ], 71 | ], 72 | }, 73 | }); 74 | 75 | export default withMDX(nextConfig); 76 | -------------------------------------------------------------------------------- /public/media/experience logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /content/docs/components/file-dropzone.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: File Dropzone 3 | description: A drag-and-drop file upload zone with preview, validation, and file management. 4 | --- 5 | 6 | 7 | 8 | ## Features 9 | 10 | - **Drag & Drop** - Drop files directly into the zone 11 | - **Click to Browse** - Fallback file input 12 | - **Image Preview** - Thumbnails for image files 13 | - **File Validation** - Size and count limits 14 | - **Remove Files** - Delete individual files 15 | 16 | ## Installation 17 | 18 | 19 | 20 | Automatic 21 | Manual 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | Copy and paste the following code into your project. 31 | 32 | 33 | 34 | 35 | 36 | 37 | ## Usage 38 | 39 | ```tsx 40 | import { FileDropzone } from "@/components/ui/file-dropzone"; 41 | 42 | export default function Example() { 43 | return ( 44 | console.log(files)} 46 | accept="image/*,.pdf" 47 | maxSize={5 * 1024 * 1024} 48 | maxFiles={5} 49 | /> 50 | ); 51 | } 52 | ``` 53 | 54 | ## Props 55 | 56 | | Prop | Type | Default | Description | 57 | | --- | --- | --- | --- | 58 | | onFilesDropped | (files) => void | - | Callback with dropped files | 59 | | accept | string | - | Accepted file types | 60 | | multiple | boolean | true | Allow multiple files | 61 | | maxSize | number | 10MB | Max file size in bytes | 62 | | maxFiles | number | 10 | Maximum number of files | 63 | | disabled | boolean | false | Disable the dropzone | 64 | -------------------------------------------------------------------------------- /content/docs/components/twitter-card.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Twitter Card 3 | description: A Twitter/X-style post card with author info, engagement metrics, and media support. 4 | --- 5 | 6 | 7 | 8 | ## Features 9 | 10 | - **Author Info** - Avatar, name, handle, verified badge 11 | - **Media Support** - Embedded images 12 | - **Quoted Tweets** - Nested quote support 13 | - **Engagement** - Likes, retweets, replies with actions 14 | 15 | ## Installation 16 | 17 | 18 | 19 | Automatic 20 | Manual 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Copy and paste the following code into your project. 30 | 31 | 32 | 33 | 34 | 35 | 36 | ## Usage 37 | 38 | ```tsx 39 | import { TwitterCard } from "@/components/ui/twitter-card"; 40 | 41 | export default function Example() { 42 | return ( 43 | 55 | ); 56 | } 57 | ``` 58 | 59 | ## Props 60 | 61 | | Prop | Type | Description | 62 | | --- | --- | --- | 63 | | author | Author | Author information | 64 | | content | string | Tweet content | 65 | | timestamp | Date \| string | Post time | 66 | | likes | number | Like count | 67 | | retweets | number | Retweet count | 68 | | replies | number | Reply count | 69 | | media | string | Media image URL | 70 | | quoted | QuotedTweet | Quoted tweet | 71 | -------------------------------------------------------------------------------- /components/previews/goal-card/default.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { GoalCard } from "@/registry/new-york/ui/goal-card"; 4 | 5 | // Static dates for demo purposes - avoids React purity rules 6 | const DEMO_DATES = { 7 | oneWeekAgo: new Date("2025-12-08T00:00:00Z"), 8 | twoWeeksAgo: new Date("2025-12-01T00:00:00Z"), 9 | today: new Date("2025-12-15T00:00:00Z"), 10 | }; 11 | 12 | export default function GoalCardDefault() { 13 | const goals = [ 14 | { 15 | id: "1", 16 | title: "Launch MVP by end of quarter", 17 | progress: 75, 18 | createdAt: DEMO_DATES.oneWeekAgo, 19 | roadmap: { 20 | title: "Launch MVP by end of quarter", 21 | nodes: [ 22 | { id: "1", title: "Design", isComplete: true }, 23 | { id: "2", title: "Development", isComplete: true }, 24 | { id: "3", title: "Testing", isComplete: true }, 25 | { id: "4", title: "Launch", isComplete: false }, 26 | ], 27 | }, 28 | }, 29 | { 30 | id: "2", 31 | title: "Complete user onboarding flow", 32 | progress: 100, 33 | createdAt: DEMO_DATES.twoWeeksAgo, 34 | roadmap: { 35 | title: "Complete user onboarding flow", 36 | nodes: [ 37 | { id: "1", title: "Research", isComplete: true }, 38 | { id: "2", title: "Design", isComplete: true }, 39 | { id: "3", title: "Implement", isComplete: true }, 40 | ], 41 | }, 42 | }, 43 | { 44 | id: "3", 45 | title: "Fix critical performance issues", 46 | progress: 30, 47 | createdAt: DEMO_DATES.today, 48 | roadmap: { 49 | title: "Fix critical performance issues", 50 | nodes: [ 51 | { id: "1", title: "Profile", isComplete: true }, 52 | { id: "2", title: "Optimize", isComplete: false }, 53 | { id: "3", title: "Test", isComplete: false }, 54 | ], 55 | }, 56 | }, 57 | ]; 58 | 59 | return ( 60 |
61 | {goals.map((goal) => ( 62 | console.log("View goal:", id)} 66 | /> 67 | ))} 68 |
69 | ); 70 | } 71 | -------------------------------------------------------------------------------- /content/docs/components/goal-card.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Goal Card 3 | description: A card component for displaying goal progress with status indicators and step tracking. 4 | --- 5 | 6 | 7 | 8 | ## Features 9 | 10 | - **Progress Bar** - Visual progress indicator 11 | - **Status Badge** - Not started, in progress, completed, at risk 12 | - **Step Tracking** - Shows completed/total steps 13 | - **Due Date** - Displays deadline 14 | 15 | ## Installation 16 | 17 | 18 | 19 | Automatic 20 | Manual 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Copy and paste the following code into your project. 30 | 31 | 32 | 33 | 34 | 35 | 36 | ## Usage 37 | 38 | ```tsx 39 | import { GoalCard } from "@/components/ui/goal-card"; 40 | 41 | export default function Example() { 42 | return ( 43 | console.log(id)} 53 | /> 54 | ); 55 | } 56 | ``` 57 | 58 | ## Props 59 | 60 | | Prop | Type | Description | 61 | | --- | --- | --- | 62 | | id | string | Unique identifier | 63 | | title | string | Goal title | 64 | | description | string | Optional description | 65 | | progress | number | Progress 0-100 | 66 | | status | GoalStatus | Current status | 67 | | steps | GoalStep[] | Array of steps | 68 | | dueDate | Date \| string | Due date | 69 | | onClick | (id) => void | Click handler | 70 | 71 | ### GoalStatus 72 | 73 | `"not_started"` | `"in_progress"` | `"completed"` | `"at_risk"` 74 | -------------------------------------------------------------------------------- /components/previews/search-results-tabs/news.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { MessageBubble } from "@/registry/new-york/ui/message-bubble"; 4 | import { SearchResultsTabs } from "@/registry/new-york/ui/search-results-tabs"; 5 | 6 | export default function SearchResultsTabsNews() { 7 | const searchResults = { 8 | web: [], 9 | images: [], 10 | news: [ 11 | { 12 | title: "AI Assistants Transform Productivity in 2025", 13 | url: "https://example.com/news/ai-productivity", 14 | content: 15 | "New AI assistant platforms are revolutionizing how people manage their digital workflows, with open-source solutions leading the charge in innovation and user adoption.", 16 | score: 0.95, 17 | date: "2025-11-08", 18 | }, 19 | { 20 | title: "Open Source Projects See Record Contributions", 21 | url: "https://example.com/news/open-source", 22 | content: 23 | "GitHub reports a 40% increase in contributions to open-source projects, with AI and productivity tools seeing the most growth across all categories.", 24 | score: 0.89, 25 | date: "2025-11-07", 26 | }, 27 | { 28 | title: "The Future of Personal AI: What's Next?", 29 | url: "https://example.com/news/future-ai", 30 | content: 31 | "Industry experts predict that personal AI assistants will become as ubiquitous as smartphones, with new capabilities emerging every quarter.", 32 | score: 0.87, 33 | date: "2025-11-06", 34 | }, 35 | ], 36 | }; 37 | 38 | return ( 39 |
40 | 41 | 42 | {/* iOS-style message bubbles */} 43 |
44 |
45 | 49 |
50 |
51 | 55 |
56 |
57 |
58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /components/ui/tooltip.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as TooltipPrimitive from "@radix-ui/react-tooltip"; 4 | import type * as React from "react"; 5 | 6 | import { cn } from "@/lib/utils"; 7 | 8 | function TooltipProvider({ 9 | delayDuration = 0, 10 | ...props 11 | }: React.ComponentProps) { 12 | return ( 13 | 18 | ); 19 | } 20 | 21 | function Tooltip({ 22 | ...props 23 | }: React.ComponentProps) { 24 | return ( 25 | 26 | 27 | 28 | ); 29 | } 30 | 31 | function TooltipTrigger({ 32 | ...props 33 | }: React.ComponentProps) { 34 | return ; 35 | } 36 | 37 | function TooltipContent({ 38 | className, 39 | sideOffset = 0, 40 | children, 41 | ...props 42 | }: React.ComponentProps) { 43 | return ( 44 | 45 | 54 | {children} 55 | 56 | 57 | 58 | ); 59 | } 60 | 61 | export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; 62 | -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "@fontsource/inter/400.css"; 2 | import "@fontsource/inter/500.css"; 3 | import "@fontsource/inter/600.css"; 4 | import "@fontsource/inter/700.css"; 5 | import type { Metadata } from "next"; 6 | import { Instrument_Serif } from "next/font/google"; 7 | import { ThemeProvider } from "next-themes"; 8 | import "./globals.css"; 9 | 10 | import { NavbarWrapper } from "@/components/core/navbar-wrapper"; 11 | import { 12 | generateOrganizationSchema, 13 | generateSEO, 14 | generateWebsiteSchema, 15 | } from "@/lib/seo"; 16 | 17 | const instrumentSerif = Instrument_Serif({ 18 | weight: "400", 19 | subsets: ["latin"], 20 | variable: "--font-instrument-serif", 21 | display: "swap", 22 | }); 23 | 24 | export const metadata: Metadata = { 25 | ...generateSEO(), 26 | metadataBase: new URL("https://ui.heygaia.io"), 27 | }; 28 | 29 | export default function RootLayout({ 30 | children, 31 | }: Readonly<{ 32 | children: React.ReactNode; 33 | }>) { 34 | const organizationSchema = generateOrganizationSchema(); 35 | const websiteSchema = generateWebsiteSchema(); 36 | 37 | return ( 38 | 43 | 44 | 49 | {/* JSON-LD Structured Data for better SEO */} 50 |