Skip to content

Commit 3457a86

Browse files
authored
Add .claude/skills and cleanup CLAUDE.md (#1975)
1 parent 36c6c61 commit 3457a86

File tree

7 files changed

+805
-375
lines changed

7 files changed

+805
-375
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
---
2+
name: commit-progress
3+
description: Commit a logical unit of work with a descriptive message. Invoke after completing a meaningful chunk (component created, store wired, tests passing) to maintain small, reviewable commits.
4+
user_invocable: true
5+
---
6+
7+
# Commit Progress
8+
9+
Create a focused commit for the work just completed. This skill produces small,
10+
reviewable commits — one per logical unit of work, not one per file edit.
11+
12+
## When to Invoke
13+
14+
- After a component is created and rendering correctly
15+
- After store fields/actions are wired and working
16+
- After tests are written and passing
17+
- After a bug fix is verified
18+
- After a refactor is complete
19+
- When switching context to a different sub-task
20+
21+
## When NOT to Invoke
22+
23+
- In the middle of incomplete work (half-written component, broken imports)
24+
- After only formatting or trivial changes
25+
- If there are no meaningful changes to commit
26+
27+
## Procedure
28+
29+
### 1. Assess what changed
30+
31+
Run in parallel:
32+
- `git status` — see all modified/untracked files
33+
- `git diff --stat` — summary of changes
34+
- `git diff` — full diff of unstaged changes
35+
- `git log --oneline -5` — recent commits for style reference
36+
37+
### 2. Determine if changes form a coherent unit
38+
39+
A good commit contains changes that serve **one purpose**. If the diff contains
40+
unrelated changes, stage only the related files.
41+
42+
Examples of coherent units:
43+
- "Add SignStepContent component and store fields"
44+
- "Wire simulate isNextDisabled logic"
45+
- "Add tracking events for sign step"
46+
- "Fix auth entry XDR parsing edge case"
47+
48+
### 3. Stage and commit
49+
50+
Stage specific files (prefer explicit paths over `git add .`):
51+
52+
```bash
53+
git add src/app/(sidebar)/transaction/build/components/SignStepContent.tsx
54+
git add src/store/createTransactionFlowStore.ts
55+
```
56+
57+
Write commit message following the project's conventions:
58+
- **Style**: Informal, descriptive, present tense
59+
- **Prefix**: Use a context-aware prefix reflecting the feature/page (e.g., `[Smart Contract Page]`, `[View XDR]`, `[New Tx]`, `[Endpoints]`)
60+
- **Format**: Short summary line; no body needed for small changes
61+
- **Examples from this repo**:
62+
- `[New Tx] Add Simulate Step`
63+
- `[New Tx] Wire sign step into page layout`
64+
- `[Smart Contract Page] Add contract deployment UI`
65+
- `[View XDR] Fix XDR decoding for auth entries`
66+
- `fix auth entry parsing for empty credentials`
67+
68+
```bash
69+
git commit -m "$(cat <<'EOF'
70+
[New Tx] Add SignStepContent component
71+
72+
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
73+
EOF
74+
)"
75+
```
76+
77+
### 4. Verify
78+
79+
Run `git status` to confirm clean state or expected remaining changes.
80+
81+
## Guidelines
82+
83+
- **Never force push** or amend without explicit user request
84+
- **Never commit** `.env`, credentials, or sensitive files
85+
- **Never skip hooks** (`--no-verify`) unless user explicitly requests it
86+
- **Prefer small commits** — if in doubt, commit more often
87+
- **Pre-commit hook runs lint-staged** (ESLint auto-fix on staged files) — if it
88+
fails, fix the lint error and create a NEW commit (don't amend)
89+
- **Pre-push hook runs** TypeScript check + all tests — these only run on push,
90+
not commit
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
---
2+
name: component-with-design-system
3+
description: Guide for building React components using @stellar/design-system and project SCSS conventions. Invoke when creating new components or reviewing component code.
4+
---
5+
6+
# Component with Design System
7+
8+
## Before Building Anything Custom
9+
10+
Check if `@stellar/design-system` already has the component:
11+
https://github.com/stellar/stellar-design-system
12+
13+
## Commonly Used Design System Components
14+
15+
### Layout & Structure
16+
- `<Box gap="sm|md|lg">` — flex container with gap
17+
- `<Card>` — bordered card container
18+
- `<PageCard heading="...">` — card with heading, optional `rightElement`
19+
- `<PageHeader heading="..." as="h1|h2">` — page/section title
20+
21+
### Form Inputs
22+
- `<Input>` — text input with label, error, note props
23+
- `<Select>` — dropdown with `fieldSize` prop
24+
- `<Textarea>` — multiline text
25+
- `<RadioButton id label fieldSize="sm|md|lg">` — radio input, extends native
26+
`<input>` attributes (`name`, `value`, `checked`, `onChange`, etc.)
27+
28+
### Actions
29+
- `<Button variant="primary|secondary|tertiary|destructive">` — with optional
30+
`icon`, `isLoading`, `disabled` props
31+
- `<CopyText textToCopy={value}>` — text with copy button
32+
33+
### Feedback
34+
- `<Alert variant="primary|success|warning|error" title="...">` — alert banner
35+
with optional children for body
36+
- `<Text size="xs|sm|md|lg" as="span|p|div">` — typography
37+
- `<Link>` — styled link
38+
- `<Icon.[Name] />` — icon from icon set
39+
40+
### Display
41+
- `<Badge variant="primary|secondary|tertiary|success|warning|error" size="sm|md|lg">`
42+
— status label with optional `icon`, `iconPosition`, `isOutlined`, `isSquare`,
43+
`isStatus` props
44+
- `<Text size="xs|sm|md|lg" as="span|p|div">` — typography for displaying text
45+
46+
## Component File Structure
47+
48+
### With styles (preferred for non-trivial components)
49+
50+
```
51+
src/components/ComponentName/
52+
├── index.tsx
53+
└── styles.scss
54+
```
55+
56+
### Without styles (simple components)
57+
58+
```
59+
src/components/ComponentName.tsx
60+
```
61+
62+
### Page-specific components
63+
64+
```
65+
src/app/(sidebar)/[feature]/components/ComponentName.tsx
66+
```
67+
68+
## Component Template
69+
70+
```typescript
71+
"use client";
72+
73+
import { useState } from "react";
74+
import { Button, Input, Card } from "@stellar/design-system";
75+
76+
import "./styles.scss";
77+
78+
interface ComponentNameProps {
79+
/** Description of prop */
80+
propName: string;
81+
}
82+
83+
/**
84+
* Brief description of what this component does
85+
*
86+
* @example
87+
* <ComponentName propName="value" />
88+
*/
89+
export const ComponentName = ({ propName }: ComponentNameProps) => {
90+
return (
91+
<div className="ComponentName">
92+
<div className="ComponentName__header">
93+
{/* ... */}
94+
</div>
95+
<div className="ComponentName__content">
96+
{/* ... */}
97+
</div>
98+
</div>
99+
);
100+
};
101+
```
102+
103+
## SCSS Template
104+
105+
```scss
106+
.ComponentName {
107+
// Root styles
108+
109+
&__header {
110+
display: flex;
111+
align-items: center;
112+
justify-content: space-between;
113+
}
114+
115+
&__content {
116+
display: flex;
117+
flex-direction: column;
118+
gap: pxToRem(16px);
119+
}
120+
121+
&__footer {
122+
display: flex;
123+
gap: pxToRem(8px);
124+
}
125+
}
126+
```
127+
128+
## Conventions
129+
130+
### Do
131+
- Use design system components for all standard UI elements
132+
- Use SCSS with BEM-ish class naming (`ComponentName__element--modifier`)
133+
- Use `pxToRem()` for spacing values in SCSS
134+
- Use SDS CSS custom properties for colors/fonts/gaps: `var(--sds-clr-gray-06)`,
135+
`var(--sds-ff-monospace)`, `var(--sds-gap-md)`
136+
- Use `data-*` attributes for state-driven styling instead of modifier classes:
137+
`data-is-active`, `data-is-visible`, `data-is-selected`, `data-is-clickable`
138+
- Use `data-testid` with dashes for test selectors (`data-testid="sign-button"`)
139+
- Add JSDoc comments with `@example` for exported components
140+
- Co-locate page-specific components with their page
141+
- Import shared SCSS utilities: `@use "../../styles/utils.scss" as *;`
142+
143+
### Don't
144+
- Use inline `style={}` attributes — always use SCSS classes
145+
- Create custom buttons, inputs, or alerts when design system has equivalents
146+
- Use arbitrary hex colors — use SDS CSS custom properties (`--sds-clr-*`)
147+
- Put styles in the component file — always separate into `.scss`
148+
- Use `className` string concatenation — use template literals or classnames lib
149+
- Use conditional CSS classes for state — prefer `data-*` attributes
150+
151+
## Design System Props Patterns
152+
153+
### Input with validation
154+
155+
```typescript
156+
<Input
157+
id="source-account"
158+
fieldSize="md"
159+
label="Source Account"
160+
value={sourceAccount}
161+
onChange={(e) => setSourceAccount(e.target.value)}
162+
error={getPublicKeyError(sourceAccount)}
163+
note="The account that originates the transaction"
164+
/>
165+
```
166+
167+
### Button with loading state
168+
169+
```typescript
170+
<Button
171+
variant="primary"
172+
size="md"
173+
isLoading={isSubmitting}
174+
disabled={!isValid}
175+
onClick={handleSubmit}
176+
>
177+
Submit Transaction
178+
</Button>
179+
```
180+
181+
### Alert with details
182+
183+
```typescript
184+
<Alert variant="warning" title="Auth entries require signing">
185+
This transaction has {authCount} authorization entries that must be
186+
signed before the transaction envelope can be signed.
187+
</Alert>
188+
```
189+
190+
### RadioButton group
191+
192+
```typescript
193+
<RadioButton
194+
id="network-testnet"
195+
name="network"
196+
label="Testnet"
197+
fieldSize="md"
198+
checked={network === "testnet"}
199+
onChange={() => setNetwork("testnet")}
200+
/>
201+
<RadioButton
202+
id="network-mainnet"
203+
name="network"
204+
label="Mainnet"
205+
fieldSize="md"
206+
checked={network === "mainnet"}
207+
onChange={() => setNetwork("mainnet")}
208+
/>
209+
```
210+
211+
### Badge with icon
212+
213+
```typescript
214+
<Badge variant="success" size="sm" icon={<Icon.CheckCircle />} iconPosition="right">
215+
Verified
216+
</Badge>
217+
218+
<Badge variant="error">Failed</Badge>
219+
220+
<Badge variant="secondary" size="sm">
221+
{itemCount} items
222+
</Badge>
223+
```
224+
225+
### PageCard with action
226+
227+
```typescript
228+
<PageCard
229+
heading="Transaction Parameters"
230+
rightElement={
231+
<Button variant="tertiary" onClick={handleClear}>
232+
Clear all
233+
</Button>
234+
}
235+
>
236+
{/* Card content */}
237+
</PageCard>
238+
```
239+
240+
## Data Attribute Pattern for State-Driven Styling
241+
242+
Prefer `data-*` attributes over CSS modifier classes for dynamic state:
243+
244+
```typescript
245+
// Component
246+
<div
247+
className="TransactionStepper__step"
248+
data-is-active={isActive || undefined}
249+
data-is-completed={isCompleted || undefined}
250+
data-is-clickable={isClickable || undefined}
251+
onClick={isClickable ? () => onStepClick(step) : undefined}
252+
>
253+
```
254+
255+
```scss
256+
// SCSS — target with attribute selectors
257+
.TransactionStepper__step {
258+
opacity: 0.5;
259+
260+
&[data-is-active="true"] {
261+
opacity: 1;
262+
font-weight: var(--sds-fw-medium);
263+
}
264+
265+
&[data-is-clickable="true"] {
266+
cursor: pointer;
267+
}
268+
269+
&[data-is-completed="true"] {
270+
opacity: 0.8;
271+
}
272+
}
273+
```
274+
275+
Pass `undefined` (not `false`) to omit the attribute from the DOM entirely.

0 commit comments

Comments
 (0)