# Product Configurator

Canonical: https://socra.design/composed-components/product-configurator

Show the selected product beside focused configuration choices.

Keep choices and their summary together without owning the host’s purchase or permission rules.

Status: partial. Real ProductConfigurator and ProductConfiguratorVisual exports. Named compact disclosure verification is tracked on issue_01m4n5z9cbe6j60v3e3jmab2q9.

Library: @socra/web-ui

## Anatomy

- A summary aside remains beside choices at wide widths.
- Only the compact selection and price stay pinned while choices scroll. Expanded details scroll with the page and are brought into view when reopened.
- The optional detailsLabel string names the compact disclosure. It defaults to Configuration details; use a specific label such as Costs and details when the summary explains charges.
- ProductConfiguratorVisual bounds product artwork without scaling controls.

## States

- **Rest:** Shows the stable, enabled component without implied activity.
- **Hover:** Every enabled clickable target shows a pointing hand. Keep the shared visual hover treatment independent, without moving content or changing meaning.
- **Focus:** Shows the shared visible focus treatment without depending on hover.
- **Pressed:** Acknowledges active input immediately and returns cleanly on release.
- **Selected:** Uses a neutral surface plus native selected semantics when selection applies.
- **Disabled:** Remains legible, unavailable, and absent from misleading interaction feedback.
- **Loading:** Preserves context while honestly identifying work that has not completed.
- **Error:** Places the failure and recovery path beside the action or content that failed.

## Motion

Stable state changes respond immediately. Appearance, expansion, and morphing begin at the triggering origin and use an interruptible spring that can retarget from its live position and velocity. When spatial motion is not meaningful, the component changes without decorative travel.

## Usage

- Use the owning platform implementation first. Each renderer improves once and every product on that platform inherits the fix.
- Name the user job before the component. A component earns a place only when it helps the user decide, act, recover, or understand.
- Promote missing behavior into the owning platform domain. Product-local UI creates drift; platform contracts preserve shared meaning and native quality.
- Raise luminance to bring a surface forward. Depth reads as light. A surface that comes toward the reader catches more of it, so a raised panel, a selected tab, a menu, a popover resolves LIGHTER than what it sits on — in dark mode away from the canvas, in light mode toward the white it cannot exceed. The ladder runs page, resting card, elevated, and never doubles back.

## Avoid

- Do not build a product-local replacement. A local implementation splits behavior, access requirements, and future migrations.
- Do not copy theme values. Semantic values are shared system roles and are consumed by meaning.
- Do not add decoration as a substitute for structure. If the hierarchy is weak, fix the hierarchy.
- Do not darken a surface to lift it. Darkening in a dark theme pushes a surface INTO the page — it reads as a hole cut in the canvas rather than a panel resting on it. Sinking a surface to make it stand out is the most common way a dark interface loses its depth.

## Tokens

- `designTokens.color[mode].color.brand.primary`: Primary action role.
- `designTokens.color[mode].color.surface.secondary`: Working surface role.
- `designTokens.color[mode].color.content.primary`: Primary content role.
- `designTokens.spacing.role.contentGap`: Spacing relationship.
- `designTokens.shape.role.control`: Shape relationship.

## Example

```tsx
import { appHome, typography, field } from '@socra/web-ui';
<appHome.ProductConfigurator detailsLabel="Costs and details" compactSummary={<typography.Body>Your configuration · $12 per month (example)</typography.Body>} summary={<><appHome.ProductConfiguratorVisual><span aria-hidden="true">A</span></appHome.ProductConfiguratorVisual><typography.Title>Your configuration</typography.Title><typography.Body>Example: $12 per month</typography.Body></>}>
  <field.TextField label="Name" defaultValue="Research partner" />
</appHome.ProductConfigurator>
```
