├── .npmrc ├── apps └── docs │ ├── .husky │ └── pre-commit │ ├── README.md │ ├── components │ ├── mdx │ │ └── index.ts │ ├── theme-toggle.tsx │ ├── animation │ │ └── container.tsx │ ├── ui │ │ ├── breadcrumb.tsx │ │ ├── Card.tsx │ │ ├── github-button.tsx │ │ ├── component-card.tsx │ │ ├── badge.tsx │ │ ├── popover.tsx │ │ ├── scroll-area.tsx │ │ ├── alert.tsx │ │ ├── progressive-blur.tsx │ │ ├── tooltip.tsx │ │ ├── tabs.tsx │ │ ├── dialog.tsx │ │ └── pixa-background.tsx │ ├── sections │ │ ├── tab │ │ │ └── home-components-tabs.tsx │ │ ├── footer.tsx │ │ ├── dia.tsx │ │ └── hero.tsx │ └── Table │ │ ├── TableComponent.tsx │ │ ├── SliderComponent.tsx │ │ ├── prop-information.tsx │ │ ├── PropsTable.tsx │ │ └── CodeBlock.tsx │ ├── app │ ├── ui │ │ ├── _components │ │ │ ├── cmdk │ │ │ │ ├── index.ts │ │ │ │ └── CommandMenuPrimitives.tsx │ │ │ ├── ActiveLink.tsx │ │ │ ├── HeaderClient.tsx │ │ │ ├── ToggleTheme.tsx │ │ │ ├── Breadcrumbs.tsx │ │ │ ├── ComponentView.tsx │ │ │ ├── CodeBlock.tsx │ │ │ ├── Header.tsx │ │ │ ├── CopyCode.tsx │ │ │ ├── CommandBlock.tsx │ │ │ ├── sidebar │ │ │ │ ├── SidebarButton.tsx │ │ │ │ └── Sidebar.tsx │ │ │ ├── Pagination.tsx │ │ │ ├── Tabs.tsx │ │ │ └── OnThisPage.tsx │ │ └── layout.tsx │ ├── sitemap.ts │ ├── buttons │ │ ├── 2 │ │ │ └── page.tsx │ │ ├── 3 │ │ │ └── page.tsx │ │ ├── 4 │ │ │ └── page.tsx │ │ ├── 5 │ │ │ └── page.tsx │ │ └── layout.tsx │ ├── _content │ │ ├── docs │ │ │ ├── meta.json │ │ │ ├── usage.mdx │ │ │ ├── index.mdx │ │ │ └── setup.mdx │ │ └── ui │ │ │ ├── meta.json │ │ │ └── dialog.mdx │ ├── robots.ts │ ├── not-found.tsx │ ├── page.tsx │ ├── api │ │ └── examples │ │ │ └── [path] │ │ │ └── route.ts │ ├── docs │ │ ├── layout.tsx │ │ └── _components │ │ │ └── sidebar │ │ │ ├── Sidebar.tsx │ │ │ └── SidebarButton.tsx │ ├── layout.tsx │ └── about │ │ └── page.tsx │ ├── public │ ├── noise.png │ ├── openGraph.png │ ├── favicon.svg │ └── logo.svg │ ├── postcss.config.mjs │ ├── lib │ ├── octokit.ts │ ├── utils.ts │ ├── fonts.ts │ ├── mdx.ts │ └── repo-utils.ts │ ├── utils │ ├── get-components.ts │ ├── get-file-content.ts │ ├── fonts.ts │ ├── shiki.ts │ └── detect-os.ts │ ├── next.config.ts │ ├── data │ ├── get-started.ts │ ├── techs.tsx │ ├── siteData.ts │ ├── updates.ts │ ├── buttons │ │ ├── 1 │ │ │ └── Button.ts │ │ ├── 2 │ │ │ └── Button.ts │ │ ├── 3 │ │ │ └── Button.ts │ │ ├── 4 │ │ │ └── Button.ts │ │ └── 5 │ │ │ └── Button.ts │ ├── modals │ │ └── 1 │ │ │ └── index.ts │ └── cards │ │ └── 1 │ │ └── index.ts │ ├── providers │ └── theme-provider.tsx │ ├── types │ ├── docs.ts │ ├── types.ts │ ├── index.ts │ └── components.ts │ ├── hooks │ ├── use-package-manager.ts │ ├── usePathnameClient.ts │ ├── useMobile.ts │ └── use-copy-to-clipboard.tsx │ ├── components.json │ ├── eslint.config.mjs │ ├── .gitignore │ ├── tsconfig.json │ ├── scripts │ ├── registry-schema.ts │ └── registry-components.ts │ ├── examples │ └── responsive-dialog-example.tsx │ ├── package.json │ └── styles │ └── pixa.css ├── pnpm-workspace.yaml ├── packages ├── eslint-config │ ├── README.md │ ├── package.json │ ├── base.js │ ├── react-internal.js │ └── next.js ├── ui │ ├── eslint.config.mjs │ ├── src │ │ ├── libs │ │ │ └── cn.ts │ │ ├── code.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ └── pixaui │ │ │ ├── button-slide-up.tsx │ │ │ ├── button-slide-right.tsx │ │ │ ├── button-slide-left.tsx │ │ │ └── animated-tabs.tsx │ ├── tsconfig.json │ ├── turbo │ │ └── generators │ │ │ ├── templates │ │ │ └── component.hbs │ │ │ └── config.ts │ └── package.json └── typescript-config │ ├── react-library.json │ ├── package.json │ ├── nextjs.json │ └── base.json ├── .vscode └── settings.json ├── vercel.json ├── turbo.json ├── .gitignore └── package.json /.npmrc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/docs/.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npx lint-staged -------------------------------------------------------------------------------- /apps/docs/README.md: -------------------------------------------------------------------------------- 1 | # pixa-ui 2 | 3 | Made with ❤️ and minimalism. -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "apps/*" 3 | - "packages/*" 4 | -------------------------------------------------------------------------------- /apps/docs/components/mdx/index.ts: -------------------------------------------------------------------------------- 1 | export { MDX } from "./MDXComponents"; 2 | -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/cmdk/index.ts: -------------------------------------------------------------------------------- 1 | export { CommandMenu } from "./CommandMenu"; 2 | -------------------------------------------------------------------------------- /apps/docs/public/noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lokendrakushwah12/pixa-ui/HEAD/apps/docs/public/noise.png -------------------------------------------------------------------------------- /packages/eslint-config/README.md: -------------------------------------------------------------------------------- 1 | # `@turbo/eslint-config` 2 | 3 | Collection of internal eslint configurations. 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.workingDirectories": [ 3 | { 4 | "mode": "auto" 5 | } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /apps/docs/public/openGraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lokendrakushwah12/pixa-ui/HEAD/apps/docs/public/openGraph.png -------------------------------------------------------------------------------- /apps/docs/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | const config = { 2 | plugins: ["@tailwindcss/postcss"], 3 | }; 4 | 5 | export default config; 6 | -------------------------------------------------------------------------------- /apps/docs/lib/octokit.ts: -------------------------------------------------------------------------------- 1 | import { Octokit } from '@octokit/rest'; 2 | 3 | export const octokit: Octokit = new Octokit({ 4 | auth: process.env.GITHUB_TOKEN, 5 | }); -------------------------------------------------------------------------------- /packages/ui/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { config } from "@repo/eslint-config/react-internal"; 2 | 3 | /** @type {import("eslint").Linter.Config} */ 4 | export default config; 5 | -------------------------------------------------------------------------------- /apps/docs/utils/get-components.ts: -------------------------------------------------------------------------------- 1 | import { getDocs } from "@/lib/mdx"; 2 | 3 | export const getComponents = getDocs().sort((a, b) => 4 | a.title.localeCompare(b.title), 5 | ); 6 | -------------------------------------------------------------------------------- /apps/docs/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | }; 6 | 7 | export default nextConfig; 8 | -------------------------------------------------------------------------------- /packages/ui/src/libs/cn.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from 'clsx' 2 | import { twMerge } from 'tailwind-merge' 3 | 4 | export const cn = (...inputs: ClassValue[]) => twMerge(clsx(...inputs)) 5 | -------------------------------------------------------------------------------- /apps/docs/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /packages/typescript-config/react-library.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "./base.json", 4 | "compilerOptions": { 5 | "jsx": "react-jsx" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "buildCommand": "pnpm turbo build --filter=pixa-ui", 3 | "outputDirectory": "apps/docs/.next", 4 | "installCommand": "pnpm install --no-frozen-lockfile", 5 | "framework": "nextjs" 6 | } 7 | -------------------------------------------------------------------------------- /apps/docs/app/sitemap.ts: -------------------------------------------------------------------------------- 1 | import { type MetadataRoute } from "next"; 2 | 3 | export default async function sitemap(): Promise { 4 | return [{ url: "https://pixaui.com", lastModified: new Date() }]; 5 | } 6 | -------------------------------------------------------------------------------- /packages/ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/react-library.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": ["src"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/typescript-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/typescript-config", 3 | "version": "0.0.0", 4 | "private": true, 5 | "license": "MIT", 6 | "publishConfig": { 7 | "access": "public" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /apps/docs/data/get-started.ts: -------------------------------------------------------------------------------- 1 | export const GET_STARTED = [ 2 | { 3 | name: "Installation", 4 | slug: "/ui/installation", 5 | }, 6 | { 7 | name: "CLI", 8 | slug: "/ui/cli", 9 | isBeta: true, 10 | }, 11 | ]; 12 | -------------------------------------------------------------------------------- /apps/docs/app/buttons/layout.tsx: -------------------------------------------------------------------------------- 1 | 2 | export default function Layout({ 3 | children, 4 | }: Readonly<{ children: React.ReactNode }>) { 5 | return ( 6 |
7 | {children} 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /packages/ui/turbo/generators/templates/component.hbs: -------------------------------------------------------------------------------- 1 | export const {{ pascalCase name }} = ({ children }: { children: React.ReactNode }) => { 2 | return ( 3 |
4 |

{{ pascalCase name }} Component

5 | {children} 6 |
7 | ); 8 | }; 9 | -------------------------------------------------------------------------------- /apps/docs/app/_content/docs/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "title": "Docs", 4 | "description": "General", 5 | "pages": [ 6 | "---Overview---", 7 | "index", 8 | "---Usage---", 9 | "setup", 10 | "usage" 11 | ] 12 | } -------------------------------------------------------------------------------- /packages/ui/src/code.tsx: -------------------------------------------------------------------------------- 1 | import { type JSX } from "react"; 2 | 3 | export function Code({ 4 | children, 5 | className, 6 | }: { 7 | children: React.ReactNode; 8 | className?: string; 9 | }): JSX.Element { 10 | return {children}; 11 | } 12 | -------------------------------------------------------------------------------- /apps/docs/app/robots.ts: -------------------------------------------------------------------------------- 1 | import { type MetadataRoute } from "next"; 2 | 3 | export default function robots(): MetadataRoute.Robots { 4 | return { 5 | rules: { 6 | userAgent: "*", 7 | allow: "/", 8 | }, 9 | sitemap: "https://pixaui.com/sitemap.xml", 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /apps/docs/utils/get-file-content.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | 4 | export function getFileContent(dir: string, fileName: string) { 5 | const filePath = path.join(process.cwd(), "src", dir, fileName); 6 | const fileContent = fs.readFileSync(filePath, "utf-8"); 7 | 8 | return fileContent; 9 | } 10 | -------------------------------------------------------------------------------- /apps/docs/providers/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { ThemeProvider as NextThemesProvider } from "next-themes"; 4 | 5 | export function ThemeProvider({ 6 | children, 7 | ...props 8 | }: React.ComponentProps) { 9 | return {children}; 10 | } -------------------------------------------------------------------------------- /apps/docs/app/_content/ui/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "title": "Ui", 4 | "description": "General", 5 | "pages": [ 6 | "---Buttons---", 7 | "button-ai", 8 | "badge", 9 | "---Dialogs---", 10 | "dialog", 11 | "card", 12 | "---Tabs---", 13 | "switch" 14 | ] 15 | } -------------------------------------------------------------------------------- /apps/docs/types/docs.ts: -------------------------------------------------------------------------------- 1 | export type Docs = { 2 | title: string; 3 | description: string; 4 | slug: string; 5 | date?: string; 6 | content: string; 7 | externalDocs?: string; 8 | externalApi?: string; 9 | author_image?: string; 10 | author_twitter?: string; 11 | banner?: string; 12 | author?: string; 13 | isNew?: boolean; 14 | }; 15 | -------------------------------------------------------------------------------- /apps/docs/types/types.ts: -------------------------------------------------------------------------------- 1 | export interface CardDataType { 2 | title: string; 3 | href: string; 4 | component?: React.ReactNode; 5 | download?: React.ReactNode; 6 | } 7 | 8 | export const tabs = [ 9 | "Buttons", 10 | "Cards", 11 | "Tabs", 12 | "Dialogs", 13 | "Extra", 14 | ] as const; 15 | export type TabType = (typeof tabs)[number]; 16 | -------------------------------------------------------------------------------- /packages/typescript-config/nextjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "./base.json", 4 | "compilerOptions": { 5 | "plugins": [{ "name": "next" }], 6 | "module": "ESNext", 7 | "moduleResolution": "Bundler", 8 | "allowJs": true, 9 | "jsx": "preserve", 10 | "noEmit": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /apps/docs/hooks/use-package-manager.ts: -------------------------------------------------------------------------------- 1 | import { useAtom } from "jotai"; 2 | import { atomWithStorage } from "jotai/utils"; 3 | 4 | type PackageManager = "npm" | "pnpm" | "yarn" | "bun"; 5 | 6 | const configAtom = atomWithStorage("packageManager", "npm"); 7 | 8 | export function usePackageManager() { 9 | return useAtom(configAtom); 10 | } 11 | -------------------------------------------------------------------------------- /apps/docs/types/index.ts: -------------------------------------------------------------------------------- 1 | export interface PersonalInfo { 2 | name: string; 3 | github: string; 4 | twitter: string; 5 | linkedin: string; 6 | } 7 | 8 | export interface LastUpdated { 9 | date: string; 10 | time: string; 11 | } 12 | 13 | export interface websiteData { 14 | personalInfo: PersonalInfo; 15 | about: string; 16 | lastUpdated: LastUpdated; 17 | } 18 | -------------------------------------------------------------------------------- /apps/docs/lib/fonts.ts: -------------------------------------------------------------------------------- 1 | import { Geist_Mono, Host_Grotesk } from "next/font/google"; 2 | 3 | const geistMono = Geist_Mono({ 4 | subsets: ["latin"], 5 | variable: "--font-geist-mono", 6 | display: "swap", 7 | }); 8 | 9 | const hostGrotesk = Host_Grotesk({ 10 | subsets: ["latin"], 11 | variable: "--font-host-grotesk", 12 | display: "swap", 13 | }); 14 | 15 | export { geistMono, hostGrotesk }; 16 | -------------------------------------------------------------------------------- /apps/docs/data/techs.tsx: -------------------------------------------------------------------------------- 1 | import { Icons } from "@/components/ui/Icons"; 2 | 3 | export const TECHS = [ 4 | { 5 | icon: , 6 | name: 'React', 7 | }, 8 | { 9 | icon: , 10 | name: 'tailwindcss', 11 | }, 12 | { 13 | icon: , 14 | name: 'Motion', 15 | }, 16 | { 17 | icon: , 18 | name: 'Radix UI', 19 | }, 20 | ] 21 | -------------------------------------------------------------------------------- /apps/docs/utils/fonts.ts: -------------------------------------------------------------------------------- 1 | import { Geist_Mono, Geist } from "next/font/google"; 2 | 3 | const geistMono = Geist_Mono({ 4 | subsets: ["latin"], 5 | variable: "--font-geist-mono", 6 | display: "swap", 7 | }); 8 | 9 | const geistSans = Geist({ 10 | subsets: ["latin"], 11 | variable: "--font-geist-sans", 12 | display: "swap", 13 | }); 14 | 15 | export const fontSans = geistSans; 16 | export const fontMono = geistMono; 17 | -------------------------------------------------------------------------------- /apps/docs/hooks/usePathnameClient.ts: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { usePathname as useNextPathname } from "next/navigation"; 4 | import { useEffect, useState } from "react"; 5 | 6 | export function usePathnameClient() { 7 | const pathname = useNextPathname(); 8 | const [clientPathname, setClientPathname] = useState(null); 9 | 10 | useEffect(() => { 11 | setClientPathname(pathname); 12 | }, [pathname]); 13 | 14 | return clientPathname; 15 | } -------------------------------------------------------------------------------- /packages/ui/src/button.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { ReactNode } from "react"; 4 | 5 | interface ButtonProps { 6 | children: ReactNode; 7 | className?: string; 8 | appName: string; 9 | } 10 | 11 | export const Button = ({ children, className, appName }: ButtonProps) => { 12 | return ( 13 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turborepo.com/schema.json", 3 | "ui": "tui", 4 | "tasks": { 5 | "build": { 6 | "dependsOn": ["^build"], 7 | "inputs": ["$TURBO_DEFAULT$", ".env*"], 8 | "outputs": [".next/**", "!.next/cache/**"] 9 | }, 10 | "lint": { 11 | "dependsOn": ["^lint"] 12 | }, 13 | "check-types": { 14 | "dependsOn": ["^check-types"] 15 | }, 16 | "dev": { 17 | "cache": false, 18 | "persistent": true 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /apps/docs/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 | } -------------------------------------------------------------------------------- /apps/docs/app/not-found.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | export default function Page() { 4 | return ( 5 |
6 |

404 - Page Not Found

7 |

The page you are looking for does not exist.

8 | 9 | Go back to Home 10 | 11 |
12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /apps/docs/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Footer from "@/components/sections/footer"; 2 | import Hero from "@/components/sections/hero"; 3 | import HomeComponentsTabs from "@/components/sections/tab/home-components-tabs"; 4 | import PixaBackground from "@/components/ui/pixa-background"; 5 | 6 | export default function Page() { 7 | return ( 8 |
9 | 10 | 11 | 12 |
13 |
14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /apps/docs/data/siteData.ts: -------------------------------------------------------------------------------- 1 | import { websiteData } from "@/types"; 2 | 3 | const siteData: websiteData = { 4 | personalInfo: { 5 | name: "Pixa/ui", 6 | github: "https://github.com/lokendrakushwah12/pixa-ui", 7 | twitter: "https://x.com/lokendratwt", 8 | linkedin: "https://www.linkedin.com/in/lokendrakushwah12/", 9 | }, 10 | about: 11 | "This is a Next.js template with tailwind CSS, TypeScript, Shadcn UI, and Motion.", 12 | lastUpdated: { 13 | date: "June 09, 2025", 14 | time: "00:42 IST", 15 | }, 16 | }; 17 | 18 | export default siteData; 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.js 7 | 8 | # Local env files 9 | .env 10 | .env.local 11 | .env.development.local 12 | .env.test.local 13 | .env.production.local 14 | 15 | # Testing 16 | coverage 17 | 18 | # Turbo 19 | .turbo 20 | 21 | # Vercel 22 | .vercel 23 | 24 | # Build Outputs 25 | .next/ 26 | out/ 27 | build 28 | dist 29 | 30 | 31 | # Debug 32 | npm-debug.log* 33 | yarn-debug.log* 34 | yarn-error.log* 35 | 36 | # Misc 37 | .DS_Store 38 | *.pem 39 | -------------------------------------------------------------------------------- /apps/docs/hooks/useMobile.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | export function useMobile(breakpoint: number = 768): boolean { 4 | const [isMobile, setIsMobile] = useState(false); 5 | 6 | useEffect(() => { 7 | const checkIsMobile = () => { 8 | setIsMobile(window.innerWidth < breakpoint); 9 | }; 10 | 11 | checkIsMobile(); 12 | window.addEventListener("resize", checkIsMobile); 13 | 14 | return () => { 15 | window.removeEventListener("resize", checkIsMobile); 16 | }; 17 | }, [breakpoint]); 18 | 19 | return isMobile; 20 | } 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pixa-ui", 3 | "private": true, 4 | "scripts": { 5 | "build": "turbo run build", 6 | "dev": "turbo run dev", 7 | "lint": "turbo run lint", 8 | "format": "prettier --write \"**/*.{ts,tsx,md}\"", 9 | "check-types": "turbo run check-types" 10 | }, 11 | "dependencies": { 12 | "@repo/ui": "workspace:*" 13 | }, 14 | "devDependencies": { 15 | "prettier": "^3.6.0", 16 | "turbo": "^2.5.4", 17 | "typescript": "5.8.2" 18 | }, 19 | "packageManager": "pnpm@9.0.0", 20 | "engines": { 21 | "node": ">=18" 22 | } 23 | } -------------------------------------------------------------------------------- /apps/docs/utils/shiki.ts: -------------------------------------------------------------------------------- 1 | import { createHighlighter } from 'shiki' 2 | 3 | type CodeProps = { 4 | code: string 5 | lang?: string 6 | } 7 | 8 | export async function codeToHtml({ code, lang = 'tsx' }: CodeProps) { 9 | const highlighter = await createHighlighter({ 10 | themes: ['github-dark', 'github-light'], 11 | langs: [lang], 12 | }) 13 | 14 | return highlighter.codeToHtml(code, { 15 | lang: lang, 16 | themes: { 17 | dark: 'github-dark', 18 | light: 'github-light', 19 | }, 20 | defaultColor: false, 21 | cssVariablePrefix: '--_s-', 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /packages/typescript-config/base.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "compilerOptions": { 4 | "declaration": true, 5 | "declarationMap": true, 6 | "esModuleInterop": true, 7 | "incremental": false, 8 | "isolatedModules": true, 9 | "lib": ["es2022", "DOM", "DOM.Iterable"], 10 | "module": "NodeNext", 11 | "moduleDetection": "force", 12 | "moduleResolution": "NodeNext", 13 | "noUncheckedIndexedAccess": true, 14 | "resolveJsonModule": true, 15 | "skipLibCheck": true, 16 | "strict": true, 17 | "target": "ES2022" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/docs/components/theme-toggle.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useTheme } from 'next-themes' 4 | import { ThemeToggleIcon } from './icons' 5 | import { Button } from './ui/Button' 6 | 7 | export function ThemeToggle() { 8 | const { setTheme } = useTheme() 9 | 10 | return ( 11 | 21 | ) 22 | } -------------------------------------------------------------------------------- /packages/ui/src/card.tsx: -------------------------------------------------------------------------------- 1 | import { type JSX } from "react"; 2 | 3 | export function Card({ 4 | className, 5 | title, 6 | children, 7 | href, 8 | }: { 9 | className?: string; 10 | title: string; 11 | children: React.ReactNode; 12 | href: string; 13 | }): JSX.Element { 14 | return ( 15 | 21 |

22 | {title} -> 23 |

24 |

{children}

25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /apps/docs/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { FlatCompat } from '@eslint/eslintrc'; 2 | import { dirname } from 'path'; 3 | import { fileURLToPath } from 'url'; 4 | 5 | const __filename = fileURLToPath(import.meta.url); 6 | const __dirname = dirname(__filename); 7 | 8 | const compat = new FlatCompat({ 9 | baseDirectory: __dirname, 10 | }); 11 | 12 | const eslintConfig = [ 13 | ...compat.extends('next/core-web-vitals', 'next/typescript'), 14 | 15 | // ignore @typescript-eslint/no-explicit-any 16 | { 17 | rules: { 18 | '@typescript-eslint/no-explicit-any': 'off', 19 | }, 20 | }, 21 | ]; 22 | 23 | export default eslintConfig; 24 | -------------------------------------------------------------------------------- /apps/docs/.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 | 43 | .env.local -------------------------------------------------------------------------------- /apps/docs/data/updates.ts: -------------------------------------------------------------------------------- 1 | type Update = { 2 | href: string; 3 | title: string; 4 | description: string; 5 | author: string; 6 | banner: string; 7 | author_image: string; 8 | date: string; 9 | }; 10 | 11 | export const UPDATES: Update[] = [ 12 | { 13 | href: "v2.0", 14 | title: "Introducing Pixa 2.0", 15 | description: 16 | "One of Pixa's biggest launches yet is here. This new version introduces powerful components with variant props, a new CLI, and a complete redesign.", 17 | author: "Lokendra Kushwah", 18 | banner: "/open-graphs/updates/v2.0.webp", 19 | author_image: "https://github.com/lokendra.png", 20 | date: "June 2, 2025", 21 | }, 22 | ]; 23 | -------------------------------------------------------------------------------- /apps/docs/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": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /packages/eslint-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/eslint-config", 3 | "version": "0.0.0", 4 | "type": "module", 5 | "private": true, 6 | "exports": { 7 | "./base": "./base.js", 8 | "./next-js": "./next.js", 9 | "./react-internal": "./react-internal.js" 10 | }, 11 | "devDependencies": { 12 | "@eslint/js": "^9.29.0", 13 | "@next/eslint-plugin-next": "^15.3.0", 14 | "eslint": "^9.29.0", 15 | "eslint-config-prettier": "^10.1.1", 16 | "eslint-plugin-only-warn": "^1.1.0", 17 | "eslint-plugin-react": "^7.37.5", 18 | "eslint-plugin-react-hooks": "^5.2.0", 19 | "eslint-plugin-turbo": "^2.5.0", 20 | "globals": "^16.2.0", 21 | "typescript": "^5.8.2", 22 | "typescript-eslint": "^8.34.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /apps/docs/hooks/use-copy-to-clipboard.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { useState } from "react"; 3 | 4 | interface UseCopyToClipboardProps { 5 | timeout?: number; 6 | } 7 | 8 | export function useCopyToClipboard({ 9 | timeout = 2000, 10 | }: UseCopyToClipboardProps) { 11 | const [isCopied, setIsCopied] = useState(false); 12 | 13 | const copyToClipboard = (value: string) => { 14 | if (typeof window === "undefined" || !navigator.clipboard?.writeText) { 15 | return; 16 | } 17 | 18 | if (!value) { 19 | return; 20 | } 21 | 22 | navigator.clipboard.writeText(value).then(() => { 23 | setIsCopied(true); 24 | 25 | setTimeout(() => { 26 | setIsCopied(false); 27 | }, timeout); 28 | }); 29 | }; 30 | 31 | return { isCopied, copyToClipboard }; 32 | } 33 | -------------------------------------------------------------------------------- /packages/eslint-config/base.js: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js"; 2 | import eslintConfigPrettier from "eslint-config-prettier"; 3 | import turboPlugin from "eslint-plugin-turbo"; 4 | import tseslint from "typescript-eslint"; 5 | import onlyWarn from "eslint-plugin-only-warn"; 6 | 7 | /** 8 | * A shared ESLint configuration for the repository. 9 | * 10 | * @type {import("eslint").Linter.Config[]} 11 | * */ 12 | export const config = [ 13 | js.configs.recommended, 14 | eslintConfigPrettier, 15 | ...tseslint.configs.recommended, 16 | { 17 | plugins: { 18 | turbo: turboPlugin, 19 | }, 20 | rules: { 21 | "turbo/no-undeclared-env-vars": "warn", 22 | }, 23 | }, 24 | { 25 | plugins: { 26 | onlyWarn, 27 | }, 28 | }, 29 | { 30 | ignores: ["dist/**"], 31 | }, 32 | ]; 33 | -------------------------------------------------------------------------------- /apps/docs/app/_content/ui/dialog.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Dialog" 3 | description: "Displays a simple or animated dialog, responsive to mobile." 4 | slug: "dialog" 5 | externalDocs: "https://radix-ui.com/primitives/docs/components/dialog" 6 | externalApi: "https://radix-ui.com/primitives/docs/components/dialog#api-reference" 7 | --- 8 | 9 | 10 | 11 |
12 | 13 | ## Installation 14 | 15 |
16 | 17 |
18 | 19 | 25 | 26 |
-------------------------------------------------------------------------------- /apps/docs/scripts/registry-schema.ts: -------------------------------------------------------------------------------- 1 | export type RegistryType = 2 | | 'registry:ui' 3 | | 'registry:hook' 4 | | 'registry:block' 5 | | 'registry:component' 6 | | 'registry:lib' 7 | | 'registry:page' 8 | | 'registry:file'; 9 | 10 | export interface RegistryFile { 11 | path: string; 12 | content: string; 13 | type: RegistryType; 14 | } 15 | 16 | export interface TailwindConfig { 17 | config?: Record; 18 | } 19 | 20 | export interface CssVars { 21 | light: Record; 22 | dark: Record; 23 | } 24 | 25 | export interface Schema { 26 | name: string; 27 | type: RegistryType; 28 | registryDependencies?: string[]; 29 | dependencies?: string[]; 30 | devDependencies?: string[]; 31 | tailwind?: TailwindConfig; 32 | cssVars?: CssVars; 33 | files: RegistryFile[]; 34 | componentName?: string; 35 | description?: string; 36 | } 37 | -------------------------------------------------------------------------------- /apps/docs/scripts/registry-components.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import { RegistryType, Schema } from "./registry-schema"; 3 | 4 | type ComponentDefinition = Partial< 5 | Pick< 6 | Schema, 7 | | "dependencies" 8 | | "devDependencies" 9 | | "registryDependencies" 10 | | "cssVars" 11 | | "tailwind" 12 | > 13 | > & { 14 | name: string; 15 | path: string; 16 | description: string; 17 | files?: { 18 | name: string; 19 | path: string; 20 | type?: RegistryType; 21 | }[]; 22 | }; 23 | 24 | export const components: ComponentDefinition[] = [ 25 | { 26 | name: "animated-tabs", 27 | path: path.join(__dirname, "../components/core/animated-tabs.tsx"), 28 | registryDependencies: [], 29 | dependencies: ["motion"], 30 | description: 31 | "A tab component with smooth animations for switching between different content sections.", 32 | }, 33 | ]; 34 | -------------------------------------------------------------------------------- /apps/docs/types/components.ts: -------------------------------------------------------------------------------- 1 | export interface Component { 2 | id: string; 3 | name: string; 4 | description: string; 5 | component?: React.ElementType; 6 | code?: string; // Optional code snippet for the component 7 | props?: ComponentProp[]; // Optional props for the component 8 | dependencies?: string[]; // Optional dependencies required for the component 9 | examples?: example[]; // Optional example usage of the component 10 | previewImage?: string; // Optional preview for grid view 11 | } 12 | 13 | export interface example { 14 | name: string; 15 | code: string; 16 | description: string; 17 | } 18 | 19 | export interface ComponentCategory { 20 | id: string; 21 | name: string; 22 | description: string; 23 | components: Component[]; 24 | } 25 | 26 | export interface ComponentProp { 27 | name: string; 28 | type: string; 29 | required?: boolean; 30 | default?: string; 31 | description?: string; 32 | } -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/ActiveLink.tsx: -------------------------------------------------------------------------------- 1 | // components/ActiveLink.tsx 2 | "use client"; 3 | import Link from "next/link"; 4 | import { usePathname } from "next/navigation"; 5 | import { cn } from "@/lib/utils"; 6 | 7 | interface ActiveLinkProps { 8 | href: string; 9 | children: React.ReactNode; 10 | className?: string; 11 | } 12 | 13 | export function ActiveLink({ href, children, className }: ActiveLinkProps) { 14 | const pathname = usePathname(); 15 | const isActive = pathname === href; 16 | 17 | return ( 18 | 28 | {children} 29 | 30 | ); 31 | } -------------------------------------------------------------------------------- /apps/docs/app/api/examples/[path]/route.ts: -------------------------------------------------------------------------------- 1 | import { readFile } from 'node:fs/promises'; 2 | import { join } from 'node:path'; 3 | import { NextRequest, NextResponse } from 'next/server'; 4 | 5 | export async function GET( 6 | request: NextRequest, 7 | { params }: { params: Promise<{ path: string }> } 8 | ) { 9 | try { 10 | const { path } = await params; 11 | 12 | // Construct the path to the example file 13 | const examplePath = join( 14 | process.cwd(), 15 | 'examples', 16 | `${path}.tsx` 17 | ); 18 | 19 | // Read the example file 20 | const code = await readFile(examplePath, 'utf-8'); 21 | 22 | // Return the code as plain text 23 | return new NextResponse(code, { 24 | headers: { 25 | 'Content-Type': 'text/plain', 26 | }, 27 | }); 28 | } catch (error) { 29 | console.error('Error reading example file:', error); 30 | return new NextResponse('Example not found', { status: 404 }); 31 | } 32 | } -------------------------------------------------------------------------------- /apps/docs/utils/detect-os.ts: -------------------------------------------------------------------------------- 1 | const MAC_OS_PLATFORMS = ["Macintosh", "MacIntel", "MacPPC", "Mac68K"]; 2 | const WINDOWS_PLATFORMS = ["Win32", "Win64", "Windows", "WinCE"]; 3 | const IOS_PLATFORMS = ["iPhone", "iPad", "iPod"]; 4 | 5 | function isPlatform(platform: string, platformsArray: string[]) { 6 | return platformsArray.includes(platform); 7 | } 8 | 9 | export function detectOS() { 10 | if (typeof window === "undefined") { 11 | return "Unknown OS - possibly server-side"; 12 | } 13 | 14 | const userAgent = window?.navigator.userAgent; 15 | const platform = window?.navigator.platform; 16 | 17 | if (isPlatform(platform, MAC_OS_PLATFORMS)) { 18 | return "Mac OS"; 19 | } 20 | 21 | if (isPlatform(platform, IOS_PLATFORMS)) { 22 | return "iOS"; 23 | } 24 | 25 | if (isPlatform(platform, WINDOWS_PLATFORMS)) { 26 | return "Windows"; 27 | } 28 | 29 | if (/Android/.test(userAgent)) { 30 | return "Android"; 31 | } 32 | 33 | if (/Linux/.test(platform)) { 34 | return "Linux"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/ui/turbo/generators/config.ts: -------------------------------------------------------------------------------- 1 | import type { PlopTypes } from "@turbo/gen"; 2 | 3 | // Learn more about Turborepo Generators at https://turborepo.com/docs/guides/generating-code 4 | 5 | export default function generator(plop: PlopTypes.NodePlopAPI): void { 6 | // A simple generator to add a new React component to the internal UI library 7 | plop.setGenerator("react-component", { 8 | description: "Adds a new react component", 9 | prompts: [ 10 | { 11 | type: "input", 12 | name: "name", 13 | message: "What is the name of the component?", 14 | }, 15 | ], 16 | actions: [ 17 | { 18 | type: "add", 19 | path: "src/{{kebabCase name}}.tsx", 20 | templateFile: "templates/component.hbs", 21 | }, 22 | { 23 | type: "append", 24 | path: "package.json", 25 | pattern: /"exports": {(?)/g, 26 | template: ' "./{{kebabCase name}}": "./src/{{kebabCase name}}.tsx",', 27 | }, 28 | ], 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /apps/docs/public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/docs/components/animation/container.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | import { motion } from "motion/react"; 5 | 6 | interface Props { 7 | className?: string; 8 | children: React.ReactNode; 9 | delay?: number; 10 | reverse?: boolean; 11 | simple?: boolean; 12 | } 13 | 14 | const Container = ({ 15 | children, 16 | className, 17 | delay = 0.2, 18 | reverse, 19 | simple, 20 | }: Props) => { 21 | return ( 22 | 37 | {children} 38 | 39 | ); 40 | }; 41 | 42 | export default Container; 43 | -------------------------------------------------------------------------------- /apps/docs/public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/ui", 3 | "version": "0.0.0", 4 | "private": true, 5 | "exports": { 6 | "./*": "./src/*.tsx" 7 | }, 8 | "scripts": { 9 | "lint": "eslint . --max-warnings 0", 10 | "generate:component": "turbo gen react-component", 11 | "check-types": "tsc --noEmit" 12 | }, 13 | "devDependencies": { 14 | "@repo/eslint-config": "workspace:*", 15 | "@repo/typescript-config": "workspace:*", 16 | "@turbo/gen": "^2.5.0", 17 | "@types/node": "^22.15.3", 18 | "@types/react": "19.1.0", 19 | "@types/react-dom": "19.1.1", 20 | "eslint": "^9.29.0", 21 | "typescript": "5.8.2" 22 | }, 23 | "dependencies": { 24 | "@radix-ui/react-slot": "^1.2.3", 25 | "class-variance-authority": "^0.7.1", 26 | "clsx": "^2.1.1", 27 | "lucide-react": "^0.487.0", 28 | "motion": "^12.19.1", 29 | "react": "^19.1.0", 30 | "react-dom": "^19.1.0", 31 | "react-use-measure": "^2.1.7", 32 | "tailwind-merge": "^3.2.0", 33 | "tailwind-variants": "^1.0.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /apps/docs/components/ui/breadcrumb.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | import { ChevronRight } from "lucide-react"; 3 | 4 | interface BreadcrumbItem { 5 | label: string; 6 | href?: string; 7 | } 8 | 9 | interface BreadcrumbProps { 10 | items: BreadcrumbItem[]; 11 | } 12 | 13 | export const Breadcrumb = ({ items }: BreadcrumbProps) => { 14 | return ( 15 | 34 | ); 35 | }; -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/HeaderClient.tsx: -------------------------------------------------------------------------------- 1 | // components/HeaderClient.tsx 2 | "use client"; 3 | import { ProgressiveBlur } from "@/components/ui/progressive-blur"; 4 | import { cn } from "@/lib/utils"; 5 | import { usePathname } from "next/navigation"; 6 | import { ReactNode, useEffect } from "react"; 7 | 8 | interface HeaderClientProps { 9 | children: ReactNode; 10 | } 11 | 12 | export function HeaderClient({ children }: HeaderClientProps) { 13 | const pathname = usePathname(); 14 | const isDocsPage = pathname.startsWith("/ui"); 15 | 16 | function handleScroll() { 17 | // Scroll handling logic can be added here if needed 18 | } 19 | 20 | useEffect(() => { 21 | window.addEventListener("scroll", handleScroll); 22 | return () => window.removeEventListener("scroll", handleScroll); 23 | }, []); 24 | 25 | return ( 26 |
32 | 33 | {children} 34 |
35 | ); 36 | } -------------------------------------------------------------------------------- /apps/docs/components/sections/tab/home-components-tabs.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | const tabs = ["buttons", "cards", "tabs", "dialogs", "extra"] as const; 4 | 5 | const ComponentsPage = () => { 6 | 7 | return ( 8 |
9 |
10 | {tabs.map((tab) => ( 11 |
15 |
18 |
19 | {tab.charAt(0).toUpperCase() + tab.slice(1).toLowerCase()} 20 |

21 | 12 components 22 |

23 |
24 |
25 | ))} 26 |
27 |
28 | ); 29 | }; 30 | 31 | export default ComponentsPage; -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/ToggleTheme.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useTheme } from "next-themes"; 4 | 5 | import { Icons } from "@/components/ui/Icons"; 6 | 7 | import { cn } from "@/lib/utils"; 8 | 9 | export function ToggleTheme() { 10 | const { setTheme, resolvedTheme: theme } = useTheme(); 11 | 12 | return ( 13 | 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /packages/eslint-config/react-internal.js: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js"; 2 | import eslintConfigPrettier from "eslint-config-prettier"; 3 | import tseslint from "typescript-eslint"; 4 | import pluginReactHooks from "eslint-plugin-react-hooks"; 5 | import pluginReact from "eslint-plugin-react"; 6 | import globals from "globals"; 7 | import { config as baseConfig } from "./base.js"; 8 | 9 | /** 10 | * A custom ESLint configuration for libraries that use React. 11 | * 12 | * @type {import("eslint").Linter.Config[]} */ 13 | export const config = [ 14 | ...baseConfig, 15 | js.configs.recommended, 16 | eslintConfigPrettier, 17 | ...tseslint.configs.recommended, 18 | pluginReact.configs.flat.recommended, 19 | { 20 | languageOptions: { 21 | ...pluginReact.configs.flat.recommended.languageOptions, 22 | globals: { 23 | ...globals.serviceworker, 24 | ...globals.browser, 25 | }, 26 | }, 27 | }, 28 | { 29 | plugins: { 30 | "react-hooks": pluginReactHooks, 31 | }, 32 | settings: { react: { version: "detect" } }, 33 | rules: { 34 | ...pluginReactHooks.configs.recommended.rules, 35 | // React scope no longer necessary with new JSX transform. 36 | "react/react-in-jsx-scope": "off", 37 | }, 38 | }, 39 | ]; 40 | -------------------------------------------------------------------------------- /packages/ui/src/pixaui/button-slide-up.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import React from "react"; 3 | 4 | interface ButtonSlideUpProps { 5 | title: string; 6 | bgColor?: string; 7 | className?: string; 8 | style?: React.CSSProperties; 9 | } 10 | 11 | const ButtonSlideUp: React.FC = ({ 12 | title, 13 | bgColor = "#f0900f", 14 | className = "", 15 | style, 16 | }) => { 17 | return ( 18 |
22 |
26 | 27 |
28 |

29 | {title} 30 |

31 |

32 | {title} 33 |

34 |
35 |
36 | ); 37 | }; 38 | 39 | export default ButtonSlideUp; 40 | -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/Breadcrumbs.tsx: -------------------------------------------------------------------------------- 1 | import { ChevronRight } from 'lucide-react' 2 | import Link from 'next/link' 3 | 4 | type Breadcrumbs = { 5 | category?: string 6 | groupName: string 7 | backLink?: string 8 | currentPage: string 9 | } 10 | 11 | export function Breadcrumbs({ 12 | category, 13 | groupName, 14 | backLink, 15 | currentPage, 16 | }: Breadcrumbs) { 17 | return ( 18 |
19 | {category && ( 20 | <> 21 | 22 | {category} 23 | 24 | 25 | 26 | )} 27 | {backLink ? ( 28 | 32 | {groupName} 33 | 34 | ) : ( 35 | 36 | {groupName} 37 | 38 | )} 39 | 40 | {currentPage} 41 |
42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /apps/docs/data/buttons/2/Button.ts: -------------------------------------------------------------------------------- 1 | export const codeData = `import { ButtonV2 } from "@pixaui/button-v2"; 2 | 3 | function App() { 4 | return ( 5 | 10 | ); 11 | } 12 | 13 | export default App;`; 14 | 15 | export const installationData = `npm i @pixaui/button-v2`; 16 | 17 | export const data = [ 18 | { 19 | name: "title", 20 | nameDetails: "Text to display on the button", 21 | type: "string", 22 | typeDetails: "The text content for the button", 23 | default: `"ButtonV2"`, 24 | }, 25 | { 26 | name: "bgColor", 27 | nameDetails: "Background color for the animated hover effect", 28 | type: "string", 29 | typeDetails: "Any valid CSS color value", 30 | default: `"bg-[#f0900f]"`, 31 | }, 32 | { 33 | name: "className", 34 | nameDetails: "Additional classes for styling the button container", 35 | type: "string", 36 | typeDetails: "CSS class names for custom styling", 37 | default: `""`, 38 | }, 39 | { 40 | name: "style", 41 | nameDetails: "Inline styles for custom styling", 42 | type: "CSSProperties", 43 | typeDetails: "An object containing CSS properties", 44 | default: "undefined", 45 | }, 46 | ]; 47 | -------------------------------------------------------------------------------- /apps/docs/components/ui/Card.tsx: -------------------------------------------------------------------------------- 1 | import { useRouter } from "next/navigation"; 2 | import React from "react"; 3 | 4 | const Card = ({ 5 | title, 6 | href, 7 | children, 8 | }: { 9 | title: React.ReactNode; 10 | href: string; 11 | children?: React.ReactNode; 12 | }) => { 13 | const router = useRouter(); 14 | 15 | const handleClick = () => { 16 | router.push(href); 17 | }; 18 | 19 | return ( 20 |
21 |
26 |
e.stopPropagation()} 28 | onMouseDown={(e) => e.stopPropagation()} 29 | > 30 | {children} 31 |
32 |
33 |

34 | {title} 35 |

36 |
37 | ); 38 | }; 39 | 40 | export default Card; 41 | -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/ComponentView.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useState } from "react"; 4 | 5 | import { motion } from "motion/react"; 6 | 7 | import { RotateCwIcon } from "lucide-react"; 8 | 9 | import { cn } from "@/lib/utils"; 10 | 11 | type ComponentViewProps = { 12 | isReloadAnimation?: boolean; 13 | } & React.ComponentProps<"div">; 14 | 15 | export function ComponentView({ 16 | isReloadAnimation, 17 | className, 18 | children, 19 | }: ComponentViewProps) { 20 | const [reloadKey, setReloadKey] = useState(0); 21 | 22 | function handleReload() { 23 | setReloadKey((prevKey) => prevKey + 1); 24 | } 25 | 26 | return ( 27 |
33 | {isReloadAnimation ?
{children}
: children} 34 | {isReloadAnimation && ( 35 |
36 | 42 | 43 | 44 |
45 | )} 46 |
47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /packages/eslint-config/next.js: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js"; 2 | import eslintConfigPrettier from "eslint-config-prettier"; 3 | import tseslint from "typescript-eslint"; 4 | import pluginReactHooks from "eslint-plugin-react-hooks"; 5 | import pluginReact from "eslint-plugin-react"; 6 | import globals from "globals"; 7 | import pluginNext from "@next/eslint-plugin-next"; 8 | import { config as baseConfig } from "./base.js"; 9 | 10 | /** 11 | * A custom ESLint configuration for libraries that use Next.js. 12 | * 13 | * @type {import("eslint").Linter.Config[]} 14 | * */ 15 | export const nextJsConfig = [ 16 | ...baseConfig, 17 | js.configs.recommended, 18 | eslintConfigPrettier, 19 | ...tseslint.configs.recommended, 20 | { 21 | ...pluginReact.configs.flat.recommended, 22 | languageOptions: { 23 | ...pluginReact.configs.flat.recommended.languageOptions, 24 | globals: { 25 | ...globals.serviceworker, 26 | }, 27 | }, 28 | }, 29 | { 30 | plugins: { 31 | "@next/next": pluginNext, 32 | }, 33 | rules: { 34 | ...pluginNext.configs.recommended.rules, 35 | ...pluginNext.configs["core-web-vitals"].rules, 36 | }, 37 | }, 38 | { 39 | plugins: { 40 | "react-hooks": pluginReactHooks, 41 | }, 42 | settings: { react: { version: "detect" } }, 43 | rules: { 44 | ...pluginReactHooks.configs.recommended.rules, 45 | // React scope no longer necessary with new JSX transform. 46 | "react/react-in-jsx-scope": "off", 47 | }, 48 | }, 49 | ]; 50 | -------------------------------------------------------------------------------- /apps/docs/components/Table/TableComponent.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | interface TableProps { 4 | columns: { header: string; key: string }[]; 5 | data: { [key: string]: string }[]; 6 | } 7 | 8 | const TableComponent: React.FC = ({ columns, data }) => { 9 | return ( 10 |
11 | 12 | 13 | 14 | {columns.map((column) => ( 15 | 21 | ))} 22 | 23 | 24 | 25 | {data.map((row, rowIndex) => ( 26 | 27 | {columns.map((column) => ( 28 | 34 | ))} 35 | 36 | ))} 37 | 38 |
19 | {column.header} 20 |
32 | {row[column.key]} 33 |
39 |
40 | ); 41 | }; 42 | 43 | export default TableComponent; 44 | -------------------------------------------------------------------------------- /apps/docs/data/modals/1/index.ts: -------------------------------------------------------------------------------- 1 | export const codeData = `import React, { useState } from "react";"; 2 | import ResetDialog from "./ResetDialog"; 3 | 4 | function App() { 5 | const [dialogOpen, setDialogOpen] = useState(false); 6 | 7 | const handleReset = () => { 8 | console.log("Reset action confirmed"); 9 | setDialogOpen(false); 10 | }; 11 | 12 | return ( 13 | <> 14 | 19 | setDialogOpen(false)} 22 | onReset={handleReset} 23 | /> 24 | 25 | ); 26 | } 27 | 28 | export default App;`; 29 | 30 | export const installationData = `npm i framer-motion`; 31 | 32 | export const data = [ 33 | { 34 | name: "isOpen", 35 | nameDetails: "Controls the visibility of the dialog", 36 | type: "boolean", 37 | typeDetails: 38 | "A boolean value that determines if the dialog is visible or not", 39 | default: `false`, 40 | }, 41 | { 42 | name: "onClose", 43 | nameDetails: "Function to handle closing the dialog", 44 | type: "function", 45 | typeDetails: "A function that is triggered when the dialog is closed", 46 | default: "undefined", 47 | }, 48 | { 49 | name: "onReset", 50 | nameDetails: "Function to handle the reset action", 51 | type: "function", 52 | typeDetails: "A function that is triggered when the user clicks on 'Reset'", 53 | default: "undefined", 54 | }, 55 | ]; 56 | -------------------------------------------------------------------------------- /apps/docs/data/buttons/4/Button.ts: -------------------------------------------------------------------------------- 1 | export const codeData = `import { ButtonV4 } from "@pixaui/button-v4"; 2 | 3 | function App() { 4 | return ( 5 | 11 | ); 12 | } 13 | 14 | export default App;`; 15 | 16 | export const installationData = `npm i @pixaui/button-v4`; 17 | 18 | export const data = [ 19 | { 20 | name: "title", 21 | nameDetails: "Text to display on the button", 22 | type: "string", 23 | typeDetails: "The text content for the button", 24 | default: `""`, 25 | }, 26 | { 27 | name: "borderRadius", 28 | nameDetails: "Border radius for button's rounded corners", 29 | type: "string", 30 | typeDetails: "Any valid CSS value for border-radius", 31 | default: `"8px"`, 32 | }, 33 | { 34 | name: "color", 35 | nameDetails: "Main color of the button, including hover effect", 36 | type: "string", 37 | typeDetails: "Any valid CSS color value", 38 | default: `"#212121"`, 39 | }, 40 | { 41 | name: "className", 42 | nameDetails: "Additional classes for styling the button container", 43 | type: "string", 44 | typeDetails: "CSS class names for custom styling", 45 | default: `""`, 46 | }, 47 | { 48 | name: "style", 49 | nameDetails: "Inline styles for custom styling", 50 | type: "CSSProperties", 51 | typeDetails: "An object containing CSS properties", 52 | default: "undefined", 53 | }, 54 | ]; 55 | -------------------------------------------------------------------------------- /apps/docs/components/ui/github-button.tsx: -------------------------------------------------------------------------------- 1 | import { octokit } from '@/lib/octokit'; 2 | import { GitHubLogoIcon } from '@radix-ui/react-icons'; 3 | import { unstable_cache } from 'next/cache'; 4 | import Link from 'next/link'; 5 | import type { ReactElement } from 'react'; 6 | import { Button } from './Button'; 7 | 8 | const getGitHubData = unstable_cache( 9 | async () => { 10 | try { 11 | const { data } = await octokit.rest.repos.get({ 12 | owner: 'lokendrakushwah12', 13 | repo: 'pixa-ui', 14 | }); 15 | return { 16 | stars: data.stargazers_count, 17 | url: data.html_url, 18 | }; 19 | } catch (error) { 20 | console.error(error); 21 | return { 22 | stars: 0, 23 | url: '', 24 | }; 25 | } 26 | }, 27 | ['github-stats'], 28 | { 29 | revalidate: 3600, 30 | } 31 | ); 32 | 33 | const GitHubButton = async (): Promise => { 34 | const { stars, url } = await getGitHubData(); 35 | 36 | return ( 37 | 51 | ); 52 | }; 53 | 54 | export default GitHubButton; -------------------------------------------------------------------------------- /apps/docs/components/ui/component-card.tsx: -------------------------------------------------------------------------------- 1 | import { Component } from "@/types/components" 2 | import { ChevronRight } from "lucide-react" 3 | import Link from "next/link" 4 | 5 | interface ComponentCardProps { 6 | component: Component 7 | category: string 8 | } 9 | 10 | const ComponentCard = ({ component, category }: ComponentCardProps) => { 11 | return ( 12 | 17 |
18 | 19 | {component.component && (() => { 20 | const ComponentToRender = component.component; 21 | return ; 22 | })()} 23 | 24 |
25 |
26 |

27 |

28 |
29 |

30 | {component.name} 31 |

32 | 33 |
34 |
35 | 36 | ) 37 | } 38 | 39 | export default ComponentCard -------------------------------------------------------------------------------- /apps/docs/data/buttons/3/Button.ts: -------------------------------------------------------------------------------- 1 | export const codeData = `import { ButtonV3 } from "@pixaui/button-v3"; 2 | 3 | function App() { 4 | return ( 5 | 11 | ); 12 | } 13 | 14 | export default App;`; 15 | 16 | export const installationData = `npm i @pixaui/button-v3`; 17 | 18 | export const data = [ 19 | { 20 | name: "title", 21 | nameDetails: "Text to display on the button", 22 | type: "string", 23 | typeDetails: "The text content for the button", 24 | default: `"ButtonV3"`, 25 | }, 26 | { 27 | name: "borderRadius", 28 | nameDetails: "Border radius for button's rounded corners", 29 | type: "string", 30 | typeDetails: "Any valid CSS value for border-radius", 31 | default: `"8px"`, 32 | }, 33 | { 34 | name: "color", 35 | nameDetails: "Main color of the button, including hover effect", 36 | type: "string", 37 | typeDetails: "Any valid CSS color value", 38 | default: `"#763afe"`, 39 | }, 40 | { 41 | name: "padding", 42 | nameDetails: "Padding inside the button", 43 | type: "string", 44 | typeDetails: "Any valid CSS value for padding", 45 | default: `"8px"`, 46 | }, 47 | { 48 | name: "className", 49 | nameDetails: "Additional classes for styling the button container", 50 | type: "string", 51 | typeDetails: "CSS class names for custom styling", 52 | default: `""`, 53 | }, 54 | { 55 | name: "style", 56 | nameDetails: "Inline styles for custom styling", 57 | type: "CSSProperties", 58 | typeDetails: "An object containing CSS properties", 59 | default: "undefined", 60 | }, 61 | ]; -------------------------------------------------------------------------------- /apps/docs/components/Table/SliderComponent.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import React from "react"; 3 | import * as Slider from "@radix-ui/react-slider"; 4 | 5 | interface SliderComponentProps { 6 | value: number; 7 | min: number; 8 | max: number; 9 | step: number; 10 | text: string; 11 | onValueChange: (value: number[]) => void; 12 | } 13 | 14 | const SliderComponent: React.FC = ({ 15 | value, 16 | min, 17 | max, 18 | step, 19 | text, 20 | onValueChange, 21 | }) => { 22 | return ( 23 |
24 | 30 | 39 | 40 | 41 | 42 | 46 | 47 | 53 |
54 | ); 55 | }; 56 | 57 | export default SliderComponent; 58 | -------------------------------------------------------------------------------- /apps/docs/data/buttons/1/Button.ts: -------------------------------------------------------------------------------- 1 | export const codeData = `import { ButtonV1 } from ./button-v1"; 2 | import { Plane } from "lucide-react"; 3 | 4 | function App() { 5 | return ( 6 | <> 7 | 16 | } 17 | className="rounded-xl border-[#d9d9d9] py-4 text-[#212121] backdrop-blur-sm dark:border-[#212121] dark:text-[#e2e2e2]" 18 | /> 19 | 20 | ); 21 | } 22 | 23 | export default App;`; 24 | 25 | export const installationData = `npm i lucide-react`; 26 | 27 | export const data = [ 28 | { 29 | name: "title", 30 | nameDetails: "Text to display on the button", 31 | type: "string", 32 | typeDetails: "The text content for the button", 33 | default: `"ButtonV1"`, 34 | }, 35 | { 36 | name: "svgColor", 37 | nameDetails: "Color of the SVG icon", 38 | type: "string", 39 | typeDetails: "Any valid CSS color value", 40 | default: `"#212121"`, 41 | }, 42 | { 43 | name: "icon", 44 | nameDetails: "Icon to display inside the button", 45 | type: "ReactNode", 46 | typeDetails: "A React element representing an icon", 47 | default: "undefined", 48 | }, 49 | { 50 | name: "className", 51 | nameDetails: "Additional classes for styling", 52 | type: "string", 53 | typeDetails: "CSS class names for custom styling", 54 | default: `""`, 55 | }, 56 | { 57 | name: "style", 58 | nameDetails: "Inline styles for custom styling", 59 | type: "React.CSSProperties", 60 | typeDetails: "An object with inline styles", 61 | default: "undefined", 62 | }, 63 | ]; 64 | -------------------------------------------------------------------------------- /apps/docs/components/ui/badge.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { Slot } from "@radix-ui/react-slot" 3 | import { cva, type VariantProps } from "class-variance-authority" 4 | 5 | import { cn } from "@/lib/utils" 6 | 7 | const badgeVariants = cva( 8 | "inline-flex items-center select-none justify-center rounded-sm 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 | -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/CodeBlock.tsx: -------------------------------------------------------------------------------- 1 | import { CodeIcon, TerminalIcon } from "lucide-react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | import { CopyCode } from "./CopyCode"; 6 | 7 | type CodeBlockProps = { 8 | fileName?: string; 9 | copyCode?: boolean; 10 | contentClassName?: string; 11 | simpleCode?: string; 12 | } & React.ComponentProps<"div">; 13 | 14 | export function CodeBlock({ 15 | fileName, 16 | className, 17 | children, 18 | contentClassName, 19 | simpleCode, 20 | copyCode = true, 21 | }: CodeBlockProps) { 22 | return ( 23 |
29 | {fileName && copyCode && ( 30 |
31 |
32 | {fileName === "Terminal" ? ( 33 | 37 | ) : ( 38 | 42 | )} 43 | 44 | {fileName} 45 | 46 |
47 | 50 |
51 | )} 52 |
53 |
{children}
54 |
55 |
56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /apps/docs/components/ui/popover.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as PopoverPrimitive from "@radix-ui/react-popover" 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 | -------------------------------------------------------------------------------- /apps/docs/components/ui/scroll-area.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" 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 | -------------------------------------------------------------------------------- /apps/docs/components/ui/alert.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { cva, type VariantProps } from "class-variance-authority" 3 | 4 | import { cn } from "@/lib/utils" 5 | 6 | const alertVariants = cva( 7 | "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", 8 | { 9 | variants: { 10 | variant: { 11 | default: "bg-card text-card-foreground", 12 | destructive: 13 | "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90", 14 | }, 15 | }, 16 | defaultVariants: { 17 | variant: "default", 18 | }, 19 | } 20 | ) 21 | 22 | function Alert({ 23 | className, 24 | variant, 25 | ...props 26 | }: React.ComponentProps<"div"> & VariantProps) { 27 | return ( 28 |
34 | ) 35 | } 36 | 37 | function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { 38 | return ( 39 |
47 | ) 48 | } 49 | 50 | function AlertDescription({ 51 | className, 52 | ...props 53 | }: React.ComponentProps<"div">) { 54 | return ( 55 |
63 | ) 64 | } 65 | 66 | export { Alert, AlertTitle, AlertDescription } 67 | -------------------------------------------------------------------------------- /apps/docs/components/ui/progressive-blur.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { cn } from "@/lib/utils"; 3 | import type { HTMLMotionProps } from "motion/react"; 4 | import { motion } from "motion/react"; 5 | 6 | export const GRADIENT_ANGLES = { 7 | top: 0, 8 | right: 90, 9 | bottom: 180, 10 | left: 270, 11 | }; 12 | 13 | export type ProgressiveBlurProps = { 14 | direction?: keyof typeof GRADIENT_ANGLES; 15 | blurLayers?: number; 16 | className?: string; 17 | blurIntensity?: number; 18 | } & HTMLMotionProps<'div'>; 19 | 20 | export function ProgressiveBlur({ 21 | direction = 'bottom', 22 | blurLayers = 8, 23 | className, 24 | blurIntensity = 0.25, 25 | ...props 26 | }: ProgressiveBlurProps) { 27 | const layers = Math.max(blurLayers, 2); 28 | const segmentSize = 1 / (blurLayers + 1); 29 | 30 | return ( 31 |
32 | {Array.from({ length: layers }).map((_, index) => { 33 | const angle = GRADIENT_ANGLES[direction]; 34 | const gradientStops = [ 35 | index * segmentSize, 36 | (index + 1) * segmentSize, 37 | (index + 2) * segmentSize, 38 | (index + 3) * segmentSize, 39 | ].map( 40 | (pos, posIndex) => 41 | `rgba(255, 255, 255, ${posIndex === 1 || posIndex === 2 ? 1 : 0}) ${pos * 100}%` 42 | ); 43 | 44 | const gradient = `linear-gradient(${angle}deg, ${gradientStops.join( 45 | ', ' 46 | )})`; 47 | 48 | return ( 49 | 59 | ); 60 | })} 61 |
62 | ); 63 | } 64 | -------------------------------------------------------------------------------- /apps/docs/examples/responsive-dialog-example.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { Loader } from 'lucide-react' 3 | import React from 'react' 4 | import { ResponsiveDialog } from '../components/sections/dia' 5 | import { Button } from '../components/ui/Button' 6 | 7 | const DialogExample = () => { 8 | const [open, setOpen] = React.useState(false) 9 | const [isLoading, setIsLoading] = React.useState(false) 10 | 11 | const onOpenChange = (open: boolean) => { 12 | setOpen(open) 13 | if (!open) { 14 | setIsLoading(false) 15 | } 16 | } 17 | 18 | const handleCancel = async () => { 19 | setIsLoading(true) 20 | await new Promise((resolve) => setTimeout(resolve, 2000)) 21 | setIsLoading(false) 22 | onOpenChange(false) 23 | } 24 | 25 | return ( 26 | Cancel Subscription} 31 | > 32 |
33 |

Are you sure you want to cancel your subscription?

34 |

35 | If you cancel now, you'll lose access immediately. You can always start a new 36 | subscription later, but you won't get another free trial. 37 |

38 |
39 |
40 | 43 | 47 |
48 |
49 | ) 50 | } 51 | 52 | export default DialogExample -------------------------------------------------------------------------------- /apps/docs/data/buttons/5/Button.ts: -------------------------------------------------------------------------------- 1 | export const installationData = `npm i @pixaui/button-v5`; 2 | 3 | export const codeData = `import { ButtonV5 } from "@pixaui/button-v5"; 4 | 5 | function App() { 6 | return ( 7 | 15 | ); 16 | } 17 | 18 | export default App;`; 19 | 20 | export const data = [ 21 | { 22 | name: "title", 23 | nameDetails: "Text to display on the button", 24 | type: "string", 25 | typeDetails: "The text content for the button", 26 | default: `""`, 27 | }, 28 | { 29 | name: "icon", 30 | nameDetails: "Displays an icon beside the button title when true", 31 | type: "boolean", 32 | typeDetails: "Set to true to show an icon", 33 | default: "true", 34 | }, 35 | { 36 | name: "loading", 37 | nameDetails: "Shows a loading spinner on the button when true", 38 | type: "boolean", 39 | typeDetails: "Set to true to indicate a loading state", 40 | default: "false", 41 | }, 42 | { 43 | name: "borderRadius", 44 | nameDetails: "Defines the border radius of the button", 45 | type: "string", 46 | typeDetails: "Any valid CSS value for border-radius", 47 | default: `"8px"`, 48 | }, 49 | { 50 | name: "variant", 51 | nameDetails: "Sets the button's style variant", 52 | type: `"default" | "primary" | "secondary" | "destructive"`, 53 | typeDetails: "Button style options", 54 | default: `"default"`, 55 | }, 56 | { 57 | name: "className", 58 | nameDetails: "Adds additional CSS classes to the button for styling", 59 | type: "string", 60 | typeDetails: "CSS class names for custom styling", 61 | default: `""`, 62 | }, 63 | { 64 | name: "style", 65 | nameDetails: "Inline styles for custom button styling", 66 | type: "CSSProperties", 67 | typeDetails: "An object containing CSS properties", 68 | default: "undefined", 69 | }, 70 | ]; 71 | -------------------------------------------------------------------------------- /apps/docs/app/docs/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Metadata } from "next"; 2 | 3 | import { OnThisPage } from "../ui/_components/OnThisPage"; 4 | import { Sidebar } from "./_components/sidebar/Sidebar"; 5 | 6 | export const metadata: Metadata = { 7 | title: { 8 | default: "Docs", 9 | template: "%s", 10 | }, 11 | description: "Browse through a curated collection of versatile Next.js components that will make your application beautiful.", 12 | openGraph: { 13 | images: [ 14 | { 15 | width: 1920, 16 | height: 1080, 17 | url: "https://pixaui.com/open-graphs/og-browse-components.png", 18 | alt: "Pixa's website cover", 19 | }, 20 | ], 21 | locale: "en", 22 | siteName: "Lokendra Kushwah", 23 | title: "Docs", 24 | description: "Browse through a curated collection of versatile Next.js components that will make your application beautiful.", 25 | type: "website", 26 | url: "https://pixaui.com/ui", 27 | }, 28 | twitter: { 29 | images: [ 30 | { 31 | width: 1920, 32 | height: 1080, 33 | url: "https://pixaui.com/open-graphs/og-browse-components.png", 34 | alt: "Pixa's website cover", 35 | }, 36 | ], 37 | card: "summary_large_image", 38 | title: "Docs", 39 | description: "Browse through a curated collection of versatile Next.js components that will make your application beautiful.", 40 | site: "@lokendra", 41 | creator: "Lokendra Kushwah", 42 | }, 43 | }; 44 | 45 | type DocsPageLayout = { 46 | children: React.ReactNode; 47 | }; 48 | 49 | export default function DocsPageLayout({ children }: DocsPageLayout) { 50 | return ( 51 |
52 | 53 |
54 |
55 | {children} 56 |
57 | 58 |
59 |
60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /apps/docs/components/ui/tooltip.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as TooltipPrimitive from "@radix-ui/react-tooltip" 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 | -------------------------------------------------------------------------------- /apps/docs/app/ui/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Metadata } from "next"; 2 | 3 | import { OnThisPage } from "./_components/OnThisPage"; 4 | import { Sidebar } from "./_components/sidebar/Sidebar"; 5 | 6 | export const metadata: Metadata = { 7 | title: { 8 | default: "Browse Components", 9 | template: "%s", 10 | }, 11 | description: "Browse through a curated collection of versatile Next.js components that will make your application beautiful.", 12 | openGraph: { 13 | images: [ 14 | { 15 | width: 1920, 16 | height: 1080, 17 | url: "https://pixaui.com/open-graphs/og-browse-components.png", 18 | alt: "Pixa's website cover", 19 | }, 20 | ], 21 | locale: "en", 22 | siteName: "Lokendra Kushwah", 23 | title: "Pixa: Browse Components", 24 | description: "Browse through a curated collection of versatile Next.js components that will make your application beautiful.", 25 | type: "website", 26 | url: "https://pixaui.com/ui", 27 | }, 28 | twitter: { 29 | images: [ 30 | { 31 | width: 1920, 32 | height: 1080, 33 | url: "https://pixaui.com/open-graphs/og-browse-components.png", 34 | alt: "Pixa's website cover", 35 | }, 36 | ], 37 | card: "summary_large_image", 38 | title: "Pixa: Browse Components", 39 | description: "Browse through a curated collection of versatile Next.js components that will make your application beautiful.", 40 | site: "@lokendra", 41 | creator: "Lokendra Kushwah", 42 | }, 43 | }; 44 | 45 | type ComponentPageLayout = { 46 | children: React.ReactNode; 47 | }; 48 | 49 | export default function ComponentPageLayout({ children }: ComponentPageLayout) { 50 | return ( 51 |
52 | 53 |
54 |
55 | {children} 56 |
57 | 58 |
59 |
60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/Header.tsx: -------------------------------------------------------------------------------- 1 | import { PixaLogo } from "@/components/icons"; 2 | import { ThemeToggle } from "@/components/theme-toggle"; 3 | import GitHubButton from "@/components/ui/github-button"; 4 | import { MenuIcon } from "lucide-react"; 5 | import Link from "next/link"; 6 | import { ActiveLink } from "./ActiveLink"; 7 | import { CommandMenu } from "./cmdk"; 8 | import Drawer from "./Drawer"; 9 | import { HeaderClient } from "./HeaderClient"; 10 | 11 | const ITEMS = [ 12 | { 13 | name: "Docs", 14 | slug: "/docs", 15 | }, 16 | { 17 | name: "Components", 18 | slug: "/ui/accordion", 19 | }, 20 | ]; 21 | 22 | export function Header() { 23 | return ( 24 | 25 | 58 | 59 | ); 60 | } -------------------------------------------------------------------------------- /apps/docs/components/Table/prop-information.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { InfoCircledIcon } from "@radix-ui/react-icons"; 4 | import * as Popover from "@radix-ui/react-popover"; 5 | import clsx from "clsx"; 6 | import { AnimatePresence, motion } from "motion/react"; 7 | import React from "react"; 8 | 9 | export const PropInformation = ({ content }: { content: React.ReactNode }) => { 10 | const [open, setOpen] = React.useState(false); 11 | 12 | return ( 13 | 14 | 15 |
22 | 23 |
24 |
25 | 26 | {open && ( 27 | 28 | e.preventDefault()} 32 | > 33 | 44 | {content} 45 | 46 | 47 | 48 | )} 49 | 50 |
51 | ); 52 | }; 53 | -------------------------------------------------------------------------------- /apps/docs/components/ui/tabs.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as TabsPrimitive from "@radix-ui/react-tabs" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | function Tabs({ 9 | className, 10 | ...props 11 | }: React.ComponentProps) { 12 | return ( 13 | 18 | ) 19 | } 20 | 21 | function TabsList({ 22 | className, 23 | ...props 24 | }: React.ComponentProps) { 25 | return ( 26 | 34 | ) 35 | } 36 | 37 | function TabsTrigger({ 38 | className, 39 | ...props 40 | }: React.ComponentProps) { 41 | return ( 42 | 50 | ) 51 | } 52 | 53 | function TabsContent({ 54 | className, 55 | ...props 56 | }: React.ComponentProps) { 57 | return ( 58 | 63 | ) 64 | } 65 | 66 | export { Tabs, TabsList, TabsTrigger, TabsContent } 67 | -------------------------------------------------------------------------------- /apps/docs/components/sections/footer.tsx: -------------------------------------------------------------------------------- 1 | import { formatLastUpdated, getRelativeTime, getRepoLastUpdate } from "@/lib/repo-utils"; 2 | import { unstable_cache } from 'next/cache'; 3 | import Link from "next/link"; 4 | 5 | // Cached version to avoid hitting GitHub API on every page load 6 | const getCachedPortfolioUpdate = unstable_cache( 7 | async () => { 8 | try { 9 | const lastUpdate = await getRepoLastUpdate({ 10 | owner: 'lokendrakushwah12', 11 | repo: 'pixa-ui', 12 | token: process.env.GITHUB_TOKEN 13 | }); 14 | 15 | return { 16 | lastUpdated: lastUpdate.lastUpdated, 17 | formatted: formatLastUpdated(lastUpdate.lastUpdated), 18 | relative: getRelativeTime(lastUpdate.lastUpdated), 19 | lastCommit: lastUpdate.lastCommit 20 | }; 21 | } catch (error) { 22 | console.error('Error fetching portfolio update:', error); 23 | return null; 24 | } 25 | }, 26 | ['portfolio-last-update'], 27 | { 28 | revalidate: 3600, 29 | tags: ['portfolio-update'] 30 | } 31 | ); 32 | 33 | const Footer = async () => { 34 | let lastUpdatedText = 'Unable to fetch'; 35 | 36 | if (process.env.NODE_ENV === 'development') { 37 | lastUpdatedText = 'Development mode'; 38 | } else { 39 | const portfolioUpdate = await getCachedPortfolioUpdate(); 40 | if (portfolioUpdate?.lastUpdated) { 41 | lastUpdatedText = portfolioUpdate.relative; 42 | } 43 | } 44 | 45 | return ( 46 |
47 |
48 |
49 |

50 | Designed and built by 51 | Lokendra 52 | 53 |

54 |
55 |

56 | Last updated {lastUpdatedText} 57 |

58 |
59 |
60 |
61 | ); 62 | }; 63 | 64 | export default Footer; -------------------------------------------------------------------------------- /apps/docs/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import { geistMono, hostGrotesk } from "@/lib/fonts"; 2 | import { ThemeProvider } from "@/providers/theme-provider"; 3 | import type { Metadata } from "next"; 4 | import "./globals.css"; 5 | import { Header } from "./ui/_components/Header"; 6 | 7 | export const metadata: Metadata = { 8 | title: "Pixa/ui", 9 | description: "Pixa/ui - Curated collection of versatile Next.js components", 10 | keywords: [ 11 | "pixa-ui", 12 | "pixa", 13 | "pixa-ui components", 14 | "pixa-ui nextjs", 15 | "pixa-ui library", 16 | "pixa-ui open source", 17 | "pixa-ui components library", 18 | "pixa-ui components collection", 19 | "pixa-ui components design", 20 | "pixa-ui components design system", 21 | "pixa-ui components design library", 22 | "pixa-ui components design system library", 23 | "pixa-ui components design system collection", 24 | "pixa-ui components design system open source", 25 | "pixa-ui components design system nextjs", 26 | "nextjs ui components", 27 | "nextjs components", 28 | "nextjs ui library", 29 | "nextjs open source", 30 | "nextjs components library", 31 | ], 32 | icons: { 33 | icon: "/favicon.svg", 34 | }, 35 | openGraph: { 36 | title: "Pixa/ui", 37 | description: "Pixa/ui - Curated collection of versatile Next.js components", 38 | url: "https://pixaui.com", 39 | images: [ 40 | { 41 | url: "/openGraph.png", 42 | }, 43 | ], 44 | }, 45 | twitter: { 46 | title: "Pixa/ui", 47 | description: "Pixa/ui - Curated collection of versatile Next.js components", 48 | card: "summary_large_image", 49 | images: ["/openGraph.png"], 50 | }, 51 | }; 52 | 53 | export default function RootLayout({ 54 | children, 55 | }: Readonly<{ children: React.ReactNode }>) { 56 | return ( 57 | 58 | 59 | 65 |
66 | {children} 67 | 68 | 69 | 70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /apps/docs/app/_content/docs/usage.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Usage" 3 | description: "Learn how to use Pixa UI components in your application." 4 | slug: "usage" 5 | icon: MousePointerClick 6 | --- 7 | 8 | 9 | ## Using Pixa UI Components 10 | 11 | Learn how to use Pixa UI components in your application. Once a Pixa UI component is installed, you can import it and use it in your application like any other React component. The components are added as part of your codebase (not hidden in a library), so the usage feels very natural. 12 | 13 | ## Example 14 | Let's say you just added an Announcement component (a simple dismissible banner for notifications). You might use it as follows: 15 | 16 | 17 | ```tsx 18 | 'use client'; 19 | 20 | import { 21 | Announcement, 22 | AnnouncementTag, 23 | AnnouncementTitle, 24 | } from '@/components/ui/pixa-ui/announcement'; 25 | import { ArrowUpRightIcon } from 'lucide-react'; 26 | 27 | const Hero = () => ( 28 | <> 29 | 30 | Latest update 31 | 32 | New feature added 33 | 34 | 35 | 36 | {/* The rest of your page... */} 37 | 38 | ); 39 | 40 | export default Hero; 41 | ``` 42 | 43 | 44 | In the example above, we import the Announcement components from our Pixa UI directory and include it in our JSX. Then, we compose the component with the `AnnouncementTag` and `AnnouncementTitle` subcomponents. You can style or configure the component just as you would if you wrote it yourself – since the code lives in your project, you can even open the component file to see how it works or make custom modifications. 45 | 46 | Feel free to add as many Pixa UI components as you need. Because components are added on-demand, you're not including code for features you aren't using. This keeps your app lean. Each component is isolated, so adding one won't bloat another – yet they all share the same design tokens (colors, fonts, etc.) from shadcn's theme. 47 | 48 | ## Customization 49 | 50 | After installation, no additional setup is needed. The component's styles (Tailwind CSS classes) and scripts are already integrated. You can start interacting with the component in your app immediately. -------------------------------------------------------------------------------- /apps/docs/data/cards/1/index.ts: -------------------------------------------------------------------------------- 1 | export const codeData = `import { motion, AnimatePresence, MotionConfig } from "motion/react";"; 2 | import StackCard from "./StackCard"; 3 | 4 | const collection: Collection = { 5 | id: 1, 6 | title: "Nature Collection", 7 | images: [ 8 | "https://images.unsplash.com/photo-1675897974745-1e78e8690755", 9 | "https://images.unsplash.com/photo-1486718448742-163732cd1544", 10 | "https://images.unsplash.com/photo-1600669091588-8aaac09509ba", 11 | "https://images.unsplash.com/photo-1583100913639-b8a172d90b77", 12 | "https://images.unsplash.com/photo-1583100913828-aeff24cc04ae", 13 | "https://images.unsplash.com/photo-1583100913639-f3b195f86da2", 14 | ], 15 | }; 16 | 17 | function App() { 18 | const [expandedIndex, setExpandedIndex] = useState(null); 19 | 20 | return ( 21 | <> 22 | setExpandedIndex(expandedIndex === 0 ? null : 0)} 29 | /> 30 | 31 | ); 32 | } 33 | 34 | export default App;`; 35 | 36 | export const installationData = `npm i framer-motion`; 37 | 38 | export const data = [ 39 | { 40 | name: "images", 41 | nameDetails: "Array of image URLs displayed in the stack", 42 | type: "string[]", 43 | typeDetails: "An array containing URLs of images to be displayed", 44 | default: "[]", 45 | }, 46 | { 47 | name: "title", 48 | nameDetails: "Title of the StackCard component", 49 | type: "string", 50 | typeDetails: "A string representing the title displayed on the card", 51 | default: `""`, 52 | }, 53 | { 54 | name: "index", 55 | nameDetails: "Index of the card in the stack", 56 | type: "number", 57 | typeDetails: "A number representing the position of the card in the stack", 58 | default: "0", 59 | }, 60 | { 61 | name: "isExpanded", 62 | nameDetails: "Controls the expanded or collapsed state of the card", 63 | type: "boolean", 64 | typeDetails: "A boolean value determining if the card is expanded", 65 | default: "false", 66 | }, 67 | { 68 | name: "onClick", 69 | nameDetails: "Function to handle click events", 70 | type: "function", 71 | typeDetails: "A function triggered when the card is clicked", 72 | default: "() => {}", 73 | }, 74 | ]; 75 | -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/CopyCode.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useState } from "react"; 4 | 5 | import { AnimatePresence, motion } from "motion/react"; 6 | 7 | 8 | import { CheckIcon } from "lucide-react"; 9 | 10 | type CopyCode = { 11 | code: string; 12 | example?: boolean; 13 | mode?: "text" | "icon"; 14 | }; 15 | 16 | export function CopyCode({ code }: CopyCode) { 17 | const [copied, setCopied] = useState(false); 18 | 19 | function handleCopy() { 20 | navigator.clipboard.writeText(code); 21 | 22 | setCopied(true); 23 | 24 | setTimeout(() => setCopied(false), 1500); 25 | } 26 | 27 | return ( 28 | 64 | ) 65 | } 66 | 67 | function Icon() { 68 | return ( 69 | 70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /apps/docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pixa-ui", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev --turbopack", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@repo/ui": "workspace:*", 13 | "@hookform/resolvers": "^5.1.1", 14 | "@mdx-js/loader": "^3.1.0", 15 | "@mdx-js/mdx": "^3.1.0", 16 | "@mdx-js/react": "^3.1.0", 17 | "@next/mdx": "^15.3.4", 18 | "@octokit/rest": "^22.0.0", 19 | "@radix-ui/react-accordion": "^1.2.11", 20 | "@radix-ui/react-checkbox": "^1.3.2", 21 | "@radix-ui/react-dialog": "^1.1.14", 22 | "@radix-ui/react-dropdown-menu": "^2.1.7", 23 | "@radix-ui/react-icons": "^1.3.2", 24 | "@radix-ui/react-navigation-menu": "^1.2.13", 25 | "@radix-ui/react-popover": "^1.1.14", 26 | "@radix-ui/react-scroll-area": "^1.2.9", 27 | "@radix-ui/react-slider": "^1.3.4", 28 | "@radix-ui/react-slot": "^1.2.3", 29 | "@radix-ui/react-switch": "^1.2.5", 30 | "@radix-ui/react-tabs": "^1.1.12", 31 | "@radix-ui/react-tooltip": "^1.2.7", 32 | "@types/mdx": "^2.0.13", 33 | "class-variance-authority": "^0.7.1", 34 | "clsx": "^2.1.1", 35 | "cmdk": "^1.1.1", 36 | "date-fns": "^4.1.0", 37 | "gray-matter": "^4.0.3", 38 | "input-otp": "^1.4.2", 39 | "jotai": "^2.12.5", 40 | "lucide-react": "^0.487.0", 41 | "motion": "^12.19.1", 42 | "next": "15.3.0", 43 | "next-mdx-remote": "^5.0.0", 44 | "next-themes": "^0.4.6", 45 | "react": "^19.0.0", 46 | "react-day-picker": "^9.7.0", 47 | "react-dom": "^19.0.0", 48 | "react-hook-form": "^7.58.1", 49 | "react-icons": "^5.5.0", 50 | "react-syntax-highlighter": "^15.6.1", 51 | "react-use-measure": "^2.1.7", 52 | "rehype-pretty-code": "^0.14.1", 53 | "rehype-slug": "^6.0.0", 54 | "remark-gfm": "^4.0.1", 55 | "shiki": "^3.7.0", 56 | "tailwind-merge": "^3.2.0", 57 | "tailwindcss-animate": "^1.0.7", 58 | "tw-animate-css": "^1.3.4", 59 | "unified": "^11.0.5", 60 | "usehooks-ts": "^3.1.1", 61 | "vaul": "^1.1.2", 62 | "zod": "^3.25.67" 63 | }, 64 | "devDependencies": { 65 | "@eslint/js": "^9.27.0", 66 | "@tailwindcss/postcss": "^4", 67 | "@types/node": "^20", 68 | "@types/react": "^19", 69 | "@types/react-dom": "^19", 70 | "@types/react-syntax-highlighter": "^15.5.13", 71 | "eslint": "^9.27.0", 72 | "eslint-config-next": "^15.3.2", 73 | "husky": "^9.1.7", 74 | "tailwindcss": "^4", 75 | "typescript": "^5", 76 | "typescript-eslint": "^8.32.1" 77 | }, 78 | "lint-staged": { 79 | "*.{ts,tsx,js,jsx}": [ 80 | "eslint --fix" 81 | ] 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /apps/docs/components/sections/dia.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useMobile } from '@/hooks/useMobile'; 4 | import { Drawer } from 'vaul'; 5 | import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '../ui/dialog'; 6 | 7 | interface ResponsiveDialogProps { 8 | open: boolean; 9 | onOpenChange: (open: boolean) => void; 10 | title: string; 11 | description?: string; 12 | trigger: React.ReactNode; 13 | children: React.ReactNode; 14 | } 15 | 16 | export function ResponsiveDialog({ 17 | open, 18 | onOpenChange, 19 | title, 20 | description, 21 | trigger, 22 | children, 23 | }: ResponsiveDialogProps) { 24 | const isMobile = useMobile(); 25 | 26 | if (isMobile) { 27 | return ( 28 | 29 | {trigger} 30 | 31 | 32 | 39 | {title} 40 | {description && ( 41 | {description} 42 | )} 43 |
{children}
44 |
45 |
46 |
47 | ); 48 | } 49 | 50 | return ( 51 | 52 | {trigger} 53 | 54 | 55 | {title} 56 | {description && ( 57 | {description} 58 | )} 59 | 60 |
{children}
61 |
62 |
63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/CommandBlock.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useMemo } from "react"; 4 | 5 | import { cn } from "@/lib/utils"; 6 | 7 | import { usePackageManager } from "@/hooks/use-package-manager"; 8 | 9 | import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"; 10 | import { CopyCode } from "./CopyCode"; 11 | import { Tabs, TabsContent, TabsList, TabsTrigger } from "./Tabs"; 12 | 13 | type PackageManager = "npm" | "pnpm" | "yarn" | "bun"; 14 | 15 | type CommandBlockProps = { 16 | npmCommand: string; 17 | yarnCommand: string; 18 | pnpmCommand: string; 19 | bunCommand: string; 20 | } & React.ComponentProps<"div">; 21 | 22 | export function CommandBlock({ 23 | npmCommand, 24 | yarnCommand, 25 | pnpmCommand, 26 | bunCommand, 27 | className, 28 | }: CommandBlockProps) { 29 | const [packageManager, setPackageManager] = usePackageManager(); 30 | 31 | const tabs = useMemo(() => { 32 | return { 33 | npm: npmCommand, 34 | pnpm: pnpmCommand, 35 | yarn: yarnCommand, 36 | bun: bunCommand, 37 | }; 38 | }, [npmCommand, pnpmCommand, yarnCommand, bunCommand]); 39 | 40 | return ( 41 |
47 | setPackageManager(value as PackageManager)} 51 | className="bg-muted dark:bg-background p-1" 52 | > 53 |
54 | 55 | {Object.entries(tabs).map(([key]) => ( 56 | 62 | {key} 63 | 64 | ))} 65 | 66 | 67 |
68 |
69 | 70 | {Object.entries(tabs).map(([key, value]) => ( 71 | 72 |
73 |                   
77 |                     {value}
78 |                   
79 |                 
80 |
81 | ))} 82 | 83 |
84 |
85 |
86 |
87 | ); 88 | } 89 | -------------------------------------------------------------------------------- /apps/docs/styles/pixa.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | @import "tw-animate-css"; 3 | 4 | :root { 5 | --site-background: oklch(0.99 0.0034 232.5); 6 | --surface: oklch(1 0 0); 7 | --background: oklch(1 0 0); 8 | --foreground: oklch(0.145 0 0); 9 | --card: oklch(1 0 0); 10 | --card-foreground: oklch(0.145 0 0); 11 | --popover: oklch(1 0 0); 12 | --popover-foreground: oklch(0.145 0 0); 13 | --primary: oklch(63.611% 0.19947 280.081); 14 | --primary-foreground: oklch(0.985 0 0); 15 | --secondary: oklch(0.97 0 0); 16 | --secondary-foreground: oklch(0.205 0 0); 17 | --muted: oklch(0.97 0 0); 18 | --muted-foreground: oklch(0.356 0 0); 19 | --accent: oklch(0.97 0 0); 20 | --accent-foreground: oklch(0.205 0 0); 21 | --destructive: oklch(0.577 0.245 27.325); 22 | --destructive-foreground: oklch(0.577 0.245 27.325); 23 | --border: oklch(0.9 0 0); 24 | --input: oklch(0.922 0 0); 25 | --ring: oklch(0.708 0 0); 26 | --chart-1: oklch(0.646 0.222 41.116); 27 | --chart-2: oklch(0.6 0.118 184.704); 28 | --chart-3: oklch(0.398 0.07 227.392); 29 | --chart-4: oklch(0.828 0.189 84.429); 30 | --chart-5: oklch(0.769 0.188 70.08); 31 | --radius: 0.625rem; 32 | --sidebar: oklch(0.985 0 0); 33 | --sidebar-foreground: oklch(0.145 0 0); 34 | --sidebar-primary: oklch(0.205 0 0); 35 | --sidebar-primary-foreground: oklch(0.985 0 0); 36 | --sidebar-accent: oklch(0.97 0 0); 37 | --sidebar-accent-foreground: oklch(0.205 0 0); 38 | --sidebar-border: oklch(0.922 0 0); 39 | --sidebar-ring: oklch(0.708 0 0); 40 | } 41 | 42 | .dark { 43 | --surface: oklch(0.0725 0 0); 44 | --site-background: oklch(0.125 0 0); 45 | --background: oklch(0.145 0 0); 46 | --foreground: oklch(0.985 0 0); 47 | --card: oklch(0.145 0 0); 48 | --card-foreground: oklch(0.985 0 0); 49 | --popover: oklch(0.145 0 0); 50 | --popover-foreground: rgb(250, 250, 250); 51 | --primary: hsl(241, 100%, 73%); 52 | --primary-foreground: oklch(0.205 0 0); 53 | --secondary: oklch(0.269 0 0); 54 | --secondary-foreground: oklch(0.985 0 0); 55 | --muted: oklch(0.269 0 0); 56 | --muted-foreground: oklch(0.708 0 0); 57 | --accent: oklch(0.269 0 0); 58 | --accent-foreground: oklch(0.985 0 0); 59 | --destructive: oklch(0.396 0.141 25.723); 60 | --destructive-foreground: oklch(0.637 0.237 25.331); 61 | --border: oklch(0.269 0 0); 62 | --input: oklch(0.269 0 0); 63 | --ring: oklch(0.439 0 0); 64 | --chart-1: oklch(0.488 0.243 264.376); 65 | --chart-2: oklch(0.696 0.17 162.48); 66 | --chart-3: oklch(0.769 0.188 70.08); 67 | --chart-4: oklch(0.627 0.265 303.9); 68 | --chart-5: oklch(0.645 0.246 16.439); 69 | --sidebar: oklch(0.205 0 0); 70 | --sidebar-foreground: oklch(0.985 0 0); 71 | --sidebar-primary: oklch(0.488 0.243 264.376); 72 | --sidebar-primary-foreground: oklch(0.985 0 0); 73 | --sidebar-accent: oklch(0.269 0 0); 74 | --sidebar-accent-foreground: oklch(0.985 0 0); 75 | --sidebar-border: oklch(0.269 0 0); 76 | --sidebar-ring: oklch(0.439 0 0); 77 | } -------------------------------------------------------------------------------- /packages/ui/src/pixaui/button-slide-right.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import React, { ReactNode } from "react"; 3 | 4 | interface ButtonSlideRightProps { 5 | title?: string; 6 | svgColor?: string; 7 | icon?: ReactNode; 8 | className?: string; 9 | style?: React.CSSProperties; 10 | } 11 | 12 | const ButtonSlideRight: React.FC = ({ 13 | title = "ButtonSlideRight", 14 | svgColor = "#212121", 15 | icon, 16 | className = "", 17 | style, 18 | }) => { 19 | return ( 20 |
24 | {icon ? ( 25 |
26 | {icon} 27 |
28 | ) : ( 29 | 37 | 45 | 53 | 54 | )} 55 |

56 | {title} 57 |

58 | {icon ? ( 59 |
60 | {icon} 61 |
62 | ) : ( 63 | 71 | 79 | 87 | 88 | )} 89 |
90 | ); 91 | }; 92 | 93 | export default ButtonSlideRight; 94 | -------------------------------------------------------------------------------- /packages/ui/src/pixaui/button-slide-left.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import React, { useState, CSSProperties } from "react"; 3 | 4 | interface ButtonSlideLeftProps { 5 | title: string; 6 | borderRadius?: string; 7 | color?: string; 8 | className?: string; 9 | style?: CSSProperties; 10 | } 11 | 12 | const ButtonSlideLeft: React.FC = ({ 13 | title, 14 | borderRadius = "8px", 15 | color = "#212121", 16 | className = "", 17 | style, 18 | }) => { 19 | const [isHovered, setIsHovered] = useState(false); 20 | 21 | return ( 22 |
setIsHovered(true)} 25 | onMouseLeave={() => setIsHovered(false)} 26 | style={{ 27 | backgroundColor: isHovered ? color : "transparent", 28 | borderRadius, 29 | ...style, 30 | }} 31 | > 32 |
33 | 42 | 50 | 58 | 59 |

63 | {title} 64 |

65 | 73 | 81 | 89 | 90 |
91 |
92 | ); 93 | }; 94 | 95 | export default ButtonSlideLeft; 96 | -------------------------------------------------------------------------------- /apps/docs/app/docs/_components/sidebar/Sidebar.tsx: -------------------------------------------------------------------------------- 1 | import { getDocsMdx, getMetaConfig } from "@/lib/mdx"; 2 | import { SidebarButton } from "./SidebarButton"; 3 | 4 | // Define the structure for grouped docs 5 | interface GroupedDocs { 6 | [category: string]: Array<{ 7 | title: string; 8 | slug: string; 9 | icon?: string; 10 | isNew?: boolean; 11 | }>; 12 | } 13 | 14 | export const getMDXdocs = getDocsMdx("docs").sort((a, b) => 15 | a.title.localeCompare(b.title), 16 | ); 17 | 18 | // Function to group docs based on meta.json structure 19 | function groupDocsFromMeta(): GroupedDocs { 20 | const metaConfig = getMetaConfig("docs"); 21 | const grouped: GroupedDocs = {}; 22 | 23 | if (!metaConfig) { 24 | // Fallback to simple grouping if meta.json is not available 25 | getMDXdocs.forEach((doc) => { 26 | if (!grouped['Docs']) { 27 | grouped['Docs'] = []; 28 | } 29 | grouped['Docs'].push({ 30 | title: doc.title, 31 | slug: doc.slug, 32 | icon: doc.icon, 33 | isNew: doc.isNew, 34 | }); 35 | }); 36 | return grouped; 37 | } 38 | 39 | let currentCategory = 'Default'; 40 | 41 | metaConfig.pages.forEach((page) => { 42 | // Check if this is a category heading (starts and ends with ---) 43 | if (page.startsWith('---') && page.endsWith('---')) { 44 | currentCategory = page.replace(/---/g, '').trim(); 45 | if (!grouped[currentCategory]) { 46 | grouped[currentCategory] = []; 47 | } 48 | return; 49 | } 50 | 51 | // Find the corresponding MDX doc 52 | const doc = getMDXdocs.find((d) => d.slug === page); 53 | if (doc) { 54 | if (!grouped[currentCategory]) { 55 | grouped[currentCategory] = []; 56 | } 57 | 58 | grouped[currentCategory].push({ 59 | title: doc.title, 60 | slug: doc.slug, 61 | icon: doc.icon, 62 | isNew: doc.isNew, 63 | }); 64 | } 65 | }); 66 | 67 | return grouped; 68 | } 69 | 70 | export function Sidebar() { 71 | const groupedDocs = groupDocsFromMeta(); 72 | const categories = Object.keys(groupedDocs); 73 | 74 | console.log("Cat", groupedDocs) 75 | 76 | return ( 77 | 99 | ); 100 | } -------------------------------------------------------------------------------- /apps/docs/components/Table/PropsTable.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import type React from "react"; 3 | import { PropInformation } from "./prop-information"; 4 | 5 | interface PropsTableProps { 6 | data: { 7 | name: string; 8 | nameDetails?: React.ReactNode; 9 | type: string; 10 | typeDetails?: React.ReactNode; 11 | default?: string; 12 | defaultDetails?: React.ReactNode; 13 | }[]; 14 | } 15 | 16 | export const PropsTable = ({ data }: PropsTableProps) => { 17 | if (data.length === 0) { 18 | return ( 19 |
20 |
21 | No Additional Props 22 |
23 |
24 | ); 25 | } 26 | 27 | return ( 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | {data.map((item) => ( 39 | 47 | 57 | 71 | 80 | 81 | ))} 82 | 83 |
PropTypeDefault
48 |
49 |
50 | {item.name} 51 |
52 | {item.nameDetails && ( 53 | 54 | )} 55 |
56 |
58 | {item.type ? ( 59 |
60 |
61 | {item.type} 62 |
63 | {item.typeDetails && ( 64 | 65 | )} 66 |
67 | ) : ( 68 |
-
69 | )} 70 |
72 | {item.default ? ( 73 |
74 | {item.default} 75 |
76 | ) : ( 77 |
-
78 | )} 79 |
84 |
85 | ); 86 | }; 87 | -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/sidebar/SidebarButton.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import Link from "next/link"; 4 | 5 | import { cn } from "@/lib/utils"; 6 | import * as LucideIcons from "lucide-react"; 7 | import { usePathname } from "next/navigation"; 8 | 9 | type SidebarButton = { 10 | slug: string; 11 | name: string; 12 | icon?: string; 13 | isNew?: boolean; 14 | isBeta?: boolean; 15 | isUpdated?: boolean; 16 | onClick?: () => void; 17 | }; 18 | 19 | export function SidebarButton({ 20 | name, 21 | slug, 22 | icon, 23 | isNew = false, 24 | isBeta = false, 25 | isUpdated = false, 26 | onClick, 27 | ...props 28 | }: SidebarButton) { 29 | const pathname = usePathname(); 30 | 31 | const isIndexPage = slug === "/docs/index"; 32 | const isActive = isIndexPage 33 | ? pathname === "/docs" || pathname === "/docs/index" 34 | : pathname === slug; 35 | 36 | const href = isIndexPage ? "/docs" : slug; 37 | 38 | 39 | const IconComponent = icon && (LucideIcons as any)[icon] ? (LucideIcons as any)[icon] : null; 40 | 41 | return ( 42 | 54 | {isNew && ( 55 |
56 | {name} 57 |
63 | New 64 |
65 |
66 | )} 67 | {isBeta && ( 68 |
69 | {name} 70 |
76 | Beta 77 |
78 |
79 | )} 80 | {isUpdated && ( 81 |
82 | {name} 83 | 84 | Updated 85 | 86 |
87 | )} 88 | {!isUpdated && !isNew && !isBeta && ( 89 | 90 | {IconComponent && ( 91 | 92 | )} 93 | {name} 94 | )} 95 | 96 | ); 97 | } 98 | -------------------------------------------------------------------------------- /apps/docs/app/docs/_components/sidebar/SidebarButton.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import Link from "next/link"; 4 | 5 | import { cn } from "@/lib/utils"; 6 | import * as LucideIcons from "lucide-react"; 7 | import { usePathname } from "next/navigation"; 8 | 9 | type SidebarButton = { 10 | slug: string; 11 | name: string; 12 | icon?: string; 13 | isNew?: boolean; 14 | isBeta?: boolean; 15 | isUpdated?: boolean; 16 | onClick?: () => void; 17 | }; 18 | 19 | export function SidebarButton({ 20 | name, 21 | slug, 22 | icon, 23 | isNew = false, 24 | isBeta = false, 25 | isUpdated = false, 26 | onClick, 27 | ...props 28 | }: SidebarButton) { 29 | const pathname = usePathname(); 30 | 31 | const isIndexPage = slug === "/docs/index"; 32 | const isActive = isIndexPage 33 | ? pathname === "/docs" || pathname === "/docs/index" 34 | : pathname === slug; 35 | 36 | const href = isIndexPage ? "/docs" : slug; 37 | 38 | 39 | const IconComponent = icon && (LucideIcons as any)[icon] ? (LucideIcons as any)[icon] : null; 40 | 41 | return ( 42 | 54 | {isNew && ( 55 |
56 | {name} 57 |
63 | New 64 |
65 |
66 | )} 67 | {isBeta && ( 68 |
69 | {name} 70 |
76 | Beta 77 |
78 |
79 | )} 80 | {isUpdated && ( 81 |
82 | {name} 83 | 84 | Updated 85 | 86 |
87 | )} 88 | {!isUpdated && !isNew && !isBeta && ( 89 | 90 | {IconComponent && ( 91 | 92 | )} 93 | {name} 94 | )} 95 | 96 | ); 97 | } 98 | -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/sidebar/Sidebar.tsx: -------------------------------------------------------------------------------- 1 | import { ScrollArea } from "@/components/ui/scroll-area"; 2 | import { getDocsMdx, getMetaConfig } from "@/lib/mdx"; 3 | import { SidebarButton } from "./SidebarButton"; 4 | 5 | // Define the structure for grouped docs 6 | interface GroupedDocs { 7 | [category: string]: Array<{ 8 | title: string; 9 | slug: string; 10 | icon?: string; 11 | isNew?: boolean; 12 | }>; 13 | } 14 | 15 | export const getMDXdocs = getDocsMdx("ui").sort((a, b) => 16 | a.title.localeCompare(b.title), 17 | ); 18 | 19 | // Function to group docs based on meta.json structure 20 | function groupDocsFromMeta(): GroupedDocs { 21 | const metaConfig = getMetaConfig("ui"); 22 | const grouped: GroupedDocs = {}; 23 | 24 | if (!metaConfig) { 25 | // Fallback to simple grouping if meta.json is not available 26 | getMDXdocs.forEach((doc) => { 27 | if (!grouped['Docs']) { 28 | grouped['Docs'] = []; 29 | } 30 | grouped['Docs'].push({ 31 | title: doc.title, 32 | slug: doc.slug, 33 | icon: doc.icon, 34 | isNew: doc.isNew, 35 | }); 36 | }); 37 | return grouped; 38 | } 39 | 40 | let currentCategory = 'Default'; 41 | 42 | metaConfig.pages.forEach((page) => { 43 | // Check if this is a category heading (starts and ends with ---) 44 | if (page.startsWith('---') && page.endsWith('---')) { 45 | currentCategory = page.replace(/---/g, '').trim(); 46 | if (!grouped[currentCategory]) { 47 | grouped[currentCategory] = []; 48 | } 49 | return; 50 | } 51 | 52 | // Find the corresponding MDX doc 53 | const doc = getMDXdocs.find((d) => d.slug === page); 54 | if (doc) { 55 | if (!grouped[currentCategory]) { 56 | grouped[currentCategory] = []; 57 | } 58 | 59 | grouped[currentCategory].push({ 60 | title: doc.title, 61 | slug: doc.slug, 62 | icon: doc.icon, 63 | isNew: doc.isNew, 64 | }); 65 | } 66 | }); 67 | 68 | return grouped; 69 | } 70 | 71 | export function Sidebar() { 72 | const groupedDocs = groupDocsFromMeta(); 73 | const categories = Object.keys(groupedDocs); 74 | 75 | console.log("Cat", groupedDocs) 76 | 77 | return ( 78 | 103 | ); 104 | } -------------------------------------------------------------------------------- /packages/ui/src/pixaui/animated-tabs.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import type { Transition } from "motion/react"; 3 | import { AnimatePresence, motion } from "motion/react"; 4 | import { 5 | createContext, 6 | useContext, 7 | useId, 8 | useState, 9 | type ReactNode 10 | } from "react"; 11 | import { cn } from "../libs/cn"; 12 | 13 | type TabsContextType = { 14 | value: string; 15 | setValue: (val: string) => void; 16 | uniqueId: string; 17 | }; 18 | 19 | const TabsContext = createContext(null); 20 | 21 | function useTabsContext() { 22 | const context = useContext(TabsContext); 23 | if (!context) throw new Error("Must be used within "); 24 | return context; 25 | } 26 | 27 | // Let's simplify and not use compound components for now 28 | export function AnimatedTabs({ 29 | defaultValue, 30 | onValueChange, 31 | children, 32 | className, 33 | style, 34 | }: { 35 | defaultValue: string; 36 | onValueChange?: (val: string) => void; 37 | children: ReactNode; 38 | className?: string; 39 | style?: React.CSSProperties; 40 | }) { 41 | const [value, setValue] = useState(defaultValue); 42 | const uniqueId = useId(); 43 | 44 | const handleChange = (val: string) => { 45 | setValue(val); 46 | onValueChange?.(val); 47 | }; 48 | 49 | return ( 50 | 51 |
{children}
52 |
53 | ); 54 | } 55 | 56 | export function AnimatedTabsList({ children, className, style }: { children: ReactNode; className?: string, style?: React.CSSProperties }) { 57 | return
{children}
; 58 | } 59 | 60 | export function AnimatedTabsTrigger({ 61 | value, 62 | children, 63 | className, 64 | style, 65 | transition = { 66 | type: 'spring', 67 | stiffness: 300, 68 | damping: 22, 69 | }, 70 | }: { 71 | value: string; 72 | children: ReactNode; 73 | className?: string; 74 | style?: React.CSSProperties; 75 | transition?: Transition; 76 | }) { 77 | const { value: active, setValue, uniqueId } = useTabsContext(); 78 | const isActive = active === value; 79 | 80 | return ( 81 |
setValue(value)} 83 | data-checked={isActive} 84 | className={cn( 85 | "relative p-2 cursor-pointer transition-colors", 86 | isActive ? "text-foreground" : "text-muted-foreground", 87 | className 88 | )} 89 | > 90 | 91 | {isActive && ( 92 | 98 | )} 99 | 100 | {children} 101 |
102 | ); 103 | } 104 | 105 | export function AnimatedTabsContent({ 106 | value, 107 | children, 108 | className, 109 | }: { 110 | value: string; 111 | children: ReactNode; 112 | className?: string; 113 | }) { 114 | const { value: active } = useTabsContext(); 115 | 116 | if (active !== value) return null; 117 | 118 | return
{children}
; 119 | } -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/Pagination.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react"; 4 | import { cn } from "@/lib/utils"; 5 | 6 | type PaginationProps = { 7 | back?: { 8 | href: string; 9 | title: string; 10 | }; 11 | next?: { 12 | href: string; 13 | title: string; 14 | }; 15 | }; 16 | 17 | export function Pagination({ back, next }: PaginationProps) { 18 | return ( 19 |
20 | {back?.href && back?.title && ( 21 | 25 |
26 | 27 | Previous 28 |
29 | 30 | {back.title} 31 | 32 | 33 | )} 34 | {next?.href && next?.title && ( 35 | 39 |
40 | 41 | Next 42 | 43 | 44 |
45 | 46 | {next.title} 47 | 48 | 49 | )} 50 |
51 | ); 52 | } 53 | 54 | function ChevronIconGlitch({ 55 | direction = "left", 56 | }: { 57 | direction?: "left" | "right"; 58 | }) { 59 | return ( 60 |
61 | 62 | {direction === "left" ? ( 63 | 64 | ) : ( 65 | 66 | )} 67 | 68 | 76 | {direction === "left" ? ( 77 | 78 | ) : ( 79 | 80 | )} 81 | 82 | 88 | {direction === "left" ? ( 89 | 90 | ) : ( 91 | 92 | )} 93 | 94 |
95 | ); 96 | } 97 | -------------------------------------------------------------------------------- /apps/docs/lib/mdx.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | 4 | import type { Docs } from "@/types/docs"; 5 | import matter from "gray-matter"; 6 | 7 | export interface DocsMdx { 8 | title: string; 9 | description: string; 10 | slug: string; 11 | icon?: string; 12 | isNew?: boolean; 13 | content: string; 14 | externalDocs?: string; 15 | externalApi?: string; 16 | } 17 | 18 | // Define the structure for meta.json 19 | export interface MetaConfig { 20 | root: boolean; 21 | title: string; 22 | description: string; 23 | pages: string[]; 24 | } 25 | 26 | // Function to read and parse meta.json 27 | export function getMetaConfig(docsType: string): MetaConfig | null { 28 | try { 29 | const metaPath = path.join( 30 | process.cwd(), 31 | "app", 32 | "_content", 33 | docsType, 34 | "meta.json" 35 | ); 36 | const metaContent = fs.readFileSync(metaPath, "utf8"); 37 | return JSON.parse(metaContent) as MetaConfig; 38 | } catch (error) { 39 | console.warn( 40 | "meta.json not found or invalid, falling back to default grouping", error 41 | ); 42 | return null; 43 | } 44 | } 45 | 46 | export function getDocsMdx(docsType: string): DocsMdx[] { 47 | const docsDirectory = path.join(process.cwd(), "app", "_content", docsType); 48 | 49 | // Get all .mdx files 50 | const files = fs 51 | .readdirSync(docsDirectory) 52 | .filter((file) => file.endsWith(".mdx")); 53 | 54 | const docs = files.map((file) => { 55 | const source = fs.readFileSync(path.join(docsDirectory, file), "utf8"); 56 | const { data: frontmatter, content } = matter(source); 57 | 58 | return { 59 | title: frontmatter.title || "", 60 | description: frontmatter.description || "", 61 | slug: frontmatter.slug || file.replace(/\.mdx$/, ""), 62 | icon: frontmatter.icon, 63 | isNew: frontmatter.isNew || false, 64 | content, 65 | externalDocs: frontmatter.externalDocs, 66 | externalApi: frontmatter.externalApi, 67 | }; 68 | }); 69 | 70 | return docs; 71 | } 72 | 73 | function readFile(filePath: string): Docs | null { 74 | try { 75 | const rawContent = fs.readFileSync(filePath, "utf-8"); 76 | const { data, content } = matter(rawContent); 77 | 78 | const slug = path.basename(filePath, path.extname(filePath)); 79 | 80 | return { 81 | ...data, 82 | slug, 83 | content, 84 | } as Docs; 85 | } catch (error) { 86 | console.error(`Failed to read or parse the file at ${filePath}:`, error); 87 | return null; 88 | } 89 | } 90 | 91 | function getFiles(dir: string): string[] { 92 | try { 93 | return fs.readdirSync(dir).filter((file) => path.extname(file) === ".mdx"); 94 | } catch (error) { 95 | console.error(`Failed to read directory at ${dir}:`, error); 96 | return []; 97 | } 98 | } 99 | 100 | // mdx for ui which is present in app/_content/ui 101 | export function getDocs(directory?: string): Docs[] { 102 | const files = getFiles( 103 | path.join( 104 | process.cwd(), 105 | "app", 106 | "_content/ui", 107 | ...(directory ? [directory] : []) 108 | ) 109 | ); 110 | 111 | return files 112 | .map((file) => 113 | readFile( 114 | path.join( 115 | process.cwd(), 116 | "app", 117 | "_content/ui", 118 | ...(directory ? [directory] : []), 119 | file 120 | ) 121 | ) 122 | ) 123 | .filter((docs): docs is Docs => docs !== null); 124 | } 125 | -------------------------------------------------------------------------------- /apps/docs/lib/repo-utils.ts: -------------------------------------------------------------------------------- 1 | // lib/repo-utils.ts 2 | 3 | export interface RepoLastUpdateOptions { 4 | owner: string; 5 | repo: string; 6 | token?: string; 7 | } 8 | 9 | export interface RepoLastUpdateResponse { 10 | lastUpdated: Date | null; 11 | lastCommit?: { 12 | message: string; 13 | author: string; 14 | sha: string; 15 | url: string; 16 | }; 17 | } 18 | 19 | /** 20 | * Get the last updated time for a GitHub repository 21 | * Uses the latest commit to the default branch 22 | */ 23 | export async function getRepoLastUpdate({ 24 | owner, 25 | repo, 26 | token, 27 | }: RepoLastUpdateOptions): Promise { 28 | try { 29 | // Get repository info first to get the default branch 30 | const repoUrl = `https://api.github.com/repos/${owner}/${repo}`; 31 | 32 | const headers: Record = { 33 | Accept: "application/vnd.github.v3+json", 34 | "User-Agent": "Portfolio-Website", 35 | }; 36 | 37 | if (token) { 38 | headers["Authorization"] = token.startsWith("Bearer ") 39 | ? token 40 | : `Bearer ${token}`; 41 | } 42 | 43 | // Get repo info to find default branch 44 | const repoResponse = await fetch(repoUrl, { headers }); 45 | 46 | if (!repoResponse.ok) { 47 | throw new Error( 48 | `GitHub API error: ${repoResponse.status} ${repoResponse.statusText}` 49 | ); 50 | } 51 | 52 | const repoData = await repoResponse.json(); 53 | const defaultBranch = repoData.default_branch || "main"; 54 | 55 | // Get the latest commit from the default branch 56 | const commitsUrl = `https://api.github.com/repos/${owner}/${repo}/commits/${defaultBranch}`; 57 | const commitResponse = await fetch(commitsUrl, { headers }); 58 | 59 | if (!commitResponse.ok) { 60 | throw new Error( 61 | `GitHub API error: ${commitResponse.status} ${commitResponse.statusText}` 62 | ); 63 | } 64 | 65 | const commitData = await commitResponse.json(); 66 | 67 | return { 68 | lastUpdated: new Date(commitData.commit.committer.date), 69 | lastCommit: { 70 | message: commitData.commit.message, 71 | author: commitData.commit.author.name, 72 | sha: commitData.sha, 73 | url: commitData.html_url, 74 | }, 75 | }; 76 | } catch (error) { 77 | console.error("Error fetching repository last update:", error); 78 | return { lastUpdated: null }; 79 | } 80 | } 81 | 82 | /** 83 | * Utility to format the last updated date 84 | */ 85 | export function formatLastUpdated(date: Date | null): string { 86 | if (!date) return "Unknown"; 87 | 88 | return new Intl.DateTimeFormat("en-US", { 89 | year: "numeric", 90 | month: "long", 91 | day: "numeric", 92 | }).format(date); 93 | } 94 | 95 | /** 96 | * Utility to get relative time (e.g., "2 days ago") 97 | */ 98 | export function getRelativeTime(date: Date | null): string { 99 | if (!date) return "Unknown"; 100 | 101 | const now = new Date(); 102 | const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000); 103 | 104 | const timeUnits = [ 105 | { unit: "year", seconds: 31536000 }, 106 | { unit: "month", seconds: 2592000 }, 107 | { unit: "day", seconds: 86400 }, 108 | { unit: "hour", seconds: 3600 }, 109 | { unit: "minute", seconds: 60 }, 110 | ]; 111 | 112 | for (const { unit, seconds } of timeUnits) { 113 | const interval = Math.floor(diffInSeconds / seconds); 114 | if (interval >= 1) { 115 | return `${interval} ${unit}${interval > 1 ? "s" : ""} ago`; 116 | } 117 | } 118 | 119 | return "Just now"; 120 | } 121 | -------------------------------------------------------------------------------- /apps/docs/app/about/page.tsx: -------------------------------------------------------------------------------- 1 | import { XIcon } from "@/components/icons"; 2 | import { Badge } from "@/components/ui/badge"; 3 | import { Button } from "@/components/ui/Button"; 4 | import PixaBackground from "@/components/ui/pixa-background"; 5 | import siteData from "@/data/siteData"; 6 | import { GitHubLogoIcon, LinkedInLogoIcon } from "@radix-ui/react-icons"; 7 | import Link from "next/link"; 8 | 9 | const page = () => { 10 | const { twitter, github, linkedin } = siteData.personalInfo; 11 | return ( 12 |
13 | 14 |
15 |
16 |

17 | About 18 |

19 |

20 | Pixa UI is a curated collection of versatile  21 | Next.js 22 |  components 23 |

24 |
25 |

26 | As a developer, I often find it challenging to locate unique, 27 | accessible components. Many are paid, or simply unavailable. With 28 | Pixa UI, I've built a library of components that I can use 29 | freely, and now you can too! 30 |

31 |
32 |

33 | Pixa UI is open source and available 34 | for everyone. Feel free to use it in your projects, and if you 35 | have unique components to share, contributions are welcome! 36 | Together, we can make this library more valuable for the 37 | community. 38 |

39 |
40 |

41 | Have questions or suggestions? Feel free to reach out! 42 |

43 |
44 |
45 |

46 | Lokendra Kushwah 47 |

48 |
49 | 54 |
55 | 60 |
61 | 66 |
67 |
68 |
69 |
70 |
71 | ); 72 | }; 73 | 74 | export default page; 75 | -------------------------------------------------------------------------------- /apps/docs/app/_content/docs/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | description: What is Pixa UI and why you should use it. 4 | icon: ScrollText 5 | --- 6 | 7 | ## What is Pixa UI? 8 | Pixa UI is a curated collection of versatile **Next.js** components that I've built from my own frustrations as a developer. You know that feeling when you're deep in a project, need a specific component, and spend hours searching through documentation only to find it's either behind a paywall or doesn't exist at all? That's exactly why Pixa UI exists. 9 | 10 | As a developer, I often find it challenging to locate unique, accessible components. Many are paid, poorly documented, or simply unavailable when you need them most. With Pixa UI, I've built a library of components that solve real problems I've encountered in my own projects - and now you can use them too, completely free. 11 | 12 | This isn't just another component library collecting dust. Every component in Pixa UI has been crafted and refined through actual use cases, and designed with the developer experience in mind. It's the toolkit I wish I had when I started building modern web applications. 13 | 14 | ## Why Pixa UI? 15 | Building beautiful, functional UIs shouldn't feel like reinventing the wheel every single time. We've all been there - copying and pasting code from Stack Overflow, trying to adapt components that almost work, or spending entire weekends building something that should take minutes. 16 | 17 | Pixa UI changes that. Each component is crafted to be: 18 | - **Immediately usable** - Copy, paste, and you're done 19 | - **Highly customizable** - Built with Tailwind CSS, so styling feels natural 20 | - **Accessible by default** - Because good UX shouldn't be an afterthought 21 | - **Production-ready** - No prototype code or "coming soon" placeholders 22 | 23 | The components aren't just pretty interfaces - they're solving real problems. Need a file upload that actually handles edge cases? A data table that doesn't break on mobile? A search interface that feels snappy? These are the components I've built because I needed them, and chances are, you do too. 24 | 25 | ## Open Source Philosophy 26 | 27 | Pixa UI is **open source** and available for everyone. This isn't a freemium model or a marketing funnel - it's a genuine contribution to the developer community. I believe that good tools should be accessible to everyone, whether you're a solo developer building your first project or part of a team at a growing startup. 28 | 29 | Feel free to use it in your projects, modify it to fit your needs, and if you have unique components to share, contributions are welcome! Together, we can make this library more valuable for the entire community. Every component added, every bug fixed, every documentation improvement makes the ecosystem better for everyone. 30 | 31 | ## Who is Pixa UI for? 32 | 33 | If you're building with Next.js and want to focus on what makes your application unique instead of rebuilding common UI patterns, Pixa UI is for you. It's perfect for: 34 | 35 | - **Solo developers** - who need to ship fast without compromising on quality 36 | - **Small teams** - that want to maintain consistency without a dedicated design system 37 | - **Experienced developers** - who appreciate well-crafted components they can build upon 38 | - **Anyone** - who's tired of the endless cycle of searching, adapting, and debugging components 39 | 40 | You don't need to be a CSS wizard or a design expert. These components work out of the box and look great, but they're also flexible enough to match your project's unique style and requirements. 41 | 42 | ## Community and Support 43 | 44 | Have questions or suggestions? Feel free to reach out! I'm always excited to hear how people are using Pixa UI, what challenges they're facing, and what components would make their development experience better. 45 | 46 | This project grows with the community's needs. Every piece of feedback, every use case, and every contribution helps shape what Pixa UI becomes. Together, we're building something that makes development more enjoyable and productive for everyone. -------------------------------------------------------------------------------- /apps/docs/app/buttons/2/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import ButtonSlideUp from "@repo/ui/pixaui/button-slide-up"; 3 | import CodeBlock from "@/components/Table/CodeBlock"; 4 | import { PropsTable } from "@/components/Table/PropsTable"; 5 | import SliderComponent from "@/components/Table/SliderComponent"; 6 | import { codeData, data, installationData } from "@/data/buttons/2/Button"; 7 | import { ChevronLeft } from "lucide-react"; 8 | import Link from "next/link"; 9 | import React, { useState } from "react"; 10 | 11 | const Page = () => { 12 | const [borderRadius, setBorderRadius] = useState(10); 13 | const [textSize, setTextSize] = useState(18); 14 | const [color, setColor] = useState("#00fff04c"); 15 | 16 | const handleSliderChange = (value: number[]) => { 17 | setBorderRadius(value[0]); 18 | }; 19 | 20 | const handleTextSizeChange = (value: number[]) => { 21 | setTextSize(value[0]); 22 | }; 23 | 24 | const handleColorChange = (event: React.ChangeEvent) => { 25 | setColor(event.target.value); 26 | }; 27 | 28 | return ( 29 | <> 30 |
31 |
32 | 33 | 38 |

Back

39 | 40 |
41 |
42 | 51 |
52 |
53 | 54 | 62 | 70 |
71 | 77 | 84 |
85 |
86 |
87 | 88 | 89 |
90 |
91 | 92 | ); 93 | }; 94 | 95 | export default Page; 96 | -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/Tabs.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import * as TabsPrimitive from "@radix-ui/react-tabs"; 5 | 6 | import { AnimatePresence, motion } from "motion/react"; 7 | 8 | import { cn } from "@/lib/utils"; 9 | 10 | const Tabs = TabsPrimitive.Root; 11 | 12 | const TabsContext = React.createContext(""); 13 | 14 | const TabsRoot = React.forwardRef< 15 | React.ElementRef, 16 | React.ComponentPropsWithoutRef 17 | >(({ ...props }, ref) => { 18 | const uniqueId = React.useId(); 19 | 20 | return ( 21 | 22 | 23 | 24 | ); 25 | }); 26 | TabsRoot.displayName = "TabsRoot"; 27 | 28 | const TabsList = React.forwardRef< 29 | React.ElementRef, 30 | React.ComponentPropsWithoutRef 31 | >(({ className, ...props }, ref) => ( 32 | 40 | )); 41 | TabsList.displayName = TabsPrimitive.List.displayName; 42 | 43 | const TabsTrigger = React.forwardRef< 44 | React.ElementRef, 45 | React.ComponentPropsWithoutRef & { 46 | classNameIndicator?: string; 47 | } 48 | >(({ className, children, classNameIndicator, ...props }) => { 49 | const triggerRef = React.useRef(null); 50 | const [isActive, setIsActive] = React.useState(false); 51 | const tabsId = React.useContext(TabsContext); 52 | 53 | React.useEffect(() => { 54 | const element = triggerRef.current; 55 | 56 | if (element) { 57 | setIsActive(element.dataset.state === "active"); 58 | 59 | const observer = new MutationObserver(() => { 60 | setIsActive(element.dataset.state === "active"); 61 | }); 62 | 63 | observer.observe(element, { attributes: true }); 64 | 65 | return () => observer.disconnect(); 66 | } 67 | }, []); 68 | 69 | return ( 70 | 78 | 79 | {isActive && ( 80 | 92 |
93 | 94 | )} 95 | 96 | {children} 97 | 98 | ); 99 | }); 100 | TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; 101 | 102 | const TabsContent = React.forwardRef< 103 | React.ElementRef, 104 | React.ComponentPropsWithoutRef 105 | >(({ className, ...props }, ref) => ( 106 | 114 | )); 115 | TabsContent.displayName = TabsPrimitive.Content.displayName; 116 | 117 | export { TabsRoot as Tabs, TabsList, TabsTrigger, TabsContent }; 118 | -------------------------------------------------------------------------------- /apps/docs/app/buttons/5/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import ButtonUnflatten from "@repo/ui/pixaui/button-unflatten"; 3 | import CodeBlock from "@/components/Table/CodeBlock"; 4 | import { PropsTable } from "@/components/Table/PropsTable"; 5 | import SliderComponent from "@/components/Table/SliderComponent"; 6 | import { 7 | codeData, 8 | data, 9 | installationData, 10 | } from "@/data/buttons/5/Button"; 11 | import { ChevronLeft } from "lucide-react"; 12 | import Link from "next/link"; 13 | import React, { useState } from "react"; 14 | 15 | const Page = () => { 16 | const [borderRadius, setBorderRadius] = useState(10); 17 | const [textSize, setTextSize] = useState(18); 18 | const [color, setColor] = useState("#191919"); 19 | 20 | const handleSliderChange = (value: number[]) => { 21 | setBorderRadius(value[0]); 22 | }; 23 | 24 | const handleTextSizeChange = (value: number[]) => { 25 | setTextSize(value[0]); 26 | }; 27 | 28 | const handleColorChange = (event: React.ChangeEvent) => { 29 | setColor(event.target.value); 30 | }; 31 | 32 | return ( 33 | <> 34 |
35 |
36 | 37 | 42 |

Back

43 | 44 |
45 |
46 | 55 |
56 |
57 | 58 | 66 | 74 |
75 | 81 | 88 |
89 |
90 |
91 | 92 | 93 |
94 |
95 | 96 | ); 97 | }; 98 | 99 | export default Page; 100 | -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/OnThisPage.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useCallback, useEffect, useState } from "react"; 4 | 5 | import { motion } from "motion/react"; 6 | import { usePathname } from "next/navigation"; 7 | import { cn } from "@/lib/utils"; 8 | 9 | type Heading = { 10 | id: string; 11 | text: string; 12 | level: string; 13 | }; 14 | 15 | export function OnThisPage() { 16 | const [headings, setHeadings] = useState([]); 17 | const [visibleHeadings, setVisibleHeadings] = useState>( 18 | new Set(), 19 | ); 20 | 21 | const pathname = usePathname(); 22 | 23 | const getHeadings = useCallback(() => { 24 | const headingElement = document.querySelectorAll("h1, h2, h3"); 25 | 26 | return Array.from(headingElement) 27 | .filter((heading) => { 28 | const isInDialog = heading.closest('[role="dialog"]'); 29 | 30 | return heading.id && !isInDialog; 31 | }) 32 | .map((heading) => ({ 33 | id: heading.id, 34 | text: heading.textContent || "", 35 | level: heading.tagName.toLowerCase(), 36 | top: (heading as HTMLElement).offsetTop, 37 | })); 38 | }, []); 39 | 40 | useEffect(() => { 41 | const collectedHeadings = getHeadings(); 42 | 43 | setHeadings(collectedHeadings); 44 | 45 | const observerOptions = { 46 | root: null, 47 | threshold: 0, 48 | }; 49 | 50 | function handleIntersection(entries: IntersectionObserverEntry[]) { 51 | const visibleSet = new Set(visibleHeadings); 52 | 53 | for (const entry of entries) { 54 | const headingId = entry.target.id; 55 | 56 | if (entry.isIntersecting) { 57 | visibleSet.add(headingId); 58 | } else { 59 | visibleSet.delete(headingId); 60 | } 61 | } 62 | 63 | setVisibleHeadings(new Set(visibleSet)); 64 | } 65 | 66 | const observer = new IntersectionObserver(handleIntersection, { 67 | ...observerOptions, 68 | }); 69 | 70 | for (const heading of collectedHeadings) { 71 | const el = document.getElementById(heading.id); 72 | 73 | if (el) observer.observe(el); 74 | } 75 | 76 | return () => { 77 | observer.disconnect(); 78 | }; 79 | }, [getHeadings, visibleHeadings, pathname]); 80 | 81 | function handleScroll(id: string) { 82 | for (const heading of Array.from(document.querySelectorAll("h1,h2,h3"))) { 83 | heading.setAttribute("data-highlight", "false"); 84 | } 85 | 86 | const element = document.getElementById(id); 87 | 88 | if (element) { 89 | const top = element.offsetTop - 100; 90 | 91 | window.scrollTo({ 92 | top, 93 | behavior: "smooth", 94 | }); 95 | 96 | element.setAttribute("data-highlight", "true"); 97 | 98 | setTimeout(() => { 99 | element.setAttribute("data-highlight", "false"); 100 | }, 2000); 101 | } 102 | } 103 | 104 | return ( 105 | 112 |
113 | {headings.map(({ id, text, level }) => { 114 | const isActive = visibleHeadings.has(id); 115 | 116 | return ( 117 | 132 | ); 133 | })} 134 |
135 |
136 | ); 137 | } 138 | -------------------------------------------------------------------------------- /apps/docs/app/buttons/4/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import CodeBlock from "@/components/Table/CodeBlock"; 3 | import { PropsTable } from "@/components/Table/PropsTable"; 4 | import SliderComponent from "@/components/Table/SliderComponent"; 5 | import ButtonSlideLeft from "@repo/ui/pixaui/button-slide-left"; 6 | import { 7 | codeData, 8 | data, 9 | installationData, 10 | } from "@/data/buttons/4/Button"; 11 | import { ChevronLeft } from "lucide-react"; 12 | import Link from "next/link"; 13 | import React, { useState } from "react"; 14 | 15 | const Page = () => { 16 | const [borderRadius, setBorderRadius] = useState(10); 17 | const [textSize, setTextSize] = useState(18); 18 | const [color, setColor] = useState("#763afe"); 19 | 20 | const handleSliderChange = (value: number[]) => { 21 | setBorderRadius(value[0]); 22 | }; 23 | 24 | const handleTextSizeChange = (value: number[]) => { 25 | setTextSize(value[0]); 26 | }; 27 | 28 | const handleColorChange = (event: React.ChangeEvent) => { 29 | setColor(event.target.value); 30 | }; 31 | 32 | return ( 33 | <> 34 |
35 |
36 | 37 | 42 |

Back

43 | 44 |
45 |
46 | 55 |
56 |
57 | 58 | 66 | 74 |
75 | 81 | 88 |
89 |
90 |
91 | 92 | 93 |
94 |
95 | 96 | ); 97 | }; 98 | 99 | export default Page; 100 | -------------------------------------------------------------------------------- /apps/docs/components/sections/hero.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { Loader } from "lucide-react"; 3 | import Link from "next/link"; 4 | import { useState } from "react"; 5 | import { SiNextdotjs, SiReact, SiTailwindcss, SiTypescript } from "react-icons/si"; 6 | import { PixaLogo, SiShadcnIcon } from "../icons"; 7 | import { Button } from "../ui/Button"; 8 | import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; 9 | import { ResponsiveDialog } from "./dia"; 10 | 11 | const Hero = () => { 12 | 13 | const ICONS = [ 14 | { name: "Next.js", icon: SiNextdotjs }, 15 | { name: "React.js", icon: SiReact }, 16 | { name: "Tailwind CSS", icon: SiTailwindcss }, 17 | { name: "TypeScript", icon: SiTypescript }, 18 | { name: "shadcn/ui", icon: SiShadcnIcon }, 19 | ] 20 | const [open, setOpen] = useState(false); 21 | const [isLoading, setIsLoading] = useState(false); 22 | const handleCancel = async () => { 23 | setIsLoading(true); 24 | try { 25 | console.log('Cancelling subscription...'); 26 | setOpen(false); 27 | } catch (error) { 28 | console.error('Cancellation failed', error); 29 | } finally { 30 | setIsLoading(false); 31 | } 32 | }; 33 | 34 | const onOpenChange = (value: boolean) => { 35 | setOpen(value); 36 | }; 37 | 38 | return ( 39 |
40 |
41 | 42 |

43 | Build faster with beautifully crafted components 44 |

45 |

46 | Pixa UI is a composable and accessible collection of open-source Next.js components built with shadcn/ui and Tailwind CSS. 47 |

48 |
49 | 54 | 59 |
60 | Cancel Subscription} 65 | > 66 |
67 |

Are you sure you want to cancel your subscription?

68 |

69 | If you cancel now, you'll lose access immediately. You can always start a new 70 | subscription later, but you won't get another free trial. 71 |

72 |
73 |
74 | 77 | 81 |
82 |
83 |
84 |

Built with

85 | {ICONS.map((icon) => ( 86 | 87 | 88 | 89 | 90 | 93 | {icon.name} 94 | 95 | 96 | ))} 97 |
98 |
99 |
100 | ); 101 | }; 102 | 103 | export default Hero; -------------------------------------------------------------------------------- /apps/docs/app/buttons/3/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import CodeBlock from "@/components/Table/CodeBlock"; 3 | import { PropsTable } from "@/components/Table/PropsTable"; 4 | import SliderComponent from "@/components/Table/SliderComponent"; 5 | import ButtonAi from "@repo/ui/pixaui/button-ai"; 6 | import { codeData, data, installationData } from "@/data/buttons/3/Button"; 7 | import { ChevronLeft } from "lucide-react"; 8 | import Link from "next/link"; 9 | import React, { useState } from "react"; 10 | 11 | const Page = () => { 12 | const [borderRadius, setBorderRadius] = useState(10); 13 | const [textSize, setTextSize] = useState(18); 14 | const [padding, setPadding] = useState(12); 15 | const [color, setColor] = useState("#763afe"); 16 | 17 | const handleSliderChange = (value: number[]) => { 18 | setBorderRadius(value[0]); 19 | }; 20 | 21 | const handleTextSizeChange = (value: number[]) => { 22 | setTextSize(value[0]); 23 | }; 24 | 25 | const handlePaddingChange = (value: number[]) => { 26 | setPadding(value[0]); 27 | }; 28 | 29 | const handleColorChange = (event: React.ChangeEvent) => { 30 | setColor(event.target.value); 31 | }; 32 | 33 | return ( 34 | <> 35 |
36 |
37 | 38 | 43 |

Back

44 | 45 |
46 |
47 | 56 | ButtonV3 57 | 58 |
59 |
60 | 61 | 69 | 77 | 85 |
86 | 92 | 99 |
100 |
101 |
102 | 103 | 104 |
105 |
106 | 107 | ); 108 | }; 109 | 110 | export default Page; 111 | -------------------------------------------------------------------------------- /apps/docs/components/ui/dialog.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as DialogPrimitive from "@radix-ui/react-dialog" 5 | import { XIcon } from "lucide-react" 6 | 7 | import { cn } from "@/lib/utils" 8 | 9 | function Dialog({ 10 | ...props 11 | }: React.ComponentProps) { 12 | return 13 | } 14 | 15 | function DialogTrigger({ 16 | ...props 17 | }: React.ComponentProps) { 18 | return 19 | } 20 | 21 | function DialogPortal({ 22 | ...props 23 | }: React.ComponentProps) { 24 | return 25 | } 26 | 27 | function DialogClose({ 28 | ...props 29 | }: React.ComponentProps) { 30 | return 31 | } 32 | 33 | function DialogOverlay({ 34 | className, 35 | ...props 36 | }: React.ComponentProps) { 37 | return ( 38 | 46 | ) 47 | } 48 | 49 | function DialogContent({ 50 | className, 51 | children, 52 | showCloseButton = true, 53 | ...props 54 | }: React.ComponentProps & { 55 | showCloseButton?: boolean 56 | }) { 57 | return ( 58 | 59 | 60 | 68 | {children} 69 | {showCloseButton && ( 70 | 74 | 75 | Close 76 | 77 | )} 78 | 79 | 80 | ) 81 | } 82 | 83 | function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { 84 | return ( 85 |
90 | ) 91 | } 92 | 93 | function DialogFooter({ className, ...props }: React.ComponentProps<"div">) { 94 | return ( 95 |
103 | ) 104 | } 105 | 106 | function DialogTitle({ 107 | className, 108 | ...props 109 | }: React.ComponentProps) { 110 | return ( 111 | 116 | ) 117 | } 118 | 119 | function DialogDescription({ 120 | className, 121 | ...props 122 | }: React.ComponentProps) { 123 | return ( 124 | 129 | ) 130 | } 131 | 132 | export { 133 | Dialog, 134 | DialogClose, 135 | DialogContent, 136 | DialogDescription, 137 | DialogFooter, 138 | DialogHeader, 139 | DialogOverlay, 140 | DialogPortal, 141 | DialogTitle, 142 | DialogTrigger, 143 | } 144 | -------------------------------------------------------------------------------- /apps/docs/components/Table/CodeBlock.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"; 3 | import { CheckIcon, ChevronDown, ChevronUp, CopyIcon } from "lucide-react"; 4 | import { useTheme } from "next-themes"; 5 | import { memo, useState } from "react"; 6 | import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; 7 | import { 8 | coldarkDark, 9 | prism, 10 | } from "react-syntax-highlighter/dist/cjs/styles/prism"; 11 | 12 | export const programmingLanguages = { 13 | javascript: ".js", 14 | python: ".py", 15 | java: ".java", 16 | c: ".c", 17 | cpp: ".cpp", 18 | "c++": ".cpp", 19 | "c#": ".cs", 20 | ruby: ".rb", 21 | php: ".php", 22 | swift: ".swift", 23 | "objective-c": ".m", 24 | kotlin: ".kt", 25 | typescript: ".ts", 26 | go: ".go", 27 | perl: ".pl", 28 | rust: ".rs", 29 | scala: ".scala", 30 | haskell: ".hs", 31 | lua: ".lua", 32 | shell: ".sh", 33 | sql: ".sql", 34 | html: ".html", 35 | css: ".css", 36 | tsx: ".tsx", 37 | bash: ".sh", 38 | // add more file extensions here 39 | }; 40 | 41 | const CodeBlock = memo(function CodeBlock({ 42 | language, 43 | value, 44 | filename = "", 45 | }: { 46 | language: keyof typeof programmingLanguages; 47 | value: string; 48 | filename?: string; 49 | }) { 50 | const { theme } = useTheme(); 51 | const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 }); 52 | const [expanded, setExpanded] = useState(false); 53 | 54 | const onCopy = () => { 55 | if (isCopied) return; 56 | copyToClipboard(value); 57 | }; 58 | 59 | const syntaxTheme = theme === "light" ? prism : coldarkDark; 60 | 61 | return ( 62 |
63 | {/* Header */} 64 |
65 | {filename} 66 |
67 | 78 |
79 |
80 | 81 | {/* Code container with show more */} 82 |
83 |
86 | 104 | {value} 105 | 106 |
107 | 108 | {/* Gradient & Button overlay */} 109 | {!expanded && value.split("\n").length > 20 && ( 110 |
111 | 117 |
118 | )} 119 |
120 | 121 | {/* Show less button */} 122 | {expanded && value.split("\n").length > 20 && ( 123 |
124 | 130 |
131 | )} 132 |
133 | 134 | ); 135 | }); 136 | 137 | export default CodeBlock; 138 | -------------------------------------------------------------------------------- /apps/docs/components/ui/pixa-background.tsx: -------------------------------------------------------------------------------- 1 | 2 | const PixaBackground = () => { 3 | return ( 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 | ) 41 | } 42 | 43 | export default PixaBackground -------------------------------------------------------------------------------- /apps/docs/app/ui/_components/cmdk/CommandMenuPrimitives.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { type DialogProps } from "@radix-ui/react-dialog"; 3 | import { Command as CommandPrimitive } from "cmdk"; 4 | 5 | import { cn } from "@/lib/utils"; 6 | import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog"; 7 | 8 | export const Command = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, ...props }, ref) => ( 12 | 17 | )); 18 | Command.displayName = CommandPrimitive.displayName; 19 | 20 | export const CommandDialog = ({ children, ...props }: DialogProps) => { 21 | return ( 22 | 23 | 24 | 25 | Search Command 26 | 27 | 28 | {children} 29 | 30 |
34 | 35 |
36 | ); 37 | }; 38 | 39 | export const CommandInput = React.forwardRef< 40 | React.ElementRef, 41 | React.ComponentPropsWithoutRef 42 | >(({ className, ...props }, ref) => ( 43 |
47 | 55 |
56 | )); 57 | 58 | CommandInput.displayName = CommandPrimitive.Input.displayName; 59 | 60 | export const CommandList = React.forwardRef< 61 | React.ElementRef, 62 | React.ComponentPropsWithoutRef 63 | >(({ className, ...props }, ref) => ( 64 | 69 | )); 70 | 71 | CommandList.displayName = CommandPrimitive.List.displayName; 72 | 73 | export const CommandEmpty = React.forwardRef< 74 | React.ElementRef, 75 | React.ComponentPropsWithoutRef 76 | >((props, ref) => ( 77 | 82 | )); 83 | 84 | CommandEmpty.displayName = CommandPrimitive.Empty.displayName; 85 | 86 | export const CommandGroup = React.forwardRef< 87 | React.ElementRef, 88 | React.ComponentPropsWithoutRef 89 | >(({ className, ...props }, ref) => ( 90 | 98 | )); 99 | 100 | CommandGroup.displayName = CommandPrimitive.Group.displayName; 101 | 102 | export const CommandSeparator = React.forwardRef< 103 | React.ElementRef, 104 | React.ComponentPropsWithoutRef 105 | >(({ className, ...props }, ref) => ( 106 | 111 | )); 112 | CommandSeparator.displayName = CommandPrimitive.Separator.displayName; 113 | 114 | export const CommandItem = React.forwardRef< 115 | React.ElementRef, 116 | React.ComponentPropsWithoutRef 117 | >(({ className, ...props }, ref) => ( 118 | 127 | )); 128 | 129 | CommandItem.displayName = CommandPrimitive.Item.displayName; 130 | -------------------------------------------------------------------------------- /apps/docs/app/_content/docs/setup.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Setup" 3 | description: "Install and configure Pixa UI components in your project" 4 | slug: "setup" 5 | icon: SquareTerminal 6 | --- 7 | 8 |
9 | 10 |
11 | 12 |
13 | 1 14 |
15 | 16 |
17 |
18 |

19 | Check Prerequisites 20 |

21 |

Before installing Pixa UI, make sure your environment meets the following requirements:

22 | 23 |
    24 |
  • • **Node.js**, version 18 or later
  • 25 |
  • • A **React** project, version 18 or later
  • 26 |
  • • **shadcn/ui** installed and configured with CSS Variables mode
  • 27 |
28 | 29 | 30 | 31 | **Important:** If you haven't installed shadcn/ui yet, run `npx shadcn@latest init` first to configure Tailwind CSS and base components. 32 | 33 | 34 |
35 |
36 | 37 |
38 | 39 |
40 |
41 | 2 42 |
43 |
44 |
45 | 46 |

Choose your installation method

47 | 48 |

You can install Pixa UI components using shadcn cli.

49 | 50 | {/* 51 | 52 | Pixa UI CLI 53 | shadcn/ui CLI 54 | 55 | 56 | 57 | 63 | 64 | 65 | */} 66 | 72 | {/* 73 | */} 74 | 75 |
76 | 77 |
78 | 79 |
80 | 81 |
82 |
83 | 3 84 |
85 |
86 | 87 |
88 | 89 |

Verify installation

90 | 91 |

The CLI will download the component's code and place it in your project directory. By default, components are added to:

92 | 93 | 94 | ``` 95 | @/components/ui/pixaui/gantt/ 96 | ``` 97 | 98 | 99 |

You should see a confirmation in your terminal that the files were added successfully.

100 | 101 |
102 | 103 |
104 | 105 |
106 | 107 |
108 |
109 | 4 110 |
111 |
112 | 113 |
114 | 115 |

Start using components

116 | 117 |

Once installed, you can immediately start using the component in your code:

118 | 119 | 120 | 121 | ```tsx 122 | import { Button } from "@/components/ui/Button" 123 | 124 | export default function Page() { 125 | return ( 126 |
127 |

Project Timeline

128 | 129 |
130 | ) 131 | } 132 | ``` 133 | 134 |
135 | 136 |
137 |

What's Next?

138 |
    139 |
  • • Browse available components in our component library
  • 140 |
  • • Check out examples and demos for each component
  • 141 |
  • • Customize components to match your design system
  • 142 |
  • • Contribute back to the community
  • 143 |
144 |
145 | 146 |
147 | 148 |
149 | 150 |
151 | 152 |
--------------------------------------------------------------------------------