styled-components
styled-components 스타일링 규칙. styled() API, ThemeProvider, createGlobalStyle, *.styled.ts 파일 분리.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
styled-components 스타일링 규칙. styled() API, ThemeProvider, createGlobalStyle, *.styled.ts 파일 분리.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
세션 핸드오프. 컨텍스트가 차기 전에 중요 맥락을 progress.md에 문서화하고 새 세션 킥오프 프롬프트를 클립보드에 복사한다. "핸드오프", "세션 정리하고 넘기자", "컨텍스트 정리", "이어갈 준비" 등의 요청에 사용.
MD 파일 또는 텍스트로 작업을 정의하면, 분석 → 디자인 확인 → 구현 → 검증 → 커밋 → PR까지 전체 플로우를 수행한다. "이거 만들어줘", "기능 구현해줘", "작업 시작하자", "이 티켓 진행해줘" 등 코드 작업 착수 발화에 사용.
Claude + OpenAI Codex 협업 스킬. MCP 서버 설정 시에만 사용 가능.
code-forge 상태 대시보드. REFLECT flag, quality 이벤트, notepad/decisions, usage 집계를 한 번에. forge-glow 같은 외부 도구는 --json으로 파싱.
교차 모델 토론. Agent Teams / Codex CLI / self-debate 모드 선택. 설계 결정, 아키텍처 선택 시 활용. "어느 쪽이 나을까", "설계 비교해줘", "토론시켜줘", "교차 검증해줘" 등의 요청에 사용.
화면 단위 E2E 테스트 자동화. Figma/코드 기반 테스트 케이스 도출 → Playwright 코드 생성 → Forge Loop(에스컬레이션 기반 자율 실행). "E2E 돌려줘", "화면 테스트 만들어줘", "이 페이지 자동 테스트" 등의 요청에 사용.
| name | styled-components |
| description | styled-components 스타일링 규칙. styled() API, ThemeProvider, createGlobalStyle, *.styled.ts 파일 분리. |
styled-components의 styled() API로 스타일 컴포넌트를 작성한다*.styled.ts 파일로 분리한다// ✅ 좋은 예: 기본 HTML 요소 스타일링
import styled from 'styled-components';
const Container = styled.div`
padding: 16px;
margin-bottom: 8px;
border-radius: 8px;
background-color: ${({ theme }) => theme.colors.surface};
`;
const Title = styled.h2`
font-size: 1.25rem;
font-weight: 700;
color: ${({ theme }) => theme.colors.text.primary};
`;
const Button = styled.button<{ variant?: 'primary' | 'secondary' }>`
display: inline-flex;
align-items: center;
padding: 8px 16px;
border-radius: 6px;
border: none;
cursor: pointer;
font-weight: 500;
transition: background-color 0.2s;
background-color: ${({ variant, theme }) =>
variant === 'secondary' ? theme.colors.secondary : theme.colors.primary};
color: #ffffff;
&:hover {
opacity: 0.9;
}
&:disabled {
cursor: not-allowed;
opacity: 0.5;
}
`;
// ✅ 기존 컴포넌트 확장
import { Link } from 'react-router-dom';
const StyledLink = styled(Link)`
color: ${({ theme }) => theme.colors.primary};
text-decoration: none;
&:hover {
text-decoration: underline;
}
`;
interface StatusBadgeProps {
status: 'active' | 'inactive' | 'pending';
}
const StatusBadge = styled.span<StatusBadgeProps>`
display: inline-block;
padding: 2px 8px;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 500;
background-color: ${({ status, theme }) => {
switch (status) {
case 'active': return theme.colors.success.light;
case 'inactive': return theme.colors.error.light;
case 'pending': return theme.colors.warning.light;
}
}};
color: ${({ status, theme }) => {
switch (status) {
case 'active': return theme.colors.success.dark;
case 'inactive': return theme.colors.error.dark;
case 'pending': return theme.colors.warning.dark;
}
}};
`;
// components/OrderCard/index.tsx
function OrderCard({ order }: { order: Order }) {
return (
<Container>
<Title>{order.name}</Title>
<StatusBadge status={order.status}>{order.status}</StatusBadge>
</Container>
);
}
export default OrderCard;
// 파일 하단에 스타일 정의
const Container = styled.div`
padding: 16px;
border: 1px solid ${({ theme }) => theme.colors.border};
border-radius: 8px;
`;
const Title = styled.h3`
font-size: 1rem;
font-weight: 600;
`;
*.styled.ts 파일로 분리// components/OrderTable/styled.ts
import styled from 'styled-components';
export const TableContainer = styled.div`
width: 100%;
overflow-x: auto;
border-radius: 8px;
border: 1px solid ${({ theme }) => theme.colors.border};
`;
export const Table = styled.table`
width: 100%;
border-collapse: collapse;
`;
export const TableHeader = styled.thead`
background-color: ${({ theme }) => theme.colors.surfaceVariant};
`;
export const TableRow = styled.tr<{ isSelected?: boolean }>`
border-bottom: 1px solid ${({ theme }) => theme.colors.divider};
background-color: ${({ isSelected, theme }) =>
isSelected ? theme.colors.primary + '20' : 'transparent'};
&:hover {
background-color: ${({ theme }) => theme.colors.surfaceVariant};
}
`;
export const TableCell = styled.td`
padding: 12px 16px;
font-size: 0.875rem;
color: ${({ theme }) => theme.colors.text.primary};
`;
// components/OrderTable/index.tsx - named import 사용
import { TableContainer, Table, TableHeader, TableRow, TableCell } from './styled';
// styles/theme.ts
export const theme = {
colors: {
primary: '#1677ff',
secondary: '#6b7280',
surface: '#ffffff',
surfaceVariant: '#f9fafb',
border: '#e5e7eb',
divider: '#f3f4f6',
text: {
primary: '#111827',
secondary: '#6b7280',
disabled: '#9ca3af',
},
success: { light: '#dcfce7', dark: '#166534' },
error: { light: '#fee2e2', dark: '#991b1b' },
warning: { light: '#fef9c3', dark: '#854d0e' },
},
spacing: {
xs: '4px',
sm: '8px',
md: '16px',
lg: '24px',
xl: '32px',
},
borderRadius: {
sm: '4px',
md: '8px',
lg: '12px',
full: '9999px',
},
typography: {
fontFamily: '"Pretendard", system-ui, sans-serif',
},
};
export type Theme = typeof theme;
// styles/styled.d.ts
import 'styled-components';
import { Theme } from './theme';
declare module 'styled-components' {
export interface DefaultTheme extends Theme {}
}
// styles/GlobalStyle.ts
import { createGlobalStyle } from 'styled-components';
export const GlobalStyle = createGlobalStyle`
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 16px;
}
body {
font-family: ${({ theme }) => theme.typography.fontFamily};
color: ${({ theme }) => theme.colors.text.primary};
background-color: ${({ theme }) => theme.colors.surface};
-webkit-font-smoothing: antialiased;
}
a {
color: inherit;
text-decoration: none;
}
`;
// src/main.tsx
import { ThemeProvider } from 'styled-components';
import { GlobalStyle } from '@/styles/GlobalStyle';
import { theme } from '@/styles/theme';
function App() {
return (
<ThemeProvider theme={theme}>
<GlobalStyle />
<AppRoutes />
</ThemeProvider>
);
}
import styled, { css } from 'styled-components';
// ✅ 재사용 가능한 스타일 조각
const flexCenter = css`
display: flex;
align-items: center;
justify-content: center;
`;
const truncate = css`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
// 사용
const CenteredBox = styled.div`
${flexCenter}
padding: 16px;
`;
const EllipsisText = styled.p`
${truncate}
max-width: 200px;
`;
*.styled.ts 분리?ThemeProvider로 theme 전역 제공?styled.d.ts로 DefaultTheme 타입 확장?GlobalStyle로 전역 스타일 초기화?