# Native icon buttons

Native icon-button mode shipped in v2.17.0, and ASIcon glyph rendering shipped in v2.18.0. The createGlyphIcon factory requires a package release containing the factory.

Use `ASIconButton as="button"` for a native button with keyboard activation, form semantics, and a button ref. Omitting `as` keeps the existing ASTappable path and `onIconButtonTap` callback. Both paths use the same `components.iconbutton` theme slots and size configuration.

```tsx
<ASIconButton
  as="button"
  icon={SearchIcon}
  aria-label="Search"
  onClick={openSearch}
/>
```

Provide an accessible name with `aria-label` or `aria-labelledby`; the glyph is decorative and hidden from assistive technology. Native mode uses `onClick` for mouse, Enter, Space, and programmatic activation. It defaults to `type="button"`; opt into form submission with `type="submit"`.

## Selection

Add `toggle` to change selection on activation and expose that selection through `aria-pressed`.

```tsx
<ASIconButton
  as="button"
  icon={EditorIcon}
  aria-label="Editor mode"
  toggle
  selected={editorMode}
  onSelectedChange={setEditorMode}
/>
```

Supplying `selected` makes the parent responsible for updating it. Omit `selected` to let the component own selection, optionally starting with `defaultSelected`. The caller's `onClick` runs first; calling `event.preventDefault()` cancels the automatic selection change. Selection without `toggle` can style a button without adding toggle behavior.

## Disabled, loading, and refs

`disabled` and `isLoading` both disable the native button, removing it from sequential keyboard navigation and preventing activation. Loading retains the glyph and sets `aria-busy`; it does not replace the icon with a spinner.

A React 19 `ref` resolves to the `HTMLButtonElement`, allowing `ref.current?.focus()`. Native props are exported as `ASNativeIconButtonProps`; the existing `ASIconButtonProps` continues to describe the ASTappable path. Changing `as` replaces the rendered path and resets internal selection.

## Custom icons

The `icon` prop accepts a component compatible with `IconProps`. Use `createGlyphIcon` to define reusable font icons. Pass a factory-created icon directly to `ASIconButton`. All modes support `GlyphIcons`. Custom SVG components can also consume the supplied `iconSize`, `fillColor`, and `color`.

The **Google Material Icons** story uses the public factory to demonstrate Material Symbols Rounded at weight 300, including all three sizes, selection, disabled, and loading states. Storybook loads the Google stylesheet in its preview head; consumers load their own font and own their application's icon collection.

```tsx
import { ASIconButton, createGlyphIcon } from '@eleventheye/asui';

// Define icons once at module scope, typically in your app's icons.ts.
const fontFamily = 'Material Symbols Rounded';
const EditIcon = createGlyphIcon({ glyph: 'edit', fontFamily });
const BoldEditIcon = createGlyphIcon({ glyph: 'edit', fontFamily, weight: 600 });
const FilledFavorite = createGlyphIcon({
  glyph: 'favorite', fontFamily, fill: 1, grade: 200, opticalSize: 48,
});
<ASIconButton as="button" icon={EditIcon} aria-label="Edit" onClick={openEditor} />
```

The factory defaults to `weight: 300`, `fill: 0`, `grade: 0`, and `opticalSize: 48`. Weight sets both CSS font weight and the variable font's `wght` axis. Optical size controls the glyph design; `iconSize` controls its rendered pixel size. Use axis values supported by your loaded font. Storybook includes comparisons for all four axes.

See [Font glyph icons](./glyph-icons.md) for font setup, the shared icon-module pattern, all factory options, instance overrides, accessibility, and refs. SVG icons continue to use their own stroke settings.

Native icon-button mode currently supports `as="button"` only. For icon-only navigation, use the existing ASButton link API; do not add navigation inside a click handler to imitate a link.

## Verification

Storybook: **ASUI Components → ASIconButton → Native behavior → Keyboard And Selection**. The story exercises Enter/Space activation, explicit submission, ref focusing, controlled/uncontrolled selection, cancelled selection, disabled/loading controls, custom glyphs, and all three sizes. Browser execution and visual review are required alongside the production and Storybook TypeScript checks and `npm run test:theme`.
