|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +**Sleek Chat** is a Foundry VTT module (v12+) that provides a minimalist dice rolling toolbar and chat interface. It appears only when the sidebar is collapsed, reducing UI clutter for story-focused games. |
| 8 | + |
| 9 | +**Critical**: This module has NO build process. There is no package.json, webpack, or any bundler. All JavaScript is native ES6 modules, CSS is plain CSS (no preprocessing), and templates are Handlebars files loaded at runtime. |
| 10 | + |
| 11 | +## Development Workflow |
| 12 | + |
| 13 | +### Making Changes |
| 14 | +1. Edit files directly in the module folder |
| 15 | +2. Refresh Foundry VTT in browser to see changes |
| 16 | +3. No compilation, build, or preprocessing step needed |
| 17 | +4. CSS is automatically loaded - do NOT try to compile or build it |
| 18 | + |
| 19 | +### Testing |
| 20 | +- Enable "Debug Mode" in module settings for console logging |
| 21 | +- Use the `debugLog()` function from `scripts/sleek-chat-debug.js` for conditional logging |
| 22 | +- Test with sidebar collapsed and expanded states |
| 23 | +- Test with both GM and player accounts for permission-based features |
| 24 | + |
| 25 | +### File Editing |
| 26 | +- ALWAYS use `foundry.applications.handlebars.loadTemplates()` (namespaced), NOT the deprecated global `loadTemplates()` |
| 27 | +- Preserve exact indentation when editing (mix of tabs/spaces exists) |
| 28 | +- Templates use Handlebars syntax (.hbs files) |
| 29 | + |
| 30 | +## Architecture |
| 31 | + |
| 32 | +### Module Loading Order (from module.json) |
| 33 | +1. **scripts/settings.js** - Registers all game settings in `Hooks.once('init')` |
| 34 | +2. **scripts/sleek-chat-debug.js** - Debug utility (`debugLog()` function) |
| 35 | +3. **scripts/main.js** - Main UI logic, dice rolling, visibility control |
| 36 | +4. **scripts/recent-message-display.js** - Message history and navigation |
| 37 | + |
| 38 | +### Key Design Patterns |
| 39 | + |
| 40 | +#### Hook-Based Architecture |
| 41 | +The module uses Foundry's Hook system extensively: |
| 42 | +- `Hooks.once('init')` - Register settings before game loads |
| 43 | +- `Hooks.on('ready')` - Initialize UI after everything loads |
| 44 | +- `Hooks.on('renderChatLog')` - Inject custom toolbar into chat |
| 45 | +- `Hooks.on('createChatMessage')` - React to new messages |
| 46 | +- `Hooks.on('updateSetting')` - Respond to setting changes |
| 47 | + |
| 48 | +#### Settings System |
| 49 | +Two types of settings: |
| 50 | +- **Client-side** (`scope: "client"`): Personal preferences (opacity, colors, debug mode) |
| 51 | +- **World-level** (`scope: "world"`): GM-controlled (hide buttons, dice ranges) |
| 52 | + |
| 53 | +Settings use `onChange` callbacks for immediate UI updates. Some require reload dialogs for complex changes. |
| 54 | + |
| 55 | +#### Static Class Pattern |
| 56 | +`RecentMessageDisplay` is a static class with methods: |
| 57 | +- `init()` - Initialize message display system |
| 58 | +- `addMessageToHistory(messageId)` - Track new messages |
| 59 | +- `updateRecentMessage(messageId)` - Display specific message |
| 60 | +- `navigateMessages(direction)` - Navigate through last 50 messages |
| 61 | +- `validateMessageIds()` - Clean up deleted message IDs |
| 62 | + |
| 63 | +### Core Features Implementation |
| 64 | + |
| 65 | +#### Conditional UI Display |
| 66 | +Uses MutationObserver to watch sidebar collapse state: |
| 67 | +```javascript |
| 68 | +const observer = new MutationObserver(() => updateVisibility()); |
| 69 | +observer.observe(document.getElementById('sidebar'), { |
| 70 | + attributes: true, |
| 71 | + attributeFilter: ['class'] |
| 72 | +}); |
| 73 | +``` |
| 74 | + |
| 75 | +#### Dice Rolling |
| 76 | +- Click to add dice, right-click to remove |
| 77 | +- Builds roll formula (e.g., "2d20kh + 3" for advantage) |
| 78 | +- Creates `new Roll(formula).evaluate()` |
| 79 | +- Integrates with Dice So Nice if available |
| 80 | +- Results color-coded based on configurable ranges per die type |
| 81 | + |
| 82 | +#### Message Display |
| 83 | +- Shows most recent chat message in compact view |
| 84 | +- Fade-out effects with configurable timing/opacity |
| 85 | +- Hover restores full opacity |
| 86 | +- Navigation through message history |
| 87 | +- Message validation handles deleted messages |
| 88 | + |
| 89 | +#### Navigation Button Hiding |
| 90 | +- Dynamically hide sidebar tabs based on settings |
| 91 | +- "Apply only to Players" option for GM |
| 92 | +- "Hide Always" hides even when sidebar expanded |
| 93 | +- Creates dynamic settings for new tabs from other modules |
| 94 | + |
| 95 | +### Data Flow Examples |
| 96 | + |
| 97 | +**Settings Change Flow:** |
| 98 | +``` |
| 99 | +game.settings.set() |
| 100 | + → onChange callback |
| 101 | + → Immediate UI update OR reload dialog |
| 102 | +``` |
| 103 | + |
| 104 | +**Dice Roll Flow:** |
| 105 | +``` |
| 106 | +User clicks "Roll!" |
| 107 | + → Build formula from selected dice/modifiers |
| 108 | + → new Roll(formula).evaluate() |
| 109 | + → Dice So Nice animation (if available) |
| 110 | + → Render templates/common-roll.hbs |
| 111 | + → ChatMessage.create() with roll data |
| 112 | +``` |
| 113 | + |
| 114 | +**Message Creation Flow:** |
| 115 | +``` |
| 116 | +ChatMessage.create() |
| 117 | + → Hook: 'createChatMessage' |
| 118 | + → RecentMessageDisplay.addMessageToHistory() |
| 119 | + → RecentMessageDisplay.updateRecentMessage() |
| 120 | + → DOM updated + fade timer started |
| 121 | + → playPingSound() if enabled |
| 122 | +``` |
| 123 | + |
| 124 | +## File Structure |
| 125 | + |
| 126 | +``` |
| 127 | +sleek-chat/ |
| 128 | +├── scripts/ |
| 129 | +│ ├── main.js # Main logic: dice rolling, UI visibility, nav hiding |
| 130 | +│ ├── settings.js # All game.settings.register() calls |
| 131 | +│ ├── recent-message-display.js # Message history management |
| 132 | +│ └── sleek-chat-debug.js # debugLog() utility |
| 133 | +├── styles/ |
| 134 | +│ └── styles.css # All styles (no preprocessing!) |
| 135 | +├── templates/ |
| 136 | +│ ├── dice-toolbar.hbs # Main UI toolbar |
| 137 | +│ ├── common-roll.hbs # Dice roll result display |
| 138 | +│ └── custom-chat-card.hbs # Custom chat card |
| 139 | +├── ui/ # SVG dice icons and sound file |
| 140 | +├── module.json # Foundry module manifest |
| 141 | +└── sleek-chat.zip # Distribution package |
| 142 | +``` |
| 143 | + |
| 144 | +## Key Functions and Exports |
| 145 | + |
| 146 | +### scripts/main.js |
| 147 | +- `applyChatBaseContainerOpacity()` - Set container opacity with hover effects |
| 148 | +- `applySeeOnlyChat(seeOnlyChat)` - Toggle chat-only mode (hide dice) |
| 149 | +- `applyNavButtonHiding()` - Show/hide navigation buttons |
| 150 | +- `applyDiceColorFilter(colorName)` - Apply CSS filter for dice colors |
| 151 | +- `parseDiceRanges()` - Parse fumble/normal/critical ranges from settings |
| 152 | + |
| 153 | +### scripts/recent-message-display.js |
| 154 | +- `RecentMessageDisplay.init()` - Initialize on ready |
| 155 | +- `RecentMessageDisplay.addMessageToHistory(messageId)` - Track new message |
| 156 | +- `RecentMessageDisplay.updateRecentMessage(messageId)` - Display message |
| 157 | +- `RecentMessageDisplay.navigateMessages(direction)` - Navigate history |
| 158 | +- `RecentMessageDisplay.validateMessageIds()` - Clean deleted messages |
| 159 | +- `applyMessageFadeOutSettings()` - Apply fade settings |
| 160 | + |
| 161 | +### scripts/sleek-chat-debug.js |
| 162 | +- `debugLog(...args)` - Conditional console.log based on debug mode setting |
| 163 | + |
| 164 | +## Important Implementation Notes |
| 165 | + |
| 166 | +### Templates |
| 167 | +- Use `renderTemplate('modules/sleek-chat/templates/file.hbs', data)` |
| 168 | +- Template data objects must match Handlebars variable names |
| 169 | +- Templates are loaded via `foundry.applications.handlebars.loadTemplates()` in ready hook |
| 170 | + |
| 171 | +### CSS |
| 172 | +- Single file: `styles/styles.css` |
| 173 | +- Uses CSS custom properties: `--dice-filter` for color changes |
| 174 | +- Applied via module.json, no manual loading needed |
| 175 | +- Auto-loaded by Foundry, no build step |
| 176 | + |
| 177 | +### DOM Manipulation |
| 178 | +- Heavy use of jQuery for animations: `$().fadeTo()`, `$().addClass()` |
| 179 | +- Direct DOM queries: `document.querySelector()`, `document.querySelectorAll()` |
| 180 | +- Event delegation for dynamic content |
| 181 | + |
| 182 | +### Foundry API Integration |
| 183 | +- `game.settings.get/set()` - All configuration |
| 184 | +- `game.user.isGM` - Permission checks |
| 185 | +- `game.messages` - Message history access |
| 186 | +- `ChatMessage.create()` - Create chat messages |
| 187 | +- `Roll` - Dice rolling engine |
| 188 | +- `ui.sidebar` - Sidebar state |
| 189 | + |
| 190 | +### Version Management |
| 191 | +- Current version: 1.4.1 |
| 192 | +- Update version in module.json when releasing |
| 193 | +- Update CHANGELOG.md with changes |
| 194 | +- Recreate sleek-chat.zip with updated files |
| 195 | +- Commit and push to GitHub main branch |
| 196 | + |
| 197 | +## Common Patterns |
| 198 | + |
| 199 | +### Adding a New Setting |
| 200 | +1. Register in `scripts/settings.js` within `Hooks.once('init')` |
| 201 | +2. Use appropriate scope: `"client"` or `"world"` |
| 202 | +3. Add `onChange` callback for immediate updates if needed |
| 203 | +4. Import and call update functions from main.js if needed |
| 204 | + |
| 205 | +### Adding a New Die Type |
| 206 | +1. Add SVG icons to `ui/` folder (normal and filled versions) |
| 207 | +2. Update `templates/dice-toolbar.hbs` with new die button |
| 208 | +3. Add setting in `scripts/settings.js` for result ranges |
| 209 | +4. Update `parseDiceRanges()` in `scripts/main.js` |
| 210 | + |
| 211 | +### Modifying UI Templates |
| 212 | +1. Edit the .hbs file in `templates/` |
| 213 | +2. Ensure data object passed to `renderTemplate()` has matching properties |
| 214 | +3. Refresh Foundry to see changes |
| 215 | +4. No compilation needed |
| 216 | + |
| 217 | +## Integration Points |
| 218 | + |
| 219 | +### With Foundry Core |
| 220 | +- Settings API for all configuration persistence |
| 221 | +- Hook system for event-driven architecture |
| 222 | +- ChatMessage API for message creation |
| 223 | +- Roll API for dice mechanics |
| 224 | +- Sidebar API for UI state |
| 225 | + |
| 226 | +### With Other Modules |
| 227 | +- **Dice So Nice**: Optional 3D dice visualization integration |
| 228 | +- **Dynamic sidebar modules**: Auto-creates hide settings for new navigation tabs |
| 229 | +- Extensible for system-specific chat buttons |
| 230 | + |
| 231 | +## Debugging |
| 232 | + |
| 233 | +- Enable "Debug Mode" in module settings |
| 234 | +- All debug output uses `debugLog()` function |
| 235 | +- Check browser console for log messages |
| 236 | +- Debug messages indicate: settings changes, opacity adjustments, message navigation, button visibility logic |
| 237 | + |
| 238 | +## Known Limitations |
| 239 | + |
| 240 | +- Some game systems with custom chat buttons may have interaction issues |
| 241 | +- Users should report issues at: https://github.com/mordachai/sleek-chat/issues |
0 commit comments