@hetenho/showcase
v0.5.0
Published
A Storybook-like component manager that renders components from multiple frameworks (React, Vue, Solid, Angular, Lit) inside Shadow DOM for complete style isolation.
Readme
Showcase
A Storybook-like component manager that renders components from multiple frameworks (React, Vue, Solid, Angular, Lit) inside Shadow DOM for complete style isolation.
Features
- 🎨 Multi-Framework Support: Develop and showcase components from React, Vue, Solid, Angular, and Lit in one repository
- 🔒 Shadow DOM Isolation: Each component renders in its own Shadow DOM, ensuring complete style isolation
- 🧭 Auto-Discovery: Automatically finds components based on folder structure (
src/components/react/,src/components/vue/, etc.) - 🎛️ Interactive Props Panel: Edit component props in real-time with schema extraction from TypeScript types
- 🧪 Visual Snapshot Testing: Vitest + Playwright integration for visual regression testing
- ⚙️ Framework Switcher: Download updated
package.jsonfiles when switching between frameworks - 📦 Presets: Built-in support for Shadcn UI and Base UI component patterns
Quick Start
Installation
npm installDevelopment
npm run devThe app will start at http://localhost:5173 with your components automatically discovered.
CLI Binary
Run as a CLI tool (like Storybook):
npx showcase
# or
node bin/showcase.mjsComponent Structure
Organize your components by framework in src/components/:
src/components/
├── react/
│ ├── Button.tsx
│ └── Button.meta.ts # Optional: props schema
├── vue/
│ ├── Button.vue
│ └── Button.meta.ts
├── solid/
│ ├── Button.tsx
│ └── Button.meta.ts
├── angular/
│ └── Button.ts
└── lit/
└── Button.tsRoutes
Components automatically map to routes based on their folder path:
src/components/react/Button.tsx→/react/buttonsrc/components/vue/ui/Card.vue→/vue/ui/card
Props Extraction
Showcase automatically extracts component props using multiple strategies:
Meta Files (highest priority): Create
.meta.tsfiles alongside components// Button.meta.ts export const propsSchema = { fields: [ { name: "label", type: "text", default: "Click me" }, { name: "disabled", type: "boolean", default: false }, { name: "variant", type: "text", options: ["primary", "secondary"] } ] };Runtime Inspection: React components with
propTypesordefaultPropsare automatically detectedFunction Signatures: Default parameters in function components are inferred
Configuration
Create a showcase.config.ts in your project root:
import { defineShowcaseConfig } from "./src/showcase/config/defaults";
export default defineShowcaseConfig({
componentsDir: "src/components", // Default component directory
presets: ["shadcn"], // Enable presets
theme: "light", // "light" | "dark"
});Presets
Shadcn UI
When enabled, Shadcn components follow the @/components/ui pattern. Use the scaffold helpers:
import { scaffoldShadcnButton } from "./showcase/integrations/shadcn";
// Generate a Shadcn-styled Button component
const code = scaffoldShadcnButton("react");Base UI
Similar support for Base UI (MUI Base) components:
import { scaffoldBaseUiButton } from "./showcase/integrations/baseUi";
const code = scaffoldBaseUiButton("react");Testing
Visual Snapshot Tests
Write visual tests using Vitest and Playwright:
import { test, expect } from "vitest";
import { ensureViteServer } from "./utils/server";
import { toMatchImageSnapshot } from "vitest-image-snapshot";
expect.extend({ toMatchImageSnapshot });
test("React Button renders correctly", async () => {
const { page, server } = await ensureViteServer();
await page.goto("http://localhost:5173/react/button");
const canvas = page.locator('[data-showcase-canvas]');
await expect(canvas).toHaveScreenshot();
});Run tests:
# Install Playwright browser first
npx playwright install chromium
# Run tests
npm run test
# Update snapshots
npm run test:updateFramework Switcher
Use the toolbar to switch between frameworks. Click a framework button to:
- See what dependencies will be added
- Download an updated
package.json - Replace your existing file and run
npm install
Component Adapters
Components are rendered using framework-specific adapters:
- React: Uses
react-dom/clientcreateRoot - Vue: Dynamically imports Vue and uses
createApp - Solid: Uses
solid-js/webrenderer - Angular: Placeholder (implementation pending)
- Lit: Placeholder (implementation pending)
Optional Dependencies
Vue and Solid are loaded dynamically. If not installed, components gracefully fail with helpful error messages.
Props Panel
The right-side props panel allows:
- Editing props defined in the schema
- Adding custom/extended props on the fly
- Real-time updates to the component
Extended props are persisted in URL state, so you can share component states via URL.
Development Tips
- Fast Refresh: Works seamlessly with Vite's HMR
- Type Safety: TypeScript is fully supported
- Shadow DOM: Components are completely isolated - no CSS leakage
- Lazy Loading: Framework adapters are loaded on-demand
Examples
See src/components/ for example components:
- React Button with meta file
- Vue Button with async factory
- Solid Button with DOM fallback
- Lit Button example
License
MIT
