Shared Nextide shadcn/ui components with a Vite playground.
The implementation guide from nextide-saas-meta is copied into docs/brand_assets/NEXTIDE_BRAND_AGENT_GUIDE.md. The large PDF and font zip stay in the meta repo for now.
packages/ui/src/components: primitive shadcn-compatible components.packages/ui/src/blocks: composed, prop-driven Nextide app patterns such asAppShell,NavigationPanel, andWorkflowStepper.packages/ui/src/hooks: shared interaction hooks such asuseStagedDrawerfor collapse/expand drawer motion.apps/playground: Vite consumer app for visual checks.docs/component-map.md: quick lookup map for shared primitives, blocks, hooks, and the upstream workflow.docs/responsive-support.md: required responsive acceptance widths and shared component behavior.
Start with docs/component-map.md when deciding whether a UI element should be imported from @nextide/ui, polished upstream, or created as a new shared component.
Use docs/responsive-support.md when changing layout,
navigation, overflow, or responsive component behavior.
To add components to the shared UI package, run:
pnpm dlx shadcn@latest add button -c packages/uiThis will place the ui components in the packages/ui/src/components directory.
The package expects React 19 and Tailwind CSS 4. Install an exact release so a consumer upgrades deliberately:
pnpm add --save-exact @nextide/ui@2.0.0
pnpm add --save-dev --save-exact tailwindcss@4.3.1 @tailwindcss/vite@4.3.1Vite consumers need the Tailwind CSS Vite plugin. Import the shared stylesheet once in the application entry point, before app-specific styles:
// vite.config.ts
import tailwindcss from "@tailwindcss/vite"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"
export default defineConfig({ plugins: [react(), tailwindcss()] })// src/main.tsx
import "@nextide/ui/globals.css"
import "./app.css"Import only through the package's public subpaths:
import { AppShell } from "@nextide/ui/blocks/app-shell"
import { NavigationPanel } from "@nextide/ui/blocks/navigation-panel"
import { Button } from "@nextide/ui/components/button"
import { PopoverTrigger } from "@nextide/ui/components/popover"
import { useStagedDrawer } from "@nextide/ui/hooks/use-staged-drawer"The primitives use Base UI. When a Base UI trigger must adopt an existing
control, compose it with render; do not use Radix's asChild convention:
function DetailsTrigger() {
return (
<PopoverTrigger render={<Button variant="outline" />}>
Open details
</PopoverTrigger>
)
}Do not import from src or dist, and do not copy shared components into a
consumer. Fix reusable behavior here, publish a release, then update the
consumer's exact package version. See packages/ui/README.md
for the npm-facing quick start and docs/component-map.md
for the complete component map.
For local development against a sibling checkout, use a file dependency:
pnpm add "@nextide/ui@file:../nextide-ui/packages/ui"pnpm run check
pnpm exec playwright install chromium
pnpm run qualify
cd packages/ui
npm pack --dry-run --access publicpnpm run check remains the canonical lint, typecheck, build, and targeted
supply-chain release gate. Install Chromium once, then run the explicit,
headless pnpm run qualify gate for packed-package consumer resolution and
representative Chromium interaction, accessibility, and responsive checks.
Direct dependencies are pinned exactly. The workspace also enforces pnpm
release-age and build-script guardrails.
- Update
packages/ui/package.jsonand the install examples in both READMEs. - Run
pnpm run check,pnpm run qualify, and the package dry run above. - Merge the release commit and create a matching
v<version>tag on that merge. - Run Publish @nextide/ui manually with the exact tag.