Seam

Halftone Section Divider for React

The edge between two sections, printed as a halftone. Drop it between a light section and a dark one and it reads both backgrounds; as you scroll past, the color below climbs into the band cell by cell along a ragged front, so the next section reaches up to meet you instead of starting at a hard line.

  • Background
  • Scroll
  • Canvas

Uses clsx, tailwind-merge

Open in ChatGPTOpen in Claude
cell12px
grain0.60
seed1
stiffness120
damping30
<Seam />

The demo follows as you drag.

Brand and product studio · Oslo

We design the first five seconds.

Identities, launch sites and product UI for teams heading into their first big release.

Since 2019

launches shipped since 2019
42
launches shipped since 2019
median from brief to a live first page
9 days
median from brief to a live first page
teams back for a second release
31
teams back for a second release
Selected work
  • TesselLaunch site for an AI upscaler2026
  • OktoIdentity and app UI for payroll2025
  • Marrow & VineSite and menus for a restaurant group2025

Have a launch on the calendar?

Book a call

© 2026 Halden Studio · halden.example

Take this demo to your coding agent.
Add this moment from KeyframeUI to our project and adapt it to our content.

Seam: The edge between two sections, printed as a halftone. Drop it between a light section and a dark one and it reads both backgrounds; as you scroll past, the color below climbs into the band cell by cell along a ragged front, so the next section reaches up to meet you instead of starting at a hard line.
This demo, Studio Site: A design studio's page, where the hero gives way to a blue stats band and back, in dots, squares or dither.

1. Install it:
   npx shadcn@latest add @keyframeui/seam-demo
   (If the CLI can't find @keyframeui, use https://keyframeui.com/r/seam-demo.json instead.)
   It adds the demo, components/seam-demo.tsx, and the component, components/ui/seam.tsx.

2. Make it ours: our copy, data, images and colors. Keep the structure the motion depends on. If we only need the effect, use <Seam> on its own.

3. These props set its feel. Change them before you change the file:
   - cell (default 12): Size of one cell, in px. Rounded to whole pixels so full cells meet without seams.
   - grain (default 0.6): How ragged the front is, from a straight line (`0`) to deep tongues (`1`).
   - seed (default 1): Changes the shape of the front's tongues. Give two seams on one page different seeds.
   - stiffness (default 120): Stiffness of the spring the front rides as it follows scroll. Higher keeps it closer to the scroll; lower lets it trail behind and glide in.
   - damping (default 30): Damping of that spring. Lower lets the front overshoot and settle back after a fast scroll.

4. Don't change, in components/ui/seam.tsx:
   - The front is painted on one canvas by one rAF loop that stops once the spring settles; scroll never re-renders React.
   - Cells are whole pixels and the rows are anchored to the band's bottom, so full cells meet edge to edge and the band meets the next section exactly.
   - The top and bottom `edgeRows` are pinned to their section's color, so neither edge of the band shows a line.
   - Mounting, resizing and coming back on screen snap the front to the scroll position instead of springing to it.
   - Under reduced motion the front skips the spring and sits exactly where the scroll puts it.
   Its timing is all in the TIMING block at the top of that file.

Docs: https://keyframeui.com/components/seam.md

Installation

Add the component on its own with the CLI, or copy the file in by hand.

The CLI writes components/ui/seam.tsx and installs clsx and tailwind-merge. It needs the @keyframeui registry in components.json; add it once per project.

npx shadcn@latest add @keyframeui/seam

Examples

Finished sections built with Seam. Each one installs whole, with the component included.

Changelog

A product changelog where the tinted latest release fades into the list of earlier ones through fine dots.

Changelog

Latest · v4.2 · Nov 4, 2026

Live cursors in comment threads
  • See who is reading a thread and where, with their cursor on the card they're looking at.
  • Replies arrive in place instead of reloading the thread.
  • Mentions now notify on mobile within two seconds.
Earlier releases
  1. v4.1 · Oct 21, 2026

    Branching boards

    Fork any board to try a layout, then merge it back with a diff of every card that moved.

  2. v4.0 · Oct 2, 2026

    Offline mode

    Boards open and edit without a connection, and sync the moment you're back.

  3. v3.9 · Sep 12, 2026

    Export to SVG and PDF

    Export a frame or a whole board, with fonts embedded and links kept.

  4. v3.8 · Aug 28, 2026

    Faster search

    Search now covers card text, comments and file names, in under 100ms on boards of 10,000 cards.

  5. v3.7 · Aug 7, 2026

    Guest seats

    Invite clients to a single board with comment-only access. Guests don't count toward your plan.

  6. v3.6 · Jul 17, 2026

    Card templates

    Save any card as a template with its fields, checklist and cover, and reuse it across boards.

  7. v3.5 · Jun 30, 2026

    Keyboard-first editing

    Move, link and resize cards without the mouse. Press ? on any board for the full map.

Take this demo to your coding agent.
Add this moment from KeyframeUI to our project and adapt it to our content.

Seam: The edge between two sections, printed as a halftone. Drop it between a light section and a dark one and it reads both backgrounds; as you scroll past, the color below climbs into the band cell by cell along a ragged front, so the next section reaches up to meet you instead of starting at a hard line.
This demo, Changelog: A product changelog where the tinted latest release fades into the list of earlier ones through fine dots.

1. Install it:
   npx shadcn@latest add @keyframeui/seam-changelog-demo
   (If the CLI can't find @keyframeui, use https://keyframeui.com/r/seam-changelog-demo.json instead.)
   It adds the demo, components/seam-changelog-demo.tsx, and the component, components/ui/seam.tsx.

2. Make it ours: our copy, data, images and colors. Keep the structure the motion depends on. If we only need the effect, use <Seam> on its own.

3. These props set its feel. Change them before you change the file:
   - cell (default 12): Size of one cell, in px. Rounded to whole pixels so full cells meet without seams.
   - grain (default 0.6): How ragged the front is, from a straight line (`0`) to deep tongues (`1`).
   - seed (default 1): Changes the shape of the front's tongues. Give two seams on one page different seeds.
   - stiffness (default 120): Stiffness of the spring the front rides as it follows scroll. Higher keeps it closer to the scroll; lower lets it trail behind and glide in.
   - damping (default 30): Damping of that spring. Lower lets the front overshoot and settle back after a fast scroll.

4. Don't change, in components/ui/seam.tsx:
   - The front is painted on one canvas by one rAF loop that stops once the spring settles; scroll never re-renders React.
   - Cells are whole pixels and the rows are anchored to the band's bottom, so full cells meet edge to edge and the band meets the next section exactly.
   - The top and bottom `edgeRows` are pinned to their section's color, so neither edge of the band shows a line.
   - Mounting, resizing and coming back on screen snap the front to the scroll position instead of springing to it.
   - Under reduced motion the front skips the spring and sits exactly where the scroll puts it.
   Its timing is all in the TIMING block at the top of that file.

Docs: https://keyframeui.com/components/seam.md

Props

pattern

Type"dots" | "squares" | "dither"Default"dots"

What the band breaks up into: halftone dots whose gaps close like a print's, halftone squares, or a pixel dither that switches whole cells through a 4 × 4 ordered matrix.

cell

TypenumberDefault12

Size of one cell, in px. Rounded to whole pixels so full cells meet without seams.

grain

TypenumberDefault0.6

How ragged the front is, from a straight line (0) to deep tongues (1).

progress

Typenumber

Hold or drive the front yourself, from 0 (all the section above) to 1 (all the section below). Leave it out to follow scroll in the nearest scrolling box or the window.

seed

TypenumberDefault1

Changes the shape of the front's tongues. Give two seams on one page different seeds.

stiffness

TypenumberDefault120

Stiffness of the spring the front rides as it follows scroll. Higher keeps it closer to the scroll; lower lets it trail behind and glide in.

damping

TypenumberDefault30

Damping of that spring. Lower lets the front overshoot and settle back after a fast scroll.

fromClassName

Typestring

A text-* color for the section above. Without it, the band reads the background of the element before it, and follows it into dark mode.

toClassName

Typestring

A text-* color for the section below. Without it, the band reads the background of the element after it.

children

TypeReact.ReactNode

Optional content drawn over the band, such as a label.

className

Typestring

Extra classes for the root. Set the band's height here; it defaults to h-40.