بنقرة واحدة
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