com um clique
create-component
// Guide for creating a new UI component in @gridland/ui. Covers file structure, focus integration, keyboard handling, theme usage, JSDoc, export registration, and documentation.
// Guide for creating a new UI component in @gridland/ui. Covers file structure, focus integration, keyboard handling, theme usage, JSDoc, export registration, and documentation.
Review a component for production readiness as a UI framework. Assesses code quality, patterns, tests, docs, and API design. Produces a prioritized fix plan. Use before shipping a new or updated component to users.
Update context files to reflect current codebase state — new components, changed APIs, new patterns, and reasoning behind non-obvious decisions. Routes updates to the correct file based on what changed. Run after any significant design change before committing.
Audit the browser rendering pipeline for scissor/clipping bypass bugs. Use when touching browser-buffer.ts, canvas-painter.ts, or adding new visual features.
Diagnose layout issues in Gridland components. Spawns the layout-debugger agent with the relevant component. Use when a component renders incorrectly or layout looks wrong.
Pre-release checklist. Runs all 4 agents plus snapshot regression test, TypeScript check, and semver confirmation. Run before publishing a new package version.
Documentation-focused review. Runs docs-mirror and dependency-auditor in parallel. Use after writing or updating documentation, demo components, or MDX pages.
| name | create-component |
| description | Guide for creating a new UI component in @gridland/ui. Covers file structure, focus integration, keyboard handling, theme usage, JSDoc, export registration, and documentation. |
Guide for creating a new UI component in @gridland/ui.
packages/ui/components/<component-name>/
<component-name>.tsx # Main component file
// @ts-nocheck — only if using OpenTUI intrinsic elements (<box>, <text>, <span>)
import type { ReactNode } from "react"
import { textStyle } from "@/registry/gridland/lib/text-style"
import { useTheme } from "@/registry/gridland/lib/theme"
export interface MyComponentProps {
/** JSDoc every prop — agents and docs generators read these. */
children: ReactNode
}
/** One-line description of what the component does. */
export function MyComponent({ children }: MyComponentProps) {
const theme = useTheme()
// ...
}
// @ts-nocheck at top ONLY when using <box>, <text>, <span>"@/registry/gridland/lib/theme", use textStyle() for styling@/registry/gridland/{ui,lib,hooks}/* alias form for every intra-package import; shadcn's CLI rewrites these to the user's components.json aliases at install timetheme.* tokens or accept color propimport { useInteractive, FocusScope } from "@gridland/utils"
const { isFocused, isSelected, focusId, focusRef, onKey } = useInteractive({
id,
disabled,
shortcuts: [{ key: "enter", label: "select" }],
})
// Attach focusRef to root element
<box ref={focusRef}>...</box>
// Wrap nested interactive content
<FocusScope trap selectable autoFocus>{children}</FocusScope>
// Handle keys while selected (fires only when isSelected)
onKey((e) => {
if (e.name === "return") submit()
})
disabled alone excludes from navigation — do NOT also set tabIndex: -1useInteractive inside FocusScope auto-binds to that scope (pass scopeId={null} for global scope)focusId with an inner interactive child should call useInteractive({ id }) without shortcuts and without onKey — the internal dispatch is a no-op so the inner component's shortcuts surviveimport { useKeyboardContext } from "../provider/provider"
export interface MyComponentProps {
useKeyboard?: (handler: (event: any) => void) => void
}
const useKeyboard = useKeyboardContext(useKeyboardProp)
useKeyboard?.((event) => { /* handle keys */ })
In packages/ui/components/index.ts:
export { MyComponent } from "./<component-name>/<component-name>"
export type { MyComponentProps } from "./<component-name>/<component-name>"
Both runtime export AND type export required.
packages/demo/demos/<component-name>.tsx — export a named app component (e.g., export function MyComponentApp())packages/demo/demos/index.tsx (import, re-export, and add to demos array)packages/docs/content/docs/components/<component-name>.mdxpackages/docs/components/demos/<component-name>-demo.tsx that imports from @demos/<component-name>Interactive components need interactive demos with useState + useKeyboard.
/review to validate focus coverage and export conventions/sync-context to update packages/ui/CLAUDE.md with the new component