ワンクリックで
add-section
Create a new HUD section (tab) with lifecycle, persistent state, and registry registration
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Create a new HUD section (tab) with lifecycle, persistent state, and registry registration
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Create a new card part within a section with factory/class pattern, Card wrapper, and proper cleanup
Add a new Jotai atom to the state system with type definitions, registry, and Store API access
Create a reusable UI component with factory pattern, theme compatibility, and proper cleanup
Scaffold a new toggleable feature with full structure, storage, API exposure, and bootstrap registration
Create a reactive global variable that derives from atoms with subscription support
Create a game UI injection that modifies existing game elements with proper cleanup
| name | add-section |
| description | Create a new HUD section (tab) with lifecycle, persistent state, and registry registration |
| aliases | ["new-section","create-section"] |
/add-section <SectionName>
Brief description (1 sentence):
What does this section display/manage?
What state needs to persist across sessions?
(Must be JSON-serializable: strings, numbers, booleans, arrays, plain objects)
Examples:
- Selected tab/filter
- Sort order
- Collapsed/expanded states
- User preferences
Does this section need game data?
A) Static data → MGData (plants, items, pets, etc.)
B) Real-time state → Globals (myInventory, myGarden, etc.)
C) Both
D) None
Does it display game sprites? → MGSprite.toCanvas()
Does it need existing UI components?
→ REUSE from src/ui/components/
[ ] ArcadeButton, GeminiIconButton → Buttons
[ ] Modal → Dialogs
[ ] ProgressBar → Progress
[ ] SegmentedControl → Tab-like selection
[ ] Tab → Tabs
[ ] SoundPicker → Audio
[ ] Other: ___
A) Simple - Single file section
B) Complex - Split into parts/ folder
- Label (displayed in tab bar): ___________
- Icon (emoji): ___________
src/ui/sections/<SectionName>/
├── index.ts # Public exports
├── section.ts # build() / destroy() lifecycle
├── state.ts # Persistent state (createSectionStore)
└── styles.css.ts # Scoped CSS (optional)
src/ui/sections/<SectionName>/
├── index.ts
├── section.ts # Assembles parts
├── state.ts
├── styles.css.ts
└── parts/
├── header.ts # Search, filters
├── content.ts # Main content
└── footer.ts # Actions
Read existing sections for templates: src/ui/sections/*/
| File | Purpose |
|---|---|
index.ts | Export <Name>Section and types only |
section.ts | build(container), destroy(), cleanups[] |
state.ts | createSectionStore() with stable ID tab-<name> |
styles.css.ts | CSS string with scoped classes |
parts/*.ts | Sub-components with own destroy() |
import { createSectionStore } from '../core/state';
export interface <Name>State {
// JSON-serializable only!
selectedTab: string;
sortOrder: 'asc' | 'desc';
}
const DEFAULT_STATE: <Name>State = {
selectedTab: 'all',
sortOrder: 'asc',
};
// ID must be stable forever (storage key)
export const state = createSectionStore<<Name>State>('tab-<name>', {
version: 1, // Increment when state shape changes
defaults: DEFAULT_STATE,
});
export interface SectionDefinition {
build(container: HTMLElement): void;
destroy(): void;
}
let root: HTMLElement | null = null;
const cleanups: (() => void)[] = [];
function build(container: HTMLElement): void {
if (root) return; // Prevent double-build
root = document.createElement('div');
root.className = '<name>-section';
// Inject styles
const style = document.createElement('style');
style.textContent = <name>Css;
root.appendChild(style);
// Subscribe to state
const unsub = state.subscribe((s) => { /* update UI */ });
cleanups.push(unsub);
// Add child components (reuse existing!)
// const button = createArcadeButton({ ... });
// cleanups.push(() => button.destroy());
container.appendChild(root);
}
function destroy(): void {
cleanups.forEach(fn => fn());
cleanups.length = 0;
root?.remove();
root = null;
}
export const <Name>Section: SectionDefinition = { build, destroy };
src/ui/sections/registry.tsimport { <Name>Section } from './<SectionName>';
export const sectionRegistry: Record<string, SectionConfig> = {
// ... existing
'tab-<name>': {
id: 'tab-<name>',
label: '<Label>',
icon: '<emoji>',
section: <Name>Section,
},
};
index.ts exports <Name>Section onlysection.ts has build() and destroy()state.ts uses createSectionStore() with stable IDtab-<name> format (stable forever)version incremented when state shape changesbuild() guards against double-build (if (root) return)destroy() cleans up ALL resourcesdestroy()destroy() called.section-name__element)root, not document.headMGData.get().subscribe() + cleanupMGSprite.toCanvas()src/ui/components/cleanups[]src/ui/sections/registry.tstab-<name>)For reference/templates:
Settings - User preferencesAutoFavoriteSettings - Feature configJournalChecker - Journal progressPets - Pet managementTrackers - Stats trackingAlerts - Notifications configDev - Developer toolsTest - Testing section.claude/rules/ui/sections.mdsrc/ui/sections/*/src/ui/sections/core/state.tssrc/ui/components/.claude/workflows/ui/section/split-section-into-parts.md