Platform

Untitled UI is a web reference. It has no way to say what a control should do when there is no cursor, no hover, and a finger instead of a pointer. These are the four rules the library adds to answer that — each one a place where the same component has to behave differently on web and on touch, while keeping one set of props and one set of semantics.

Touch-first defaults

Every sized control defaults to md, not Untitled UI's sm, because a finger is not a pointer.
Untitled UI defaults sized controls to desktop density, where a mouse can hit a small target precisely. On a phone the same target is a miss. So the library flips the default: `size` defaults to `md`, and `md` is drawn at the 44pt floor a finger needs. Select's `md` trigger is exactly `minHeight: 44`; `sm` (38pt) stays available for genuinely dense, pointer-first layouts, but it is opt-in, never the shape you get by leaving the prop off.
Grammar rule G12
Sizes default to `md`, not Untitled UI's `sm` — a 44pt touch-target floor on mobile. Leaving `size` unset should never produce a control too small to tap.

Popover on web, sheet on native

Select is the precedent: one component, one prop surface, two presentations chosen by platform.
A dropdown anchored to its trigger is the web convention — a small floating list a mouse lands on easily. On touch that same list is awkward to hit and dismissed by an accidental tap just outside it. So Select renders an inline popover on web and a bottom sheet on native: the sheet is larger, easier to hit, and dismissed deliberately rather than by a stray touch. Both branches carry identical listbox and option semantics, so assistive tech and the component's props do not change — only the surface does.
One API, two surfaces
The rule is not "sheets on mobile" as a style choice. It is that a control picks the presentation each platform can actually operate, without forking its props, its selection API, or its accessibility tree. New overlays follow Select: branch on `Platform.OS` at the presentation layer only.

No hover-dependent affordances

Hover is an enhancement layered on top of a control that already works without it — never the only way in.
Touch has no hover state. Anything a person can only discover or reach by hovering is invisible and unreachable on a phone. So hover never carries meaning on its own: it dims, previews, or reveals detail that is already available through a visible control, a press, or keyboard focus. The Tooltip doctrine is the sharpest case — tooltips show on hover and focus on web and on long press on native, and because a touch user may never know to long-press, anything actually needed to act belongs in visible text or a Popover, not a tooltip.
The test
If removing every hover interaction would hide a way to do something, the design is broken on touch. Hover may make an action nicer to find; it may never be the sole path to it.

PressableFeedback, the universal primitive

Buttons, chips, rows, and controls are all the same pressable underneath — so platform behavior is written once.
Every interactive surface in the library — buttons, chips, list rows, segments, select triggers — is built on one primitive, `PressableFeedback`, rather than on raw `Pressable`. That is what lets the three platform rules above hold everywhere at once instead of per component. On top of a quick, non-bouncing press animation it adds, on web, a hover dim, a themed keyboard focus ring drawn from the `focusRing` token, and a pointer cursor; on Android it adds native ripple. The focus ring is the keyboard path the hover rule depends on, and it exists for free on anything built this way.
Build on the primitive
New interactive components wrap `PressableFeedback`, not `Pressable`. Doing so is how a component inherits the touch target, the focus ring, the hover dim, and the ripple without re-deriving platform behavior — and how it stays consistent with the rest of the library by construction.