plugins/fpkit-developer/skills/fpkit-developer/SKILL.md
Guides development of applications built with @fpkit/acss React components. Use when composing custom components from fpkit primitives, validating or customizing CSS variables, extending fpkit components with new behavior, or ensuring WCAG accessibility compliance in fpkit-based UIs. Not for developing the @fpkit/acss library itself — use fpkit-component-builder for that.
npx skillsauth add shawn-sandy/acss-plugins fpkit-developerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
A Claude Code skill for building applications with @fpkit/acss components.
This skill helps developers:
This skill is for: Developers using @fpkit/acss in their applications
Not for: Developing the @fpkit/acss library itself (use fpkit-component-builder for that)
When a user requests a new component or feature, follow this workflow:
Understand what the user needs:
Ask clarifying questions if the requirements are unclear.
Review the @fpkit/acss component catalog or Storybook:
Available components:
aria-disabled pattern, focus management, performance optimized)Decision tree:
1. CHECK: Does fpkit have the exact component?
✓ YES → Use it directly, customize with CSS variables
(Skip to Step 6: Accessibility)
✗ NO → Continue to next check
2. CHECK: Can it be built by composing 2+ fpkit components?
✓ YES → Proceed to Step 3 (Composition)
✗ NO → Continue to next check
3. CHECK: Can an existing fpkit component be extended/wrapped?
✓ YES → Proceed to Step 4 (Extension)
✗ NO → Continue to next check
4. BUILD: Component requires custom implementation
→ Proceed to Step 5 (Custom Implementation)
Create a new component file that imports and combines fpkit components:
// components/StatusButton.tsx
import { Button, Badge } from '@fpkit/acss'
export interface StatusButtonProps extends React.ComponentProps<typeof Button> {
status: 'active' | 'inactive' | 'pending'
}
export const StatusButton = ({ status, children, ...props }: StatusButtonProps) => {
return (
<Button {...props}>
{children}
<Badge variant={status}>{status}</Badge>
</Button>
)
}
Guidelines:
...props to preserve all fpkit functionalityReference: See references/composition.md for patterns and examples
Wrap an fpkit component to add custom behavior:
// components/LoadingButton.tsx
import { Button, type ButtonProps } from '@fpkit/acss'
import { useState } from 'react'
export interface LoadingButtonProps extends ButtonProps {
loading?: boolean
onClickAsync?: (e: React.MouseEvent) => Promise<void>
}
export const LoadingButton = ({
loading,
onClickAsync,
children,
...props
}: LoadingButtonProps) => {
const [isLoading, setIsLoading] = useState(false)
const handleClick = async (e: React.MouseEvent) => {
if (onClickAsync) {
setIsLoading(true)
try {
await onClickAsync(e)
} finally {
setIsLoading(false)
}
}
}
return (
<Button
{...props}
aria-disabled={isLoading || props.disabled}
onClick={handleClick}
>
{isLoading ? 'Loading...' : children}
</Button>
)
}
Guidelines:
aria-disabled pattern for better keyboard accessibility.is-disabled stylingIf the component is truly custom and can't use fpkit:
Follow fpkit patterns:
Create styles (if needed):
// components/CustomComponent.scss
.custom-component {
padding: var(--custom-padding, 1rem);
border-radius: var(--custom-radius, 0.375rem);
background: var(--custom-bg, white);
// Use rem units only!
margin-bottom: 1rem; // NOT 16px
gap: 0.5rem; // NOT 8px
}
Validate CSS variables (for custom styles):
Prerequisites: Python 3.x required. Verify with python --version.
python scripts/validate_css_vars.py components/
Reference: See references/css-variables.md for naming conventions
Check accessibility compliance:
<button>, <nav>, etc.)aria-label, aria-describedby, etc.)Test:
npm install --save-dev jest-axe @types/jest-axe)Reference: See references/accessibility.md for patterns
Feedback loop: If any checklist item fails, return to Step 3, 4, or 5 to fix the issue before continuing. Do not proceed to Step 7 until all required checklist items pass.
When creating a reusable component for a team:
Create a Storybook story:
// components/StatusButton.stories.tsx
import type { Meta, StoryObj } from '@storybook/react'
import { StatusButton } from './StatusButton'
const meta = {
title: 'Components/StatusButton',
component: StatusButton,
tags: ['autodocs'],
} satisfies Meta<typeof StatusButton>
export default meta
type Story = StoryObj<typeof meta>
export const Active: Story = {
args: {
status: 'active',
children: 'Server Status',
},
}
export const Inactive: Story = {
args: {
status: 'inactive',
children: 'Server Status',
},
}
Read references/composition.md when composing components. Covers:
Common questions → Reference sections:
Read references/css-variables.md for customization guidance. Covers:
--component-property)Common questions → Reference sections:
Read references/accessibility.md for WCAG compliance guidance. Covers:
Common questions → Reference sections:
Read references/architecture.md to understand fpkit design patterns. Covers:
as prop for semantic flexibilityCommon questions → Reference sections:
as prop?" → Polymorphic ComponentsRead references/testing.md for component testing strategies. Covers:
Common questions → Reference sections:
Read references/storybook.md for documentation strategies. Covers:
Common questions → Reference sections:
Validate custom CSS variables against fpkit conventions:
# Validate a file
python scripts/validate_css_vars.py components/Button.scss
# Validate a directory
python scripts/validate_css_vars.py styles/
# Validate current directory
python scripts/validate_css_vars.py
What it checks:
--{component}-{property}See the inline code examples in Steps 3 and 4 above for the core composition and extension patterns (StatusButton, LoadingButton).
For advanced production-ready implementations, see references/composition.md:
aria-disabled for better keyboard accessibilityonClick for events - Captures keyboard, mouse, touch, and assistive techaria-disabled pattern allows this!onPointerDown alone - It doesn't fire for keyboard usersdisabled handling - Trust fpkit's aria-disabled pattern<button> inside <a>as prop instead of wrappingrel="noopener" to external links - fpkit Link does this automatically<button>, not <div>)role, tabIndex, and keyboard handlers if neededinterface MyProps extends ButtonPropsimport { Button, type ButtonProps } from '@fpkit/acss'<Button {...props}>This skill is designed for applications using @fpkit/acss >= v0.1.x. For version-specific documentation, check the npm package documentation in node_modules/@fpkit/acss/docs/.
development
Internal orchestrator for /kit-create, /kit-list, /kit-sync, /kit-update and Form/HTML/Style-Tune modes. Per-component generation lives in component-<name> skills; do not auto-trigger for component requests.
data-ai
Use when the user asks to generate, create, or scaffold a Table — accessible data table with caption, scope headers, responsive scroll wrapper, and sortable column support.
tools
Use when the user asks to generate, create, or scaffold a Popover — accessible tooltip/popover using the Popover API with focus trap, aria-expanded, and light-dismiss.
tools
Use when the user asks to generate, create, or scaffold a Nav — accessible navigation landmark with aria-label, current-page link marking, and horizontal/vertical layout.