ワンクリックで
create-db-component
Creates a new DB UX Design System component with Mitosis source, SCSS, typed model, and Playwright tests.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Creates a new DB UX Design System component with Mitosis source, SCSS, typed model, and Playwright tests.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
Modifies an existing DB UX Design System Mitosis component (add variants, update props, change styles).
Implements production-ready UI using DB UX Design System v3 components, tokens, and icons with a discovery-first approach.
Migrates legacy DB UI v2 code (cmp-*, elm-*, rea-* classes, <db-*> Web Components, db-color-* tokens) to DB UX Design System v3.
Runs, analyzes, and fixes Playwright and accessibility tests for a specific DB UX component.
SOC 職業分類に基づく
| name | create-db-component |
| description | Creates a new DB UX Design System component with Mitosis source, SCSS, typed model, and Playwright tests. |
| triggers | ["create a new component","add component","generate component","new db component"] |
| inputs | [{"name":"component_slug","type":"string","required":true,"description":"Component directory name in kebab-case (e.g. 'navigation-item', 'tooltip')"},{"name":"component_name","type":"string","required":false,"description":"Optional PascalCase symbol name (e.g. 'NavigationItem'). If omitted, derive it from component_slug."},{"name":"figma_file_key","type":"string","required":true,"description":"Figma file key (e.g. from https://www.figma.com/file/<fileKey>/...)."},{"name":"figma_node_id","type":"string","required":true,"description":"Figma node ID of the target component/frame (e.g. 1234-5678)."},{"name":"figma_url","type":"string","required":false,"description":"Optional full Figma URL. Use only as fallback when file key and node ID are not provided separately."}] |
| requires | [{"context":"context/architecture.md","autoLoad":true}] |
| tools | ["db-ux/list_components","db-ux/get_component_props","db-ux/get_component_details","db-ux/get_example_code","db-ux/get_design_tokens","db-ux/list_design_token_categories","db-ux/list_icons","db-ux/docs_search","figma/get_figma_data","figma/download_figma_images"] |
| outputs | ["packages/components/src/components/{component_slug}/"] |
| on_error | {"max_retries":3,"actions":[{"log":"Review the shell output (lint/test/build) and fix reported errors before retrying."},{"fallback":"If errors persist after 3 retries, report to user with full error output."}]} |
Throughout this skill:
{component_slug} = kebab-case directory/file name (e.g. navigation-item){component_name} = PascalCase symbol name derived from {component_slug} (e.g. navigation-item -> NavigationItem)DB{component_name} = full component class name (e.g. DBNavigationItem).db-{component_slug} = CSS class (e.g. .db-navigation-item)context/architecture.md IS in context.@db-ux/mcp-server) IS connected.component_slug IS provided by user. Derive component_name from component_slug unless explicitly provided.figma_file_key and figma_node_id ARE provided by user.figma_url only as a fallback source to extract them. If still unresolved: ABORT.list_components to verify the component does NOT already exist.figma_file_key and figma_node_id provided by the user as the primary source of truth.figma_url as fallback.
https://www.figma.com/file/<fileKey>/...?node-id=<nodeId>get_figma_data with fileKey and nodeId to retrieve the component frame and its design data.get_figma_data response — extract them from the returned data structure.@db-ux/mcp-server node package)list_components. ABORT if component already exists.list_design_token_categories to discover available categories. Then call get_design_tokens with the categories identified in Phase 0.1 (spacing, sizing, colors, radius).variables.$db-*) or CSS custom property (var(--db-*)) as fallback:
--db-spacing-fixed-* token.--db-*-bg-* token.--db-*-on-bg-* token.--db-*-border-* token.--db-sizing-* token.--db-border-radius-* token.list_icons if the component uses icons in Figma.get_component_details on a structurally similar existing component (same interaction family: form-control, container, navigation or feedback). If no similar component exists, state that explicitly and skip.Create packages/components/src/components/{component_slug}/{component_slug}.spec.tsx:
import AxeBuilder from '@axe-core/playwright';
import { expect, test } from '@playwright/experimental-ct-react';
import { DB{component_name} } from './index';
// @ts-ignore - vue can only find it with .ts as file ending
import { DEFAULT_VIEWPORT } from '../../shared/constants.ts';
const comp: any = <DB{component_name}>Content</DB{component_name}>;
const testComponent = () => {
test('should contain text', async ({ mount }) => {
const component = await mount(comp);
await expect(component).toContainText('Content');
});
test('should match screenshot', async ({ mount }) => {
const component = await mount(comp);
await expect(component).toHaveScreenshot();
});
// AI-REPLACE: Inline the real variant list from Figma Phase 0.1 here.
// AI-NOTE: Do NOT import from model.ts — it does not exist yet in RED phase.
for (const variant of ['variant1', 'variant2' /* AI-REPLACE: use real Figma variants */]) {
const variantComp: any = <DB{component_name} variant={variant}>Content</DB{component_name}>;
test(`should contain text for variant ${variant}`, async ({ mount }) => {
const component = await mount(variantComp);
await expect(component).toContainText('Content');
});
test(`should match screenshot for variant ${variant}`, async ({ mount }) => {
const component = await mount(variantComp);
await expect(component).toHaveScreenshot();
});
}
};
const testA11y = () => {
test('should have same aria-snapshot', async ({ mount }, testInfo) => {
const component = await mount(comp);
const snapshot = await component.ariaSnapshot();
expect(snapshot).toMatchSnapshot(`${testInfo.testId}.yaml`);
});
test('should not have any A11y issues', async ({ page, mount }) => {
await mount(comp);
const accessibilityScanResults = await new AxeBuilder({ page })
.include('.db-{component_slug}')
.analyze();
expect(accessibilityScanResults.violations).toEqual([]);
});
};
test.describe('DB{component_name}', () => {
test.use({ viewport: DEFAULT_VIEWPORT });
testComponent();
testA11y();
});
After writing the spec, build the project, generate outputs, and run the component tests from output/react:
pnpm run build && pnpm run build-outputs &&
cd output/react && pnpm run test:components
The RED phase is only complete if:
If the spec has syntax errors, fix them first and re-run until you get clean "missing implementation" failures.
model.tsimport { GlobalProps, GlobalState } from '../../shared/model';
export const {component_name}VariantList = [/* AI-REPLACE: insert real variants from Figma Phase 0.1 */] as const;
export type {component_name}VariantType = (typeof {component_name}VariantList)[number];
export type DB{component_name}DefaultProps = {
/** AI-REPLACE: Add real JSDoc description for this prop */
variant?: {component_name}VariantType;
};
export type DB{component_name}Props = DB{component_name}DefaultProps & GlobalProps;
export type DB{component_name}DefaultState = {};
export type DB{component_name}State = DB{component_name}DefaultState & GlobalState;
Rules:
DefaultProps & GlobalProps.{component_slug}.lite.tsximport { useDefaultProps, useMetadata, useRef, useStore } from '@builder.io/mitosis';
import { cls } from '../../utils';
import type { DB{component_name}Props, DB{component_name}State } from './model';
useMetadata({});
useDefaultProps<DB{component_name}Props>({});
export default function DB{component_name}(props: DB{component_name}Props) {
const _ref = useRef<HTMLElement | any>(null);
const state = useStore<DB{component_name}State>({});
return (
<div
ref={_ref}
id={props.id ?? props.propOverrides?.id}
class={cls('db-{component_slug}', props.className)}
data-variant={props.variant}
>
{props.children}
</div>
);
}
Rules:
.lite.tsx components.id={props.id ?? props.propOverrides?.id}.{component_slug}.scss@use "@db-ux/core-foundations/build/styles/variables";
.db-{component_slug} {
// AI-REPLACE: Add real styles using mapped tokens from Phase 0.2
padding: variables.$db-spacing-fixed-sm;
block-size: variables.$db-sizing-md;
&[data-variant="..."] { /* AI-REPLACE: use real variant name */
// AI-REPLACE: variant-specific styles using tokens
}
}
Rules: Line 1 = @use. Root = .db-{component_slug}. NO hardcoded values. Keep nesting shallow — prefer extracting shared/internal styles over deeply nested selectors.
index.tsexport { default as DB{component_name} } from './{component_slug}';
Do NOT re-export from ./model. Do NOT use .lite suffix.
Angular.md, HTML.md, React.md, Vue.md, Migration.md.default.example.lite.tsx, variant.example.lite.tsx, _{component_slug}.arg.types.ts.import { PatternhubProps } from '../../../shared/model';
import CardWrapperShowcase from '../../../shared/showcase/card-wrapper.showcase.lite';
import ContainerWrapperShowcase from '../../../shared/showcase/container-wrapper.showcase.lite';
import LinkWrapperShowcase from '../../../shared/showcase/link-wrapper.showcase.lite';
import VariantExample from '../examples/variant.example.lite';
export default function {component_name}Showcase(props: PatternhubProps) {
return (
<ContainerWrapperShowcase title="DB{component_name}" isPatternhub={props.isPatternhub}>
<LinkWrapperShowcase exampleName="Variant">
<CardWrapperShowcase>
<VariantExample />
</CardWrapperShowcase>
</LinkWrapperShowcase>
</ContainerWrapperShowcase>
);
}
pnpm run test. ALL MUST PASS.pnpm run build. MUST SUCCEED.pnpm run build-showcases. MUST SUCCEED.pnpm run build-storybooks. MUST SUCCEED.Create agent/{component_slug}.agent.lite.tsx with usage examples.
Build framework outputs:
pnpm run build-outputs
This MUST succeed.
Create changeset:
bash pnpm changeset
Select @db-ux/core-components (only if the changes also affect styling: SCSS/CSS) and all JavaScript framework output packages (@db-ux/ngx-core-components, @db-ux/react-core-components, @db-ux/wc-core-components, @db-ux/v-core-components). Bump: minor.
As a changeset message, describe why we made a change and what changes to the developers. In most cases, we don't need to describe what we have changed internally, as the users are most curious about what changes for them.
model.ts with typed props{component_slug}.lite.tsx with Mitosis patterns{component_slug}.scss with tokens only{component_slug}.spec.tsx with screenshots + a11yindex.ts (no .lite, no model re-export)docs/, examples/, showcase/, agent/ completepnpm run build passespnpm run test passespnpm run build-outputs passes| Thought | Response |
|---|---|
| "Figma link is missing" | STOP. ABORT. Demand URL. |
| "I'll write tests later" | STOP. Step 1 is FIRST. |
| "I don't need model.ts" | STOP. Every component gets typed props. |
| "A quick hardcoded color" | STOP. Use SCSS variables (variables.$db-*). |
| "I'll skip MCP query" | STOP. Step 0 is mandatory. |
| "Icon is probably 'close'" | STOP. Call list_icons. |
| "Edit React output directly" | STOP. .lite.tsx ONLY. |
| "I'll use px" | STOP. Use tokens. |
| "Export from .lite" | STOP. No .lite suffix. |
| "Skip changeset" | STOP. Governance requires it. |
| "build-outputs is optional" | STOP. It is mandatory. |