# Icon and Label Button

## Essence

Interactive public component that renders one approved icon plus one text label as a single wrap-content button.

It uses the same icon box, typography, spacing, and accent color pattern as the non-clickable `Collapsible Menu Item` header, but owns its own button interaction states and does not own disclosure or menu behavior.

## Hook

Use when a UI needs a compact icon + label button that is not navigation and not disclosure.

## Status

Active

## Aliases

- Icon and Label Button
- Icon button with label

## Contract

- Renders an icon on the left and label text on the right.
- Uses an icon from the approved iconography catalog.
- Uses Body typography treatment.
- Uses `--color-accent` for the current icon and text color.
- Width wraps content.
- Height wraps content.
- Does not stretch to fill parent.
- Owns button interaction states: normal, hover, focus, focus-visible, pressed, and disabled.
- Does not own selection, disclosure, navigation, or menu-tree behavior.
- Does not choose the icon semantically; parent supplies the icon.

## Ownership

| Owner | Responsibilities |
| --- | --- |
| Component | Owns inline icon + label layout, spacing, typography, wrap-content sizing, and button states. |
| Parent | Supplies the icon and label. |
| Icon system | Provides approved icon components. |
| Parent composition | Owns placement and any higher-level action outcome. |

## Public Props

- `icon`: icon component from the approved iconography set.
- `label`: visible text label.
- `iconSize`: optional rendered icon glyph size, default `16`.
- `disabled`: disables the button.
- `type`: native button type, default `button`.

## Preview-Only Context

- `State` switcher on the Design System page simulates normal, hover, focus, focus-visible, pressed, and disabled states.

## Internal Rules

- Icon and label must align on the same visual row.
- Icon box matches the `Collapsible Menu Item` non-clickable header pattern.
- Text uses one line by default to preserve wrap-content behavior.
- Use generic iconography in examples unless a specific product meaning is being tested.
- Do not reuse this component inside `Collapsible Menu Item`; they are separate components with separate contracts.

## Non-Goals

- Does not replace `Menu Item`.
- Does not replace `Collapsible Menu Item`.
- Does not decide which icon is correct.
- Does not define icon search or icon taxonomy.
- Does not own navigation routing.
- Does not own disclosure state.

## Use When

- Displaying a compact icon + label button.
- Building a button action where the icon and text should stay together.
- Matching the non-clickable `Collapsible Menu Item` header visual treatment while keeping the component independent.

## Do Not Use When

- The item should navigate; use `Link`, `Menu Item`, or a future icon link component.
- The item should expand/collapse content; use `Collapsible Menu Item`.
- The icon is decorative without a visible label.
- Text must wrap across many lines inside a constrained area.

## Edge Cases

- Long labels may overflow because the component intentionally wraps content. Use shorter labels or a parent-specific wrapping variant if needed.
- Missing icon renders only the label; this should be treated as incomplete component usage.

## Accessibility Notes

- The icon is decorative because the text label carries the accessible meaning.
- Uses native `button` semantics.
- Disabled state should use the native `disabled` attribute.
- The icon is decorative because the visible label carries the accessible name.

## Token Dependencies

- `--font-sans`
- `--font-size-body`
- `--font-weight-regular`
- `--line-height-body`
- `--color-accent`
- `--space-1`
- `--space-2`

## Related Components And Patterns

| Item | Relationship | Direction | Notes |
| --- | --- | --- | --- |
| `Icons` | Uses | Component -> Token catalog | Parent picks an icon from the approved catalog. |
| `Collapsible Menu Item` | Visual Reference | Component -> Component | Icon and Label Button mirrors the non-clickable header layout but is not consumed by Collapsible Menu Item. |
| `Menu Item` | Adjacent | Component <-> Component | Menu Item owns navigation behavior; Icon and Label Button owns button behavior. |

## Change Impact

| Change | Risk | Review Needed |
| --- | --- | --- |
| Changing icon box size | Medium | Check alignment against `Collapsible Menu Item`. |
| Changing width from wrap-content to fill-parent | High | Would violate component contract. |
| Removing interaction states | High | Would violate the button contract. |

## Source Of Truth

| Source | Path / Link | Notes |
| --- | --- | --- |
| Component implementation | `packages/design-system/src/components/IconAndLabelButton.astro` | Primary behavior and layout source. |
| DS page | `apps/portfolio-site/src/pages/design-system/index.astro` | Visible documentation and example. |
| Icon token page | `/design-system/#icons` | Approved icon source. |

## Rule Confidence

| Rule | Evidence | Confidence |
| --- | --- | --- |
| Wrap-content width | User explicitly requested wrap-content width. | High |
| Same visual pattern as Collapsible Menu Item clickable=false | User explicitly requested same look. | High |
| Icon can be any icon from iconography | User explicitly requested iconography source. | High |
| Interactable component with state switcher | User corrected static implementation and requested states. | High |

## Open Questions

- Should `Icon and Label Button` later support a wrapping variant, or should wrapping belong to a parent-specific component?
- What real product action will first consume this button?

## Code Paths

- `packages/design-system/src/components/IconAndLabelButton.astro`
- `apps/portfolio-site/src/pages/design-system/index.astro`
- `apps/portfolio-site/src/pages/design-system/essences/[slug].md.ts`

## Validation Checklist

- [x] Canonical name is clear
- [x] Aliases are captured
- [x] Contract is explicit
- [x] Ownership is separated
- [x] Public props are separated from preview-only context
- [x] Token dependencies are listed
- [x] Related items use typed relationships
- [x] Accessibility notes are present
- [x] Change impact is described
- [x] Code paths are listed
- [x] DS page link is updated
- [x] Route slug is updated
- [x] Relationship map is updated
- [x] Build passed
