Skip to content
Nizivo UI

StickyBar

A bar of actions that sticks to the bottom of the viewport while its section scrolls, above the device's home indicator and the shell's bottom tab bar.

Server component, no client JS

Import

import { StickyBar } from '@nizivo/react/sticky-bar';

// Once per app (Getting started), after
// @nizivo/tokens/tokens.css and @nizivo/react/css/base.css
import '@nizivo/react/css/sticky-bar.css';

Static or interactive

Server. It ships no client JavaScript when a Server Component renders it, in every Next.js build mode; its code is bundled only when a client component (a 'use client' file) imports it. How to choose.

In a client app (a Vite or React Router single-page app, or a 'use client' file) it is an ordinary React component: event handlers, refs and state work as usual. In a client app.

Placement

Put it last in the content it acts on: it sticks to the viewport's bottom edge while that content scrolls, and settles at its end. A summary (for example the item count and the total) sits at the start, Label/M in text/secondary; the actions sit at the end. Without a summary, the actions share the row, as the storefront's product screen draws them.

The bar's bottom padding includes the device's safe area (env(safe-area-inset-bottom), which needs viewport-fit=cover in the page's viewport meta), where Figma drew a fixed 28 px. It sits above the shell's bottom chrome through --nz-layout-bottom-inset, in the --nz-z-sticky band: below overlays and toasts.

Hooks: --nz-sticky-bar-bg, --nz-sticky-bar-border, --nz-sticky-bar-gap.

Examples

Basic

The storefront's post view (10): the items and their total, then one action.

2 items$62.00
import type { JSX } from 'react';
import { Button } from '@nizivo/react/button';
import { NumberValue } from '@nizivo/react/number-value';
import { StickyBar } from '@nizivo/react/sticky-bar';

export function StickyBarExample(): JSX.Element {
  return (
    <StickyBar
      summary={
        <>
          <span>2 items</span>
          <NumberValue value={62} format={{ style: 'currency', currency: 'USD' }} />
        </>
      }
    >
      <Button size="lg" variant="primary">
        Add both to bag
      </Button>
    </StickyBar>
  );
}

Actions

The product screen (10): two actions share the bar.

import type { JSX } from 'react';
import { Button } from '@nizivo/react/button';
import { StickyBar } from '@nizivo/react/sticky-bar';

export function StickyBarActionsExample(): JSX.Element {
  return (
    <StickyBar>
      <Button size="lg" variant="secondary">
        Buy now
      </Button>
      <Button size="lg" variant="primary">
        Add to bag
      </Button>
    </StickyBar>
  );
}

Props

A bar that sticks to the bottom of the viewport while its section scrolls: the last child of the page's content, or of the region it acts on.

Server component Renders data-slot="sticky-bar" with the class nz-sticky-bar. Props: StickyBarProps. Source: src/sticky-bar/sticky-bar.tsx.

NameTypeDefaultDescription
childrenReactNode–

The actions, usually one or two size="lg" Buttons, at the end.

renderRenderProp<Record<string, never>>–
summaryReactNode–

At the start, for example "2 items" and the total.

  • Also takes every attribute of <div>; children is redeclared above. (ComponentPropsWithRef<"div">)

render takes an element, or, in client code, a function of the props and no state.

Other exports

StickyBarProps type

import type { StickyBarProps } from '@nizivo/react/sticky-bar'

The props of StickyBar, listed above.

Data attributes and slots

Style parts by class (.nz-<slot>) and state by data attribute. Attribute meanings come from contracts/vocabulary.json.

SlotRendered byData attributes
sticky-bar
.nz-sticky-bar
StickyBar
root (takes render)
none
sticky-bar-actions
.nz-sticky-bar-actions
StickyBar
inner element (CSS only)
none
sticky-bar-summary
.nz-sticky-bar-summary
StickyBar
inner element (CSS only)
none

CSS hooks

Set a hook on the component's class or any ancestor to restyle it without specificity games; leave it unset for the default shown.

HookDefaultRead as
--nz-sticky-bar-bg--nz-bg-surface
  • background on .nz-sticky-bar
--nz-sticky-bar-border--nz-border-subtle
  • border-block-start on .nz-sticky-bar
--nz-sticky-bar-gap--nz-space-3
  • gap on .nz-sticky-bar
  • gap on .nz-sticky-bar-actions

Layers: nz.components. Classes: .nz-sticky-bar, .nz-sticky-bar-actions, .nz-sticky-bar-summary. Runtime variables: --nz-layout-bottom-inset.

Tokens this stylesheet reads (10)

--nz-bg-surface, --nz-border-subtle, --nz-border-width-default, --nz-font-label-m, --nz-space-3, --nz-space-4, --nz-text-primary, --nz-text-secondary, --nz-tracking-label-m, --nz-z-sticky

Accessibility

Nothing in this component takes focus or keyboard input.

Keyboard

None.

Figma

Node ids from design/component-map.json, which nz gen writes from component.json. The links open the Nizivo Figma library, which may ask you to sign in.

  • Canonical: none
  • Ghost masters: none

On this page