diff --git a/.claude/README.md b/.claude/README.md new file mode 100644 index 00000000..5562c444 --- /dev/null +++ b/.claude/README.md @@ -0,0 +1,92 @@ +# Claude Code Configuration + +This directory contains team-wide Claude Code settings for the Remix project. + +## Files + +### settings.json (Team Settings) + +Team-wide configuration that applies to all developers: + +```json +{ + "hooks": { + "sessionStart": "scripts/setup.sh" + }, + "model": { + "default": "sonnet" + }, + "shell": { + "defaultShell": "/bin/bash" + } +} +``` + +**What it does:** +- Runs `scripts/setup.sh` automatically when Claude Code session starts +- Sets Sonnet as the default model +- Uses bash as the default shell + +### settings.local.json (Personal Settings - Git Ignored) + +You can create a `settings.local.json` file for personal overrides. This file is git-ignored and will not be committed. + +**Example personal settings:** +```json +{ + "model": { + "default": "opus" + } +} +``` + +## Settings Precedence + +Settings are loaded in this order (lowest to highest priority): + +1. User global settings (`~/.claude/settings.json`) +2. Project team settings (`.claude/settings.json`) ← This file +3. Project local settings (`.claude/settings.local.json`) ← Your personal overrides +4. Command-line arguments +5. Enterprise policies + +Higher priority settings override lower priority ones. + +## Session Start Hook + +The `sessionStart` hook runs `scripts/setup.sh` which: + +1. Verifies AGENTS.md and CLAUDE.md exist +2. Configures PATH for pub-cache and FVM +3. Installs/verifies FVM (Flutter Version Management) +4. Installs Flutter via FVM (reads `.fvmrc`) +5. Installs/verifies Melos (monorepo workspace manager) +6. Installs/verifies DCM (Dart Code Metrics) +7. Bootstraps workspace (`melos bootstrap`) +8. Verifies setup with Flutter doctor + +This ensures Claude Code has a fully configured environment ready to work with the Remix project. + +## Personal Overrides + +To create personal settings that won't be committed: + +```bash +# Create personal settings +cat > .claude/settings.local.json << 'EOF' +{ + "model": { + "default": "opus" + } +} +EOF +``` + +This is already git-ignored, so it won't be committed to the repository. + +## Documentation + +For more information about Claude Code configuration: +- **Claude Code Docs:** https://docs.claude.com/en/docs/claude-code +- **Settings Reference:** https://docs.claude.com/en/docs/claude-code/settings.md +- **Hooks Documentation:** https://docs.claude.com/en/docs/claude-code/hooks.md diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 00000000..944e8d88 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,11 @@ +{ + "hooks": { + "sessionStart": "scripts/setup.sh" + }, + "model": { + "default": "sonnet" + }, + "shell": { + "defaultShell": "/bin/bash" + } +} diff --git a/.gitignore b/.gitignore index fa28c457..cc888f65 100644 --- a/.gitignore +++ b/.gitignore @@ -281,3 +281,7 @@ app.*.symbols # Analysis and development artifacts component_patterns_analysis.md /.cursor + +# Claude Code (personal overrides) +CLAUDE.local.md +.claude/settings.local.json diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..813d1a0b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,545 @@ +# Remix Architecture & Context + +> **Last Updated:** 2025-11-05 +> **Version:** 0.1.0-beta.1 +> **Repository:** https://github.com/btwld/remix + +## Executive Summary + +Remix is a comprehensive Flutter component library that combines headless UI behavior with Mix's powerful styling system. It provides complete freedom to build and customize components that match any design system perfectly. + +**Tech Stack:** +- **Language:** Dart 3.9.0+ +- **Framework:** Flutter 3.35.0+ +- **Styling:** Mix 2.0.0-dev.5 (composable styling system) +- **Behavior:** Naked UI 0.2.0-beta.7 (headless UI components) +- **Design System:** Fortal (Radix-inspired, included) +- **Monorepo:** Melos 7.1.1+ (workspace management) +- **Flutter Version:** Managed by FVM (stable channel) + +**Key Features:** +- Ready-to-use components with built-in behavior and accessibility +- Complete styling freedom via Mix's chainable API +- State-aware styling (hover, focus, press, custom states) +- Smooth animations integrated with styling +- Production-ready Fortal design system +- Fully customizable and themeable + +## Monorepo Structure + +``` +remix/ +├── .fvmrc # FVM configuration (Flutter stable) +├── pubspec.yaml # Workspace configuration +├── docs/ # Documentation +├── packages/ +│ ├── remix/ # Core library package +│ │ ├── lib/ +│ │ │ ├── src/ +│ │ │ │ ├── components/ # All UI components +│ │ │ │ ├── fortal/ # Fortal design system +│ │ │ │ └── ... +│ │ │ └── remix.dart # Main export +│ │ ├── test/ # Component tests +│ │ └── pubspec.yaml # Package metadata +│ ├── demo/ # Demo application +│ ├── example/ # Example code snippets +│ └── playground/ # Development playground +└── README.md +``` + +### Package Dependencies + +**Workspace packages:** +- `remix` - Core component library (main package) +- `demo` - Interactive demo application +- `example` - Code examples and usage patterns +- `playground` - Development and testing environment + +**Core dependencies:** +- `mix: ^2.0.0-dev.5` - Styling and theming system +- `naked_ui: ^0.2.0-beta.7` - Headless UI primitives +- `prism: ^2.0.0` - Token system +- `prism_flutter: ^2.0.0` - Flutter integration for tokens + +## Key Architectural Patterns + +### 1. Component Structure + +All Remix components follow this pattern: + +```dart +// Component Widget +class RemixButton extends StatelessWidget { + final String label; + final VoidCallback? onPressed; + final RemixButtonStyle? style; + + const RemixButton({ + required this.label, + this.onPressed, + this.style, + }); + + @override + Widget build(BuildContext context) { + // Uses Naked UI for behavior + Mix for styling + } +} + +// Style Class (Chainable API) +class RemixButtonStyle { + RemixButtonStyle paddingX(double value) { /* ... */ } + RemixButtonStyle paddingY(double value) { /* ... */ } + RemixButtonStyle color(Color value) { /* ... */ } + RemixButtonStyle onHovered(RemixButtonStyle style) { /* ... */ } + RemixButtonStyle animate(AnimationConfig config) { /* ... */ } + + // Callable - style can be used as a function + RemixButton call({required String label, VoidCallback? onPressed}) { + return RemixButton(label: label, onPressed: onPressed, style: this); + } +} +``` + +### 2. Styling System (Mix Integration) + +Remix uses Mix for all styling. Mix provides: + +**Chainable API:** +```dart +final style = RemixButtonStyle() + .paddingX(16) + .paddingY(10) + .color(Colors.blue) + .borderRadiusAll(const Radius.circular(8)); +``` + +**State-based styling:** +```dart +final style = RemixButtonStyle() + .color(Colors.blue) + .onHovered(RemixButtonStyle().color(Colors.blue.shade700)) + .onPressed(RemixButtonStyle().wrapScale(x: 0.95, y: 0.95)) + .onDisabled(RemixButtonStyle().opacity(0.5)); +``` + +**Animation integration:** +```dart +final style = RemixButtonStyle() + .color(Colors.blue) + .animate(AnimationConfig.spring(300.ms)) + .onHovered(RemixButtonStyle().color(Colors.blue.shade700)); +``` + +**Style composition:** +```dart +final base = RemixButtonStyle().paddingX(16).paddingY(10); +final primary = base.color(Colors.blue); +final destructive = base.color(Colors.red); +``` + +### 3. Behavior System (Naked UI Integration) + +Naked UI provides headless component behavior: +- Interaction handling (click, hover, focus, press) +- Keyboard navigation +- Accessibility (ARIA attributes, screen reader support) +- State management + +Remix wraps Naked UI components and adds Mix styling on top. + +### 4. Token System (Prism) + +Fortal design system uses Prism for design tokens: + +```dart +// Token access +FortalTokens.accent9() // Accent color step 9 +FortalTokens.space4() // Spacing step 4 +FortalTokens.radius3() // Border radius step 3 +FortalTokens.accentContrast() // Contrast color for accent +``` + +**Token categories:** +- Colors: 12-step scales (powered by Radix Colors) +- Spacing: 9-step scale +- Border Radius: 6-step scale +- Shadows: 6-level system +- Typography: 9-size type scale +- Border Widths: Consistent strokes + +### 5. Fortal Design System + +Fortal provides production-ready styles: + +**Usage:** +```dart +// Wrap app with Fortal scope +createFortalScope( + child: RemixButton( + style: FortalButtonStyle.solid(), + label: 'Click me', + onPressed: () {}, + ), +); + +// Available variants +FortalButtonStyle.solid() // Primary solid button +FortalButtonStyle.soft() // Soft background button +FortalButtonStyle.outline() // Outlined button +FortalButtonStyle.ghost() // Ghost/text button +``` + +**Customization:** +```dart +final custom = FortalButtonStyle.solid() + .borderRadiusAll(Radius.circular(8)) + .paddingX(32) + .onHovered(RemixButtonStyle().wrapScale(x: 1.05, y: 1.05)); +``` + +## Available Components + +### Interactive Elements +- `RemixButton` - Clickable actions (lib/src/components/button/) +- `RemixIconButton` - Icon-based actions +- `RemixSwitch` - Toggle controls +- `RemixCheckbox` - Multiple selection +- `RemixRadio` - Single selection from group +- `RemixSlider` - Continuous value selection + +### Input Components +- `RemixTextField` - Text input with validation +- `RemixSelect` - Dropdown with keyboard navigation + +### Display Components +- `RemixAvatar` - User avatars and images +- `RemixBadge` - Status indicators and labels +- `RemixCard` - Content containers +- `RemixDivider` - Visual separators +- `RemixProgress` - Progress indicators +- `RemixSpinner` - Loading states + +### Layout & Navigation +- `RemixTabs` - Tabbed navigation +- `RemixAccordion` - Collapsible sections +- `RemixMenu` - Context menus and dropdowns + +### Overlays +- `RemixDialog` - Modal dialogs +- `RemixTooltip` - Contextual help +- `RemixCallout` - Highlighted information blocks + +## Development Workflows + +### Setup Environment + +```bash +# Install FVM (if not installed) +dart pub global activate fvm + +# Install Flutter via FVM +fvm install + +# Install Melos +dart pub global activate melos + +# Bootstrap workspace (installs all dependencies) +melos bootstrap + +# Verify setup +flutter doctor +``` + +### Common Commands + +```bash +# Bootstrap workspace +melos bootstrap + +# Run all tests +melos run test:flutter + +# Run CI tests +melos run ci + +# Run specific package tests +cd packages/remix && flutter test + +# Run demo app +cd packages/demo && flutter run + +# Run playground +cd packages/playground && flutter run + +# Clean all packages +melos clean + +# Get dependencies for all packages +melos exec -- flutter pub get +``` + +### Adding a New Component + +1. Create component directory: `packages/remix/lib/src/components/my_component/` +2. Create widget file: `my_component.dart` +3. Create style file: `my_component_style.dart` +4. Export from main: Add to `packages/remix/lib/remix.dart` +5. Add tests: `packages/remix/test/my_component_test.dart` +6. Add to demo: Update `packages/demo/lib/` with example +7. Run tests: `melos run test:flutter` + +### Code Style & Standards + +- Follow [Effective Dart](https://dart.dev/guides/language/effective-dart) guidelines +- Use `dart format` for formatting +- Use `dart analyze` for linting +- Component files use lowercase_with_underscores.dart naming +- Class names use PascalCase +- Private members use _leadingUnderscore + +## Current State & Recent Changes + +**Version:** 0.1.0-beta.1 + +**Recent commits:** +- `cd0446f` - chore: reorganize repo +- `847ef3d` - test: Add test for interactive widgets +- `399f06a` - Change banner image to new URL +- `ca43cac` - Change banner image source to hosted URL +- `0ae60d8` - refactor: Remove unused internal utilities and specs + +**Active development areas:** +- Component library expansion +- Fortal design system refinement +- Documentation improvements +- Demo application enhancements +- Testing coverage + +## Testing Strategy + +**Unit tests:** +- Component behavior tests +- Style composition tests +- Token system tests +- State management tests + +**Integration tests:** +- Component interaction tests +- Accessibility tests +- Animation tests + +**Widget tests:** +- Visual regression tests +- Layout tests +- Responsive behavior tests + +**Run tests:** +```bash +# All tests +melos run test:flutter + +# Specific package +cd packages/remix && flutter test + +# Specific test file +flutter test test/components/button_test.dart + +# With coverage +flutter test --coverage +``` + +## Common Patterns + +### Creating a Styled Component + +```dart +// 1. Define style class +class MyComponentStyle { + MyComponentStyle padding(double value) { /* ... */ } + MyComponentStyle color(Color value) { /* ... */ } + MyComponentStyle onHovered(MyComponentStyle style) { /* ... */ } +} + +// 2. Create component widget +class MyComponent extends StatelessWidget { + final MyComponentStyle? style; + + const MyComponent({this.style}); + + @override + Widget build(BuildContext context) { + // Apply style using Mix + } +} + +// 3. Export from library +// Add to lib/remix.dart +``` + +### Using Fortal Tokens + +```dart +final style = RemixButtonStyle() + .color(FortalTokens.accent9()) + .paddingAll(FortalTokens.space4()) + .borderRadiusAll(FortalTokens.radius3()) + .label(TextStyler().color(FortalTokens.accentContrast())); +``` + +### Composing Styles + +```dart +// Base style +final base = RemixButtonStyle() + .paddingX(16) + .paddingY(10) + .borderRadiusAll(const Radius.circular(8)); + +// Variants +final primary = base.color(Colors.blue); +final secondary = base.color(Colors.gray); +final destructive = base.color(Colors.red); + +// With states +final interactive = primary + .onHovered(RemixButtonStyle().color(Colors.blue.shade700)) + .onPressed(RemixButtonStyle().wrapScale(x: 0.95, y: 0.95)); + +// With animation +final animated = interactive + .animate(AnimationConfig.spring(300.ms)); +``` + +### Using Callable Styles + +```dart +// Style as function +final button = RemixButtonStyle() + .paddingX(16) + .paddingY(10) + .color(Colors.blue); + +// Call style to create widget +button( + label: 'Click me', + onPressed: () {}, +); // Returns RemixButton widget +``` + +## Critical Files + +### Core Library +- `packages/remix/lib/remix.dart` - Main library export +- `packages/remix/lib/src/components/` - All component implementations +- `packages/remix/lib/src/fortal/` - Fortal design system +- `packages/remix/pubspec.yaml` - Package configuration + +### Workspace +- `pubspec.yaml` - Workspace configuration and Melos scripts +- `.fvmrc` - Flutter version configuration +- `README.md` - Project documentation + +### Development +- `packages/demo/` - Demo application +- `packages/example/` - Usage examples +- `packages/playground/` - Development playground + +## Integration Points + +### Mix Integration +Remix heavily depends on Mix for styling. Understanding Mix is crucial: +- Mix provides the styling API and attribute system +- Remix wraps Mix's styling in component-specific style classes +- Animation is handled by Mix's animation system +- See: https://github.com/btwld/mix + +### Naked UI Integration +Naked UI provides headless behavior: +- Keyboard navigation +- Focus management +- Accessibility features +- Interaction handling +- See: https://github.com/btwld/naked_ui + +### Prism Integration +Prism provides the token system: +- Design tokens (colors, spacing, etc.) +- Token resolution and inheritance +- Theme switching support + +## Performance Considerations + +- Mix uses efficient attribute system for styling +- Components rebuild only when necessary +- Animation performance optimized via Mix +- Token system uses efficient lookup +- Widget tree kept shallow where possible + +## Debugging Tips + +**Style not applying:** +- Check if component wrapped in Fortal scope (if using Fortal) +- Verify style method chaining returns new instance +- Check state conditions (hover requires pointer device) + +**Animation not working:** +- Ensure `.animate()` is called before state styles +- Check animation duration is reasonable (100-500ms typical) +- Verify Mix animation system is properly configured + +**Component not responding:** +- Check if `onPressed` or similar callback is provided +- Verify Naked UI behavior is properly configured +- Check accessibility properties + +**Build errors:** +- Run `melos bootstrap` to ensure dependencies +- Clean workspace: `melos clean && melos bootstrap` +- Check Flutter version: `fvm flutter --version` + +**Test failures:** +- Ensure workspace is bootstrapped +- Run `flutter pub get` in test package +- Check for async timing issues in widget tests + +## Additional Resources + +- **Repository:** https://github.com/btwld/remix +- **Documentation:** https://docs.page/btwld/remix +- **Mix Repository:** https://github.com/btwld/mix +- **Naked UI Repository:** https://github.com/btwld/naked_ui +- **Issue Tracker:** https://github.com/btwld/remix/issues + +## Quick Reference + +**Component usage:** +```dart +RemixButton( + label: 'Click me', + onPressed: () {}, + style: RemixButtonStyle() + .color(Colors.blue) + .paddingX(16) + .onHovered(RemixButtonStyle().color(Colors.blue.shade700)), +) +``` + +**Fortal usage:** +```dart +createFortalScope( + child: RemixButton( + style: FortalButtonStyle.solid(), + label: 'Fortal button', + onPressed: () {}, + ), +) +``` + +**Development commands:** +```bash +melos bootstrap # Setup workspace +melos run test:flutter # Run tests +cd packages/demo && flutter run # Run demo +``` diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..2bc907dd --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,40 @@ +# Remix - Claude Code Context + +> Project Context: @AGENTS.md + +This file imports AGENTS.md to provide full project context to Claude Code. + +## Quick Start for Claude + +When working on this project: + +1. **Use Melos commands** for all workspace operations +2. **Run tests** before committing: `melos run test:flutter` +3. **Follow component patterns** documented in AGENTS.md +4. **Use Fortal design system** when applicable +5. **Maintain style composition** patterns + +## Development Guidelines + +- Follow Effective Dart style guidelines +- All components must have corresponding tests +- Use Mix API for all styling +- Maintain accessibility features via Naked UI +- Update AGENTS.md when architecture changes + +## Common Tasks + +**Setup:** +```bash +melos bootstrap +``` + +**Testing:** +```bash +melos run test:flutter +``` + +**Run demo:** +```bash +cd packages/demo && flutter run +``` diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100755 index 00000000..af86aa4e --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,176 @@ +#!/bin/bash +# Remix Development Environment Setup Script +# Automatically runs when Claude Code session starts + +set -e # Exit immediately if a command exits with a non-zero status + +# Color codes for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Helper functions +print_step() { + echo -e "${BLUE}==>${NC} $1" +} + +print_success() { + echo -e "${GREEN}✓${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}⚠${NC} $1" +} + +print_error() { + echo -e "${RED}✗${NC} $1" +} + +# Detect environment +if [ "${CLAUDE_CODE_REMOTE:-false}" = "true" ]; then + IS_REMOTE=true + print_step "Running in Claude Code remote environment" +else + IS_REMOTE=false + print_step "Running in local environment" +fi + +echo "" +print_step "Setting up Remix development environment..." +echo "" + +# Step 1: Verify context files exist +print_step "[1/10] Verifying project context files..." +if [ -f "AGENTS.md" ] && [ -f "CLAUDE.md" ]; then + print_success "AGENTS.md and CLAUDE.md found" +else + print_error "Missing AGENTS.md or CLAUDE.md" + exit 1 +fi + +# Step 2: Configure PATH for Dart/Flutter tools +print_step "[2/10] Configuring PATH for Dart and Flutter tools..." + +# Add pub-cache to PATH if not already present +PUB_CACHE_BIN="$HOME/.pub-cache/bin" +if [[ ":$PATH:" != *":$PUB_CACHE_BIN:"* ]]; then + export PATH="$PUB_CACHE_BIN:$PATH" + print_success "Added $PUB_CACHE_BIN to PATH" +else + print_success "pub-cache already in PATH" +fi + +# Add FVM to PATH if not already present +FVM_BIN="$HOME/fvm/default/bin" +if [[ ":$PATH:" != *":$FVM_BIN:"* ]]; then + export PATH="$FVM_BIN:$PATH" + print_success "Added $FVM_BIN to PATH" +else + print_success "FVM already in PATH" +fi + +# Step 3: Install/verify FVM +print_step "[3/10] Installing/verifying FVM (Flutter Version Management)..." +if ! command -v fvm &> /dev/null; then + print_warning "FVM not found, installing..." + dart pub global activate fvm + print_success "FVM installed" +else + FVM_VERSION=$(fvm --version 2>&1 | head -n 1 || echo "unknown") + print_success "FVM already installed: $FVM_VERSION" +fi + +# Step 4: Install Flutter via FVM +print_step "[4/10] Installing Flutter via FVM..." +if [ -f ".fvmrc" ]; then + FLUTTER_CHANNEL=$(cat .fvmrc | grep -oP '(?<="flutter": ")[^"]*') + print_step "Installing Flutter from .fvmrc: $FLUTTER_CHANNEL" + + if ! fvm list | grep -q "$FLUTTER_CHANNEL"; then + print_warning "Flutter $FLUTTER_CHANNEL not installed, installing now..." + fvm install + print_success "Flutter $FLUTTER_CHANNEL installed" + else + print_success "Flutter $FLUTTER_CHANNEL already installed" + fi + + # Use the installed Flutter version + fvm use --force + print_success "Flutter $FLUTTER_CHANNEL activated" +else + print_warning ".fvmrc not found, skipping Flutter installation via FVM" +fi + +# Update PATH to include FVM Flutter +if [ -d ".fvm/flutter_sdk/bin" ]; then + export PATH="$(pwd)/.fvm/flutter_sdk/bin:$PATH" + print_success "FVM Flutter added to PATH" +fi + +# Step 5: Install/verify Melos +print_step "[5/10] Installing/verifying Melos (workspace manager)..." +if ! command -v melos &> /dev/null; then + print_warning "Melos not found, installing..." + dart pub global activate melos + print_success "Melos installed" +else + MELOS_VERSION=$(melos --version 2>&1 || echo "unknown") + print_success "Melos already installed: $MELOS_VERSION" +fi + +# Step 6: Install/verify DCM (Dart Code Metrics) +print_step "[6/10] Installing/verifying DCM (Dart Code Metrics)..." +if ! command -v dcm &> /dev/null; then + print_warning "DCM not found, installing..." + dart pub global activate dart_code_metrics_presets + print_success "DCM installed" +else + DCM_VERSION=$(dcm --version 2>&1 | head -n 1 || echo "unknown") + print_success "DCM already installed: $DCM_VERSION" +fi + +# Step 7: Bootstrap workspace +print_step "[7/10] Bootstrapping workspace with Melos..." +if melos bootstrap; then + print_success "Workspace bootstrapped successfully" +else + print_error "Failed to bootstrap workspace" + exit 1 +fi + +# Step 8: Verify Flutter doctor +print_step "[8/10] Verifying Flutter installation..." +echo "" +flutter doctor || print_warning "Flutter doctor reported issues (this may be normal)" +echo "" +print_success "Flutter doctor check completed" + +# Step 9: Show workspace info +print_step "[9/10] Workspace information..." +echo "" +if [ -f "pubspec.yaml" ]; then + echo "Workspace packages:" + grep -A 10 "workspace:" pubspec.yaml | grep " -" | sed 's/ - / • /' + echo "" +fi + +# Step 10: Summary +print_step "[10/10] Setup complete!" +echo "" +echo -e "${GREEN}✓ Environment ready for Remix development${NC}" +echo "" +echo "Quick commands:" +echo " • melos bootstrap - Bootstrap workspace" +echo " • melos run test:flutter - Run all tests" +echo " • melos run ci - Run CI tests" +echo " • cd packages/demo && flutter run - Run demo app" +echo " • flutter doctor - Check Flutter setup" +echo "" +echo "Documentation:" +echo " • AGENTS.md - Project architecture" +echo " • CLAUDE.md - Claude Code context" +echo " • README.md - Project overview" +echo "" +print_success "Happy coding! 🚀"