# Button-styled links

ASButton supports three explicit rendering paths. Omitting `as` keeps ASTappable and `onTapped`. `as="button"` retains native form/button behavior. `as="a"` or an anchor-compatible component renders a link using the same button theme.

```tsx
import { ASButton, type ASLinkButtonProps } from '@eleventheye/asui';
import { Link } from 'react-router-dom';

<ASButton as="a" href="https://example.com" target="_blank" rel="noopener noreferrer">
  Open project
</ASButton>
<ASButton as={Link} to="/projects" onClick={handleNavigationClick}>
  Back to projects
</ASButton>
```

React Router is a development dependency for verification only. ASUI does not import it in production. A custom target must render an anchor and forward `className`, children, anchor attributes/events, and an HTMLAnchorElement ref. The `as` target determines destination props and ref/event types; for example, Link requires `to`, while a native anchor uses `href`.

## Navigation and state

- Use `href` for a native anchor or the selected component's destination prop, such as React Router Link's `to`.
- Enter activates a focused link; Space does not. Browser/router behavior handles modifier-click, `target`, `rel`, and `download`. The ASTappable pointer debounce does not apply.
- Call `preventDefault()` in `onClick` to cancel navigation. Use `onClick`, not `onTapped`.
- Links do not support `toggle`. Use `selected` for appearance and explicitly set `aria-current="page"` when the link represents the current page. ASUI does not determine the current route for you.
- Project primary/secondary button overrides apply through the existing button theme slots.

## Disabled and loading links

`disabled` or `isLoading` removes navigation and removes the link from the tab order. Clicks are blocked, and caller click handlers do not run. Loading retains the accessible label/layout, shows a spinner, and sets `aria-busy`.

ASUI achieves this by rendering an anchor with no destination, `role="link"`, `aria-disabled`, and `tabIndex={-1}`. For a custom routing component, this replaces that component while inactive. Its local state resets and its ref detaches/reattaches when the rendering target changes.

The fallback anchor retains identity/style, language/direction, data attributes, and ARIA attributes. Custom-target props and event handlers other than ASUI's click guards are not forwarded. A custom target must therefore tolerate being unmounted while disabled or loading.

`ASButtonProps` and `ASNativeButtonProps` remain available and extendable. `ASLinkButtonProps` describes native anchors; `ASLinkButtonProps<typeof Link>` describes router links. Refs resolve to the rendered anchor.

## Verification

The **ASButton → Link behavior → Navigation And Keyboard** Storybook fixture uses a real MemoryRouter/Link and checks destination rendering, routing/cancellation, disabled/loading links, refs, Enter versus Space, tab order, and theme inheritance. The in-app Chromium run passed 43 interaction steps. Type fixtures cover extendable consumer props, Link destinations, anchor refs/events, and rejected button/tap-only inputs. All 42 regression tests pass, including real-router rendering and ensuring inactive targets never mount.

The production and Storybook TypeScript checks pass. Andrey verified appearance and keyboard behavior in Safari: Enter activates, Space does not, disabled/loading links are skipped, and cancellation prevents navigation. The standalone preview was used to avoid Storybook toolbar focus; Safari required Option–Tab for link navigation. Published-package portfolio link migration remains a follow-up. This change is unreleased and does not change existing portfolio links automatically.
