Frontend-core counterpart to QRun-IO/qqq#396 — adds the Collapsible TypeScript model and wires it into QTableSection and QWidgetMetaData so the frontend can read collapsible metadata from the backend.
New Collapsible class (isCollapsible, initiallyOpen) with constructor and clone() support
QTableSection gains an optional collapsible property, deserialized in the constructor and properly cloned
QWidgetMetaData gains the same optional collapsible property with constructor deserialization
Details
Collapsible (new file)
Simple model with two boolean fields: isCollapsible and initiallyOpen
Constructor hydrates from a plain object (matching the JSON shape from the backend's CollapsibleMetaData)
clone() via spread operator for immutable copy support
QTableSection
Optional collapsible?: Collapsible field added
Constructor conditionally instantiates Collapsible when present in the source object
clone() updated to deep-copy the collapsible property
QWidgetMetaData
Optional collapsible?: Collapsible field added
Constructor conditionally instantiates Collapsible when present in the source object
## Summary
Frontend-core counterpart to QRun-IO/qqq#396 — adds the **`Collapsible`** TypeScript model and wires it into `QTableSection` and `QWidgetMetaData` so the frontend can read collapsible metadata from the backend.
- New `Collapsible` class (`isCollapsible`, `initiallyOpen`) with constructor and `clone()` support
- `QTableSection` gains an optional `collapsible` property, deserialized in the constructor and properly cloned
- `QWidgetMetaData` gains the same optional `collapsible` property with constructor deserialization
## Details
### Collapsible (new file)
- Simple model with two boolean fields: `isCollapsible` and `initiallyOpen`
- Constructor hydrates from a plain object (matching the JSON shape from the backend's `CollapsibleMetaData`)
- `clone()` via spread operator for immutable copy support
### QTableSection
- Optional `collapsible?: Collapsible` field added
- Constructor conditionally instantiates `Collapsible` when present in the source object
- `clone()` updated to deep-copy the collapsible property
### QWidgetMetaData
- Optional `collapsible?: Collapsible` field added
- Constructor conditionally instantiates `Collapsible` when present in the source object
## Test plan
- [x] Verify `Collapsible` correctly deserializes `{ isCollapsible: true, initiallyOpen: false }`
- [x] Verify `QTableSection` round-trips `collapsible` through constructor and `clone()`
- [x] Verify `QWidgetMetaData` populates `collapsible` from backend JSON
- [x] Verify sections/widgets without `collapsible` in the JSON remain `undefined`
- [ ] Integration: confirm frontend renders collapse controls once the UI layer consumes these models
🤖 Generated with [Claude Code](https://claude.com/claude-code) and 🤓[Darin Code](https://kelkhoff.com/)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Frontend-core counterpart to QRun-IO/qqq#396 — adds the
CollapsibleTypeScript model and wires it intoQTableSectionandQWidgetMetaDataso the frontend can read collapsible metadata from the backend.Collapsibleclass (isCollapsible,initiallyOpen) with constructor andclone()supportQTableSectiongains an optionalcollapsibleproperty, deserialized in the constructor and properly clonedQWidgetMetaDatagains the same optionalcollapsibleproperty with constructor deserializationDetails
Collapsible (new file)
isCollapsibleandinitiallyOpenCollapsibleMetaData)clone()via spread operator for immutable copy supportQTableSection
collapsible?: Collapsiblefield addedCollapsiblewhen present in the source objectclone()updated to deep-copy the collapsible propertyQWidgetMetaData
collapsible?: Collapsiblefield addedCollapsiblewhen present in the source objectTest plan
Collapsiblecorrectly deserializes{ isCollapsible: true, initiallyOpen: false }QTableSectionround-tripscollapsiblethrough constructor andclone()QWidgetMetaDatapopulatescollapsiblefrom backend JSONcollapsiblein the JSON remainundefined🤖 Generated with Claude Code and 🤓Darin Code