Pressable

An unstyled clickable surface: button semantics - keyboard activation, focus ring, disabled state - with none of a button's looks. It carries no padding, margin, border, background, or font of its own, so it can wrap arbitrary content without shifting a single pixel of it.

Reach for this instead of putting onClick on a div or a styled Flex. Those are invisible to keyboard and screen-reader users; this is not. Reach for Button instead when you want something that looks like a button.

feedback picks what happens while the surface is held - nothing (the default), the content dims, or the surface tints. Feedback is press-only, so hover styling stays entirely yours.

What it renders

A div by default. That is deliberate: a <button> may only contain phrasing content, so it cannot legally wrap a link, another button, or block-level markup - exactly the things a clickable card or row is made of. The div is given role="button", a tab stop, Enter/Space activation, and aria-disabled, so it is announced and operated as a button regardless.

asElementSemantics
(default)divShimmed - role, tabIndex, Enter/Space.
"button"buttonNative. Use when the content is phrasing-only.
(any other tag)that tagShimmed, same as the div.
(href set)aNative link. No shim; Enter activates.

as="button" is worth reaching for when the content is phrasing-only and you want the browser rather than a shim to do the work.

Whichever element it renders, its text is not selectable: dragging across it or double-clicking it presses rather than highlighting, matching a native button. Override with userSelect through theme.components.Pressable.styleOverrides or a styled() wrapper if you are deliberately wrapping selectable copy.

Usage

// A clickable row that lays out exactly as it would unwrapped.
<Pressable onClick={() => select(id)}>
  <Flex flexDirection="row" alignItems="center" gap={2}>
    <Icon name="folder" size="1.25rem" color="inherit" />
    <span>Documents</span>
  </Flex>
</Pressable>

// Dim the content while held.
<Pressable feedback="opacity" activeOpacity={0.4} onClick={onPress}>
  <Avatar src={user.avatar} alt={user.name} />
</Pressable>

// Tint the surface while held - padding and radius are opt-in.
<Pressable feedback="highlight" color="secondary" p={2} borderRadius="md" onClick={onPress}>
  <Typography as="span">Settings</Typography>
</Pressable>

// A native button - the content here is phrasing-only, so it is legal.
<Pressable as="button" onClick={onPress}>
  <Typography as="span">Save</Typography>
</Pressable>

// Renders an anchor.
<Pressable href="/docs">Read the docs</Pressable>

Examples

Default

Press me
<Pressable>Press me</Pressable>

Opacity

Hold to dim
<Pressable feedback="opacity">Hold to dim</Pressable>

Highlight

Hold to tint
<Pressable feedback="highlight" p={2} borderRadius="md">Hold to tint</Pressable>

Wrapping Content

Documents
<Pressable feedback="highlight" p={2} borderRadius="md" width="16rem">
  <Flex flexDirection="row" alignItems="center" gap={2} width="100%">
    <Icon name="folder" size="1.25rem" color="inherit" />
    <Typography as="span" variant="inherit" m={0}>
      Documents
    </Typography>
  </Flex>
</Pressable>

Pressable API reference