# Interaction states, responsive polish & a smoother docs experience

> Source: https://design.nanatec.co.ke/blog/interaction-and-responsive-polish/
> A library-wide interaction-state sweep, a responsive docs pass, native smooth scrolling, and a centered top-bar search.

<p style="color: var(--sl-color-gray-3); font-size: 0.9rem; margin-top: -0.5rem;">
  <time datetime="2026-07-18">July 18, 2026</time> · Engineering
</p>

This release is about the details you feel rather than see on a feature list:
how every control responds to a press, a keyboard, or a touch — and how the docs
themselves behave across screens. Hover is only one interaction state; a
professional component treats pointer, keyboard, and touch as first-class.

## A library-wide interaction sweep

We audited all 63 components against the full interaction hierarchy — not just
hover. The foundation was already strong (disabled, focus-visible, keyboard,
reflected state, reduced-motion, forced-colors were broadly covered), so this
pass closed the real gaps:

- **Touch-hover guard.** Every visible `:hover` style is now wrapped in
  `@media (hover: hover)` so a tap on a phone never *latches* a hover state until
  you tap elsewhere. Where hover was fused into a `:hover, :focus-visible`
  selector, we split them — keyboard focus stays ungated.
- **Press feedback.** `:active` fires for mouse, pen, **and** touch, so it's the
  one affordance that works everywhere. Buttons, cards, tags, and menu items now
  give tactile feedback on press — menu items even mirror their highlight so a tap
  reads instantly.
- **Pointer over mouse.** Outside-click dismissal in the color picker and editor
  moved from `mousedown` to `pointerdown` for reliable touch behavior. The
  deliberate `mousedown`+`preventDefault` idiom on remove/clear buttons was left
  intact — it exists to *stop* focus theft and already works cross-device.

```html
<nana-button variant="primary">Press me</nana-button>
<nana-button variant="secondary">Secondary</nana-button>
<nana-tag removable>Removable</nana-tag>
<nana-icon-button label="Star"><nana-icon name="star"></nana-icon></nana-icon-button>
```

### Shared, not scattered

Rather than copy-paste the same rules into 63 files, the reusable pieces live in a
single `src/styles/interactions.ts` module (a `pressable` fragment and a
`focusRing`), composed into a component's styles. On mixins: the library already
ships the *right* ones — `Focusable`, `FormAssociatedMixin`, `NanaEventsMixin` —
so we invested in wider adoption and shared styles instead of inventing a new
class hierarchy on a shipping library.

Everything honors `prefers-reduced-motion`, and because component styles live in
shadow DOM, a page-level motion reset can never leak into them.

## Responsive docs, top to bottom

The documentation site now holds up from roughly 320px on up:

- **Wide API tables** scroll horizontally on narrow screens instead of pushing the
  whole page sideways.
- **Display type, hero actions, stat strips, and the CTA** scale and stack
  gracefully on small screens.
- **Long URLs and union types** wrap instead of overflowing.

## Smoother by default

- **Native smooth scrolling** (`scroll-behavior: smooth` + `scroll-padding-top`)
  eases anchor and table-of-contents jumps — no JavaScript, no dependency — and
  switches off under `prefers-reduced-motion`.
- **A centered top-bar search**, sized as a real search field, so it's easy to
  find at a glance.

## Why this matters

A component library earns trust in the small moments: the button that dips when
you press it, the menu that doesn't stick under your thumb, the page that never
scrolls sideways on a phone. This release is a down-payment on that trust — and a
standard we'll hold new components to.
