基于 SOC 职业分类
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/hpsgd/turtlestack --skill component-from-spec命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
Review staged or recent changes — native Claude Code review for mechanics, layered with team conventions and the team verdict contract
Perform a security-focused audit of code changes or a specific area of the codebase.
Propose a change to a marketplace repo based on learned patterns — new rules, updated skills, evolved regex patterns. Infers which upstream marketplace the learning belongs to, confirms with the user, then creates a branch, applies changes, shows diff for review, and raises a PR on approval. Use when patterns have enough evidence to share upstream.
| name | component-from-spec |
| description | Implement a React component from a design specification or component-spec output. |
| argument-hint | [component spec, description, or reference to spec file] |
| user-invocable | true |
| allowed-tools | Read, Write, Edit, Bash, Glob, Grep |
| paths | ["**/*.tsx","**/*.jsx"] |
Implement a React component from the specification at $ARGUMENTS.
Before writing any code, examine existing components to match project conventions:
Scan for patterns:
# Find existing components to match conventions
ls -la src/components/ 2>/dev/null || ls -la app/components/ 2>/dev/null
Identify and match:
index.ts)?Read the spec completely: Props, variants, states, responsive behaviour, accessibility requirements, interactions, animations
Rules:
Before writing JSX, design the component API:
Props interface (TypeScript MANDATORY):
export interface ComponentNameProps {
/** Required props first, grouped by purpose */
title: string;
items: Item[];
/** Variant prop for visual modes */
variant?: 'default' | 'compact' | 'expanded';
/** State props */
isLoading?: boolean;
isDisabled?: boolean;
/** Event handlers — use standard naming */
onSelect?: (item: Item) => void;
onDismiss?: () => void;
/** Composition props */
className?: string;
children?: React.ReactNode;
}
Rules:
{ComponentName}Props and exportedvariant, not type or modeis/has/can prefix: isLoading, hasError, canEditon prefix: onSelect, onChange, onDismissclassName for composition (merged via clsx)Write tests BEFORE implementation. Test behaviour, not implementation details.
Test file: component-name.test.ts (co-located)
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ComponentName } from './component-name';
describe('ComponentName', () => {
it('renders the title', () => {
render(<ComponentName title="Hello" items={[]} />);
expect(screen.getByText('Hello')).toBeInTheDocument();
});
it('calls onSelect when an item is clicked', async () => {
const onSelect = vi.fn();
const items = [{ id: '1', label: 'Item 1' }];
render(<ComponentName title="Test" items={items} onSelect={onSelect} />);
await userEvent.click(screen.());
(onSelect).(items[]);
});
(, {
();
(screen.()).();
});
(, {
();
(screen.()).();
});
});
Rules:
userEvent (not fireEvent) for user interactionsComponent structure:
import { clsx } from 'clsx';
export interface ComponentNameProps {
// ... (from Step 2)
}
export function ComponentName({
title,
items,
variant = 'default',
isLoading = false,
isDisabled = false,
onSelect,
className,
}: ComponentNameProps) {
// 1. Hooks first (useState, useEffect, custom hooks)
// 2. Derived state (computed from props/state, no useMemo unless measured)
// 3. Event handlers
// 4. Early returns for special states
if (isLoading) {
return <ComponentNameSkeleton />;
}
if (items.length === 0) {
return <ComponentNameEmpty />;
}
// 5. Main render
return (
<div className={clsx('base-classes', variantClasses[variant], className)}>
{/* ... */}
</div>
);
}
Rules:
function ComponentName), not arrow functions, for top-level componentsuseMemo unless profiling shows a performance problemuseCallback only when passing to memoised children or in dependency arraysclsx for conditional class composition — never string interpolation| State | Must handle | Implementation |
|---|---|---|
| Default | Always | Normal rendering with data |
| Loading | If data is async | Skeleton or spinner with role="status" and aria-label |
| Error | If data can fail | Error message with retry action |
| Empty | If collection can be empty | Meaningful empty state, not just blank space |
| Disabled | If interactive | Reduced opacity, no hover effects, aria-disabled="true" |
| Hover/Focus | If interactive | Visual feedback via CSS :hover/:focus-visible |
| Active/Selected | If selectable | aria-selected="true", visual indicator |
| Overflow | If content varies | Text truncation, scrollable containers, responsive layout |
Rules:
| Requirement | Implementation | Test |
|---|---|---|
| Semantic HTML | Use <button>, <nav>, <main>, <article>, not <div onClick> | Query by role in tests |
| ARIA roles | role="status" for loading, role="alert" for errors, role="list" for lists | Verify with getByRole |
| Keyboard navigation | Tab order, Enter/Space for activation, Escape for dismissal, Arrow keys for lists | Test with userEvent.keyboard |
| Focus management | Focus trap in modals, focus restoration on close, visible focus ring | Test focus element after interaction |
| Screen reader text | aria-label for icon buttons, aria-live for dynamic content | Verify ARIA attributes |
| Colour contrast | Minimum 4.5:1 for text, 3:1 for large text | Manual check against design |
| Motion | prefers-reduced-motion media query for animations | CSS media query |
Rules:
<button>, not a <div> or <span><a>, not a <button>alt text (empty string alt="" for decorative images)aria-label if visually hidden)focus-visible, not focus)| Breakpoint | Approach |
|---|---|
| Mobile-first | Default styles are mobile. Add complexity with sm:, md:, lg: |
| Touch targets | Minimum 44x44px for interactive elements on mobile |
| Layout shifts | No content jumps on load — reserve space with skeletons |
| Text overflow | Truncate with ellipsis or expand/collapse, never horizontal scroll |
| Images | next/image with sizes attribute, responsive source sets |
Tailwind breakpoint usage:
<div className="flex flex-col gap-2 md:flex-row md:gap-4 lg:gap-6">
<div className="w-full md:w-1/3 lg:w-1/4">Sidebar</div>
<div className="w-full md:w-2/3 lg:w-3/4">Content</div>
</div>
Rules:
w-[347px]) unless the design system requires exact pixels<div> for everything. Use semantic HTML elementsuseEffect is for side effects, not data transformationtext-[13.5px] is a code smell. Use standard scale valuesDeliver:
component-name.tsx) with typed props, all states, accessibilitycomponent-name.test.ts) co-located, testing behaviour not implementationindex.ts)/ui-designer:component-spec — this skill consumes the component spec as input. Write the spec first, then build the component from it.