LoadingButton
16px progress ring with a cross in the middle, for cancelling what it is measuring. It is the marker the portal puts next to a row while that row's file is uploading.
Use this when / not when
- Use next to one item whose operation is running and can be cancelled: a row in an upload list, a file being converted.
- Not for the progress of the whole screen —
ProgressBaris the bar, andFloatingButtonis the corner badge. - Not for "something is loading" with no number behind it;
Loaderis the plain spinner. - Not as a button with a label: this one is 16px square and has no text of its own.
Import
import { LoadingButton } from "@onlyoffice/apps-ui-kit/components/loading-button";
Also exported from the root barrel @onlyoffice/apps-ui-kit.
Needs ThemeProvider from @onlyoffice/apps-ui-kit/providers/theme, which supplies the accent
colour the ring is drawn in.
Stories
Default
The ring as it first appears, before any progress is known: at the default percent of 0 a half ring spins. Change the percentage, drop the cross or pick colours live in the Controls panel below.
Progress Stages
Five rings labelled with their percent, to show how far the arc reaches at each stage: at 0% a half ring spins, the look for an operation whose size is not known yet, and from 25% on the arc grows clockwise until it closes at 100%.
In Conversion
The same rings with no cross in the middle (inConversion), for a marker that shows progress and nothing else: at 0% the ring spins, at 50% it is half filled, at 100% it is closed.
Default Mode
The ring and the cross in the theme's grey instead of the accent colour (isDefaultMode), for an item that is waiting rather than running. Hover the ring to see the cross change colour.
Custom Colors
Colours set per instance, for a ring that has to match its surroundings rather than the theme: the first three change the ring and the cross (loaderColor), the last also tints the disc behind the cross (backgroundColor).
Css Customization
Every overridable variable set on one wrapper -- the variables are listed under CSS variables on this page. The first ring shows the accent and the disc colours; the second sets isDefaultMode to show the idle colour, and hovering it shows the hover colour.
Minimal example
The ring has to sit in a positioned box of its own — see "Behaviour the types don't state".
import { LoadingButton } from "@onlyoffice/apps-ui-kit/components/loading-button";
export function UploadProgress({
percent,
onCancel,
}: {
percent: number;
onCancel: () => void;
}) {
return (
<div style={{ position: "relative", width: 16, height: 16 }}>
<LoadingButton percent={percent} onClick={onCancel} />
</div>
);
}
Props
Recipes
Indeterminate
Leaving percent at its default of 0 spins the ring instead of filling it, which is the look
for an operation whose size is not known yet.
import { LoadingButton } from "@onlyoffice/apps-ui-kit/components/loading-button";
export function Converting({ onCancel }: { onCancel: () => void }) {
return (
<div style={{ position: "relative", width: 16, height: 16 }}>
<LoadingButton inConversion onClick={onCancel} />
</div>
);
}
Idle
isDefaultMode draws the ring in grey rather than the accent colour and lightens the cross on
hover — the look for a row that is queued rather than running.
import { LoadingButton } from "@onlyoffice/apps-ui-kit/components/loading-button";
export function Queued({ onRemove }: { onRemove: () => void }) {
return (
<div style={{ position: "relative", width: 16, height: 16 }}>
<LoadingButton isDefaultMode onClick={onRemove} />
</div>
);
}
Colours of its own
loaderColor recolours the ring and the cross, and backgroundColor the disc behind the
cross, for a ring that has to match its surroundings rather than the theme.
import { LoadingButton } from "@onlyoffice/apps-ui-kit/components/loading-button";
export function Exporting({
percent,
onCancel,
}: {
percent: number;
onCancel: () => void;
}) {
return (
<div style={{ position: "relative", width: 16, height: 16 }}>
<LoadingButton
percent={percent}
loaderColor="var(--export-colour)"
backgroundColor="var(--export-surface)"
onClick={onCancel}
/>
</div>
);
}
Behaviour the types don't state
- Every part of the ring is
position: absoluteand the component positions nothing itself. The outer element is a plain 16×16<div>with noposition, so the mask, the fill and the cross are laid out against whatever positioned ancestor happens to be above them. Wrap it in aposition: relativebox of 16×16, or it will be drawn somewhere else entirely. id,classNameandstyleare ignored. They are declared, never read and not even spread onto the element, so there is no way to hook a class onto it — use the custom properties below.percentis a number from 0 to 100 and is turned intopercent × 1.8degof arc on each half of the ring, so the fill grows clockwise from a quarter at 25 to a closed circle at 100. At0the arc rule is replaced by a half ring rotating endlessly, which is why a ring that never receives a percentage looks like a spinner.inConversiononly removes the cross. It is drawn as an unbroken ring; whether it spins still depends onpercentbeing0.- The whole 16px square is clickable, not just the cross, and
onClickreceives no arguments. There is no disabled state: if the operation cannot be cancelled, do not render the component. - A five-second timer runs on mount and flips the internal animation flag, then restarts itself once. It has no visible effect in the states described above; there is nothing to configure and nothing to clean up.
- The component brings no margin and no label. It is 16×16 with a 12px disc inside it, and the cross is drawn in the ring's own colour on a disc that is white in the light theme and black in the dark one.
CSS variables
Set them on any ancestor.
loaderColor and backgroundColor are written as inline custom properties, so they win over
--loading-button-accent and --loading-button-custom-bg respectively. loaderColor does
nothing under isDefaultMode: that mode reads --loading-button-idle and
--loading-button-hover-fill only.
Accessibility
- The component is a
<div>with a click handler: no role, notabIndex, no key handler and no accessible name. It cannot be reached or activated from the keyboard, and nothing announces what it is or what cancelling it would do. - The progress is conveyed only by the arc. There is no
role="progressbar"and noaria-valuenow, so the percentage is invisible to assistive technology. - Give the cancel action a real control elsewhere in the row, or wrap this one in a
Buttonwith a label.
Test ids
It cannot be overridden by a prop.
Related
FloatingButton— the same idea at the size of a corner badge.Loader— a spinner with no progress behind it.ProgressBar— the linear form of the same number.