ComponentsTables and views

Save view bar

When someone changes a shared View's filters, sort, group, columns or search, Discard changes and Save for everyone appear in the toolbar until they choose.

Playground

Change the controls to try each prop. The code under the preview lists only the props you changed.

States
import { SaveViewBar } from '@/ui/save-view-bar';<SaveViewBar />

In the toolbar

The pair sits between search and Display: a quiet Discard changes, then Save for everyone as the secondary button. Add the filter to make the View unsaved, then save or discard. A save ends in a toast and the pair goes.

import { FunnelSimpleIcon, SlidersHorizontalIcon } from '@phosphor-icons/react';
import { useState } from 'react';
import { Button } from '@/ui/button';
import { SaveViewBar, ViewSaveStatus } from '@/ui/save-view-bar';
import { toast } from '@/ui/toast';

// Add a filter to make the View unsaved, then save or discard it.
export default function SaveViewBarInTheToolbar() {
  const [dirty, setDirty] = useState(false);
  const [saving, setSaving] = useState(false);
  const save = () => {
    setSaving(true);
    setTimeout(() => {
      setSaving(false);
      setDirty(false);
      toast.add({ type: 'success', title: 'View saved for everyone' });
    }, 1200);
  };
  return (
    <div className="flex h-11 w-full items-center justify-between gap-100 border-b border-border bg-surface px-150">
      <Button variant="ghost" selected={dirty} onClick={() => setDirty(true)}>
        <FunnelSimpleIcon />
        {dirty ? 'Stage is CV sent' : 'Filter'}
      </Button>
      <div className="flex items-center gap-100">
        <ViewSaveStatus status={saving ? 'saving' : 'idle'} />
        <SaveViewBar dirty={dirty} saving={saving} onDiscard={() => setDirty(false)} onSave={save} />
        <Button variant="ghost">
          <SlidersHorizontalIcon />
          Display
        </Button>
      </div>
    </div>
  );
}

Saving

While the save runs, Save for everyone disables and ignores more presses, and the status line left of search says so.

Saving shared View…
import { SaveViewBar, ViewSaveStatus } from '@/ui/save-view-bar';

// While the save runs, Save for everyone disables and the status line says so.
export default function SaveViewBarSaving() {
  return (
    <div className="flex items-center gap-100">
      <ViewSaveStatus status="saving" />
      <SaveViewBar saving onDiscard={() => {}} onSave={() => {}} />
    </div>
  );
}

Updating records

The same status line says when the grid reloads after a change.

Updating records…
import { ViewSaveStatus } from '@/ui/save-view-bar';

// The same line says when the grid reloads after a change.
export default function SaveViewBarUpdating() {
  return <ViewSaveStatus status="updating" />;
}

When a save can't finish

A save that can't confirm, or loses a race with someone else's, shows one warning line under the toolbar with the ways out. Nothing is discarded without the person choosing.

import { ViewSaveProblem } from '@/ui/save-view-bar';

export default function SaveViewBarProblems() {
  return (
    <div className="flex w-full flex-col gap-150">
      <ViewSaveProblem kind="uncertain" onRetry={() => {}} />
      <ViewSaveProblem kind="conflict" savedBy="Priya" viewName="Shortlisted" onUseShared={() => {}} onKeepMine={() => {}} />
    </div>
  );
}

On this page