Skip to content

Status Feedback And Badges

StatusFeedbackPanel groups activity into one outlined surface with a heading, item count, and divided rows. Each row accepts a title, description, optional detail, semantic tone, loading indicator, and actions. The component renders the supplied state; your application owns requests, retries, and state transitions.

import { h, render } from 'preact';
import { StatusFeedbackPanel, StatusBadge } from '@revolist/revogrid-pro';
import '@revolist/revogrid-pro/styles.css';
render(
<StatusFeedbackPanel title="Sync activity" items={[
{
id: 'card-save',
title: 'Changes need review',
description: 'This card was updated elsewhere.',
detail: 'Your newer edits are kept.',
tone: 'warning',
actions: [
{ id: 'retry', label: 'Retry changes', appearance: 'primary', onClick: () => retrySave() },
{ id: 'server', label: 'Use server data', onClick: () => loadServerData() },
],
},
{
id: 'queued-save',
title: 'Save queued',
description: 'Waiting for the previous save.',
busy: true,
actions: [{ id: 'cancel', label: 'Cancel', appearance: 'ghost', onClick: () => cancelSave() }],
},
]} />,
document.querySelector('#activity')!,
);
render(<StatusBadge label="Saved" tone="success" />, document.querySelector('#save-state')!);

Supply stable item and action IDs. An empty items array renders no panel. Actions use native buttons and accept disabled and ariaLabel. Use appearance: 'primary' for the main action, 'secondary' for an outlined button, and 'ghost' for a quieter action. Secondary is the default.

Use renderStatusFeedbackPanel(h, props) or renderStatusBadge(h, props) inside a RevoGrid template or registered overlay node. Pass the template’s own h function so the grid remains the renderer owner. The same helpers back the Preact components.

Kanban uses the shared panel for its persistence feedback. Its adapter supplies transaction messages and callbacks; the shared component has no dependency on Kanban or its save implementation.

Both components accept tone: 'neutral' | 'warning' | 'danger' | 'success'. Set busy: true to show the loading indicator. Use a descriptive label or title so state is communicated through text as well as color and icons.

The panel uses alert semantics for warning and danger rows, and status semantics for other rows. Decorative icons are hidden from assistive technology. Buttons retain native keyboard operation and visible focus, while panel interactions are isolated from grid selection and keyboard shortcuts. Loading animation is disabled when reduced motion is requested.

The panel follows shared --rv-ui-* surface, text, border, radius, button, and focus tokens. Semantic colors can be customized with --rv-status-warning, --rv-status-danger, and --rv-status-success. Light and dark themes follow the same Pro theme selectors as other shared controls. Actions wrap below the message when the panel’s container is narrow; long text wraps within its row.

For a floating activity surface, create a StatusFeedbackPopoverController and pass it as the panel’s popover prop. Attach controller.anchorRef to the bottom-right anchor element. Supply onChange to rerender your view, and call controller.destroy() when the view unmounts. Place the anchor inside a positioned container. The controller uses the browser’s manual Popover API, with a positioned fallback when that API is unavailable. It follows scrolling and resizing and keeps the surface within the viewport.

import { StatusFeedbackPopoverController } from '@revolist/revogrid-pro';
const activity = new StatusFeedbackPopoverController({
boundary: gridElement,
onChange: () => gridElement.refreshExtraElements(),
});
// In your grid overlay renderer:
h('div', {
ref: activity.anchorRef,
style: { position: 'absolute', right: '8px', bottom: '8px', width: '0', height: '0' },
},
renderStatusFeedbackPanel(h, { title: 'Sync activity', items, popover: activity }));

The disclosure button collapses the popup into a small bar showing its heading, count, and state icon. Expand it to see messages and actions again. Escape also collapses an expanded popup. Collapsing keeps requests running and preserves all messages. Focus moves to the disclosure button before its content is hidden. For an inline panel, supply collapsed and onCollapsedChange to control the same presentation without floating positioning. Customize the shadow with --rv-status-shadow.

Titles, item text, badges and action labels are supplied by your application. Use localeText for the panel’s own controls and count presentation:

<StatusFeedbackPanel
title="Atividade"
items={translatedItems}
popover={activity}
localeText={{
collapse: 'Recolher atividade',
expand: 'Expandir atividade',
countLabel: count => `${count} alterações`,
formatCount: count => new Intl.NumberFormat('pt-PT').format(count),
}}
/>

collapse and expand translate both the button tooltip and accessible name. countLabel supplies the accessible count label; formatCount formats its visible number. Existing collapseLabel and expandLabel props take precedence when supplied. Partial localeText overrides retain the default presentation.

Floating panels animate on entrance, exit, collapse and expansion. Motion lasts 140–180 ms and respects prefers-reduced-motion: reduce. Interrupted transitions are cancelled, and exit snapshots are inert and hidden from assistive technology. Destroying the popover controller removes outstanding animations and snapshots.