Adding Components
Learn how to add new components to siddcn.
Adding Components
Learn how to contribute new components to the siddcn library.
Component Structure
Each component in siddcn follows a consistent structure:
src/components/
└── category-name/
└── index.tsx # Component implementationsCreating a New Component
1. Define the Component
Create your component in the appropriate category folder:
import React from 'react';
import { Box, Text } from 'ink';
export interface MyButtonProps {
label: string;
variant?: 'primary' | 'secondary' | 'outline';
onPress?: () => void;
}
export function MyButton({
label,
variant = 'primary',
onPress
}: MyButtonProps) {
const colors = {
primary: { bg: 'cyan', fg: 'black' },
secondary: { bg: 'gray', fg: 'white' },
outline: { bg: undefined, fg: 'cyan' },
};
const style = colors[variant];
return (
<Box
borderStyle={variant === 'outline' ? 'single' : undefined}
borderColor={variant === 'outline' ? 'cyan' : undefined}
>
<Text
backgroundColor={style.bg}
color={style.fg}
bold
>
{` ${label} `}
</Text>
</Box>
);
}2. Register in the Registry
Add your component to the component registry:
import { MyButton } from './buttons';
export const componentRegistry = {
buttons: {
'my-button': {
name: 'My Button',
component: MyButton,
description: 'A customizable button component',
props: {
label: 'Click me',
variant: 'primary',
},
},
// ... other components
},
};3. Add Preview Data
Create sample data for the component preview:
export const myButtonPreviewData = {
default: {
label: 'Primary Button',
variant: 'primary' as const,
},
secondary: {
label: 'Secondary Button',
variant: 'secondary' as const,
},
outline: {
label: 'Outline Button',
variant: 'outline' as const,
},
};Best Practices
Theme Compatibility
Always use theme colors for consistency:
import { useTheme } from 'siddcn';
function MyComponent() {
const theme = useTheme();
return (
<Text color={theme.primary}>
Themed text
</Text>
);
}Keyboard Accessibility
Support keyboard navigation where appropriate:
import { useInput } from 'ink';
function MyComponent({ onSelect }) {
useInput((input, key) => {
if (key.return || input === 'l') {
onSelect?.();
}
});
// ...
}TypeScript
Export proper TypeScript interfaces:
export interface MyComponentProps {
/** The label to display */
label: string;
/** Optional callback when pressed */
onPress?: () => void;
}Testing
Test your component in the CLI:
# Run the dev server
pnpm dev
# In another terminal, test the CLI
pnpm siddcnNavigate to your component and verify it renders correctly with all variants.