All components
0:00/0:00
Appearance

Recorded on iPhone. The button inside Telegram, ChatGPT, Grok, WhatsApp and Slack, then close up on the send, Speak and hang-up buttons as the metal drifts.

Shader

Liquid Metal Button

A pressable button whose face is moving liquid metal, with drifting chrome reflections.

Features

  • A button that looks poured from moving chrome
  • Three styles: a metal ring, a metal rim around glass, or glass over metal
  • Four ready-made looks: bright chrome, gunmetal, ember and stripes
  • Holds an icon, a label, or both, as a circle or a pill
  • Runs on iOS and Android, with real Liquid Glass on iOS 26 and a blur elsewhere
  • The ring's centre turns white or black to match light or dark mode
  • Holds still when Reduce Motion is on

Built with

  • Skia runtime shader
  • Reanimated
  • expo-glass-effect
  • expo-blur

Early access

Checkout opens soon

TesseraUI is in early access. Leave your email and we'll let you know the moment you can buy, before anyone else.

No spam. One email when checkout opens.

Or get it with Pro

Installation

1Install dependencies
npx expo install @shopify/react-native-skia react-native-reanimated react-native-worklets expo-glass-effect expo-blur
2Run a development build (Expo Go can't load Skia)
npx expo run:ios   # or: npx expo run:android

Usage

import { LiquidMetalButton } from '@/components/liquid-metal-button';

export function SendButton() {
  return (
    <LiquidMetalButton onPress={send} accessibilityLabel="Send">
      <SendIcon />
    </LiquidMetalButton>
  );
}

Examples

Three styles

A metal rim around a solid well, a metal rim around glass, or glass over the whole metal face.

<LiquidMetalButton variant="ring" />
<LiquidMetalButton variant="lens" />
<LiquidMetalButton variant="glass" />

Presets and tint

Pick a look, then override any single value.

<LiquidMetalButton preset="noir" />

<LiquidMetalButton preset="ember" config={{ tint: '#d00000' }} />

A labelled pill

Give it a height and padding, and it grows to fit an icon and a label.

<LiquidMetalButton style={{ height: 44, paddingHorizontal: 16, gap: 4 }}>
  <WaveIcon />
  <Text>Speak</Text>
</LiquidMetalButton>

Props

PropTypeDefaultDescription
childrenReactNode—An icon, a label, or both, laid out in a centred row.
onPress(event: GestureResponderEvent) => void—Called when the button is pressed.
variant"ring" | "lens" | "glass""lens"A metal rim around a solid well, a metal rim around glass, or glass over the whole face.
preset"default" | "noir" | "ember" | "stripes""default"The look of the metal: bright chrome, soft blue gunmetal, chrome with a hot orange glow, or dense colourful stripes.
speednumber1Animation speed. 0 holds still.
configPartial<LiquidMetalConfig>—Fine tuning. See Advanced.
styleStyleProp<ViewStyle>—Size, shape and layout.
accessibilityLabelstring—Read by screen readers. Set it whenever the button shows only an icon.

Advanced

Everything most apps never need to touch.

Every field is optional and overrides the preset.

FieldDefaultDescription
tint"#ffffff"Colour burned into the metal. White is none; alpha sets the strength.
softness0.1Softness of the reflection edges, 0–1.
repetition2Reflection bands across the surface, 1–10.
shiftRed0.3Warm colour fringe on the reflections, -1–1.
shiftBlue0.3Cool colour fringe on the reflections, -1–1.
distortion0.07Noise that bends the reflections, 0–1.
contour0.4How closely the reflections follow the outline, 0–1.
angle70Direction the reflections travel, in degrees.
highlightColor"#fafaff"Brightest colour of the metal.
shadowColor"#1a1a1a"Darkest colour of the metal.

PropDefaultDescription
onLongPress—Called on a long press.
disabledfalseIgnores presses.
ringWidth3Width of the metal rim around the well, in points. Ignored by glass.
bevel0.5Depth of the rolled metal edge, 0–1. 0 is a flat cut.
glassStyle"regular"Glass look for lens and glass: "regular" or "clear".
glassTint—Colour laid over the glass.
innerColor"auto"Well colour for ring. Auto is white in light mode and black in dark mode.
pausedfalseHolds the metal still.

  • With no width or height it is at least 40 points each way and grows to fit its content.
  • It is a circle or a pill unless style sets a borderRadius.
  • Pressing dims it to 70% opacity.
  • Works on iOS and Android from the same code, but not on web. The metal looks the same on both.
  • Glass is native Liquid Glass on iOS 26 and newer. On older iOS and on Android it is a blur of the metal with a hairline rim. ring has no glass, so it is identical everywhere.

  • Screen readers announce it as a button, with its accessibilityLabel, and as dimmed when disabled.
  • With Reduce Motion on, the metal holds still.

How it works

A Skia shader draws the metal: bands of reflection travel across a rounded surface, bend with noise and split into warm and cool fringes, while the distance to the button's outline shades the rolled edge. Everything except the clock is worked out once per layout, so each frame only moves time forward. The shader is ported from Paper Design's liquid metal shader.

Next componentLiquid Metal Shape