React Bootstrap Buttons
React Bootstrap button markup in AdminKit: theme and outline colors, sizes, icon buttons, toggle buttons and a loading state driven by React state.
Buttons are how people act on a page: save a form, open a dialog, start an export. In AdminKit for React a button is Bootstrap's .btn classes on a <button> or a link.
There is no Button component to import. You write the markup in JSX with className, and set attributes such as disabled and aria-pressed from React state. Buttons are part of the free and PRO versions.
Example
<button type="button" className="btn btn-primary me-2 mb-2">Primary</button>
<button type="button" className="btn btn-secondary me-2 mb-2">Secondary</button>
<button type="button" className="btn btn-success me-2 mb-2">Success</button>
<button type="button" className="btn btn-danger me-2 mb-2">Danger</button>
<button type="button" className="btn btn-warning me-2 mb-2">Warning</button>
<button type="button" className="btn btn-info me-2 mb-2">Info</button>
<button type="button" className="btn btn-light me-2 mb-2">Light</button>
<button type="button" className="btn btn-dark me-2 mb-2">Dark</button>
<button type="button" className="btn btn-link me-2 mb-2">Link</button>JSX drops the line breaks between inline elements, so the buttons above are spaced with me-2. The buttons demo renders its rows from a list of colors instead, and puts a {" "} after each button to keep the gap:
import { Fragment } from "react";
const colors = ["primary", "secondary", "success", "danger", "warning", "info"];
export function ColorButtons() {
return (
<div className="mb-3">
{colors.map((color) => (
<Fragment key={color}>
<button type="button" className={`btn btn-${color}`}>
{color}
</button>{" "}
</Fragment>
))}
</div>
);
}Classes
| Class | Effect |
|---|---|
btn | The base class, needed on every button |
btn-primary, btn-secondary, btn-success, btn-danger, btn-warning, btn-info, btn-light, btn-dark | A filled button in a theme color |
btn-outline-<color> | The border and text in the color, filled on hover |
btn-link | A button that looks like a link |
btn-sm, btn-lg | A smaller or larger button |
btn-facebook, btn-twitter, btn-google, btn-github, ... | Brand colors, one per entry of $social-colors in src/scss/1-variables/_app.scss |
active | The pressed look of a toggle button |
The styles are Bootstrap's, extended in src/scss/3-components/_buttons.scss. AdminKit gives .btn-warning dark text, because white text does not reach a 4.5:1 contrast on it. The brand colors are darkened where white text does not reach 4.5:1 either.
Outline buttons and sizes
An outline button is quieter than a filled one, which suits a second action next to the main one. Add btn-sm or btn-lg to change the size.
<button type="button" className="btn btn-outline-primary me-2 mb-2">Primary</button>
<button type="button" className="btn btn-outline-secondary me-2 mb-2">Secondary</button>
<button type="button" className="btn btn-outline-success me-2 mb-2">Success</button>
<button type="button" className="btn btn-primary btn-sm me-2">Small</button>
<button type="button" className="btn btn-primary me-2">Medium</button>
<button type="button" className="btn btn-primary btn-lg">Large</button>Loading state
When a click starts a request, the user should see that something is happening and should not click twice. A loading button disables itself and changes its label until the request is done. In JSX, disabled is a boolean prop, so pass it the state:
The spinner in this button is only available in AdminKit PRO.
import { useState } from "react";
export function SaveButton() {
const [saving, setSaving] = useState(false);
async function save() {
setSaving(true);
try {
await fetch("/api/settings", { method: "POST" });
} finally {
setSaving(false);
}
}
return (
<button type="button" className="btn btn-primary" disabled={saving} onClick={save}>
{saving && <span className="spinner-border spinner-border-sm me-2" aria-hidden="true" />}
{saving ? "Saving..." : "Save changes"}
</button>
);
}See Spinners for the other spinner styles.
Toggle buttons
Use a toggle button for something the user turns on and off, such as pinning an item. The button keeps its pressed state in React. Add active to the class and set aria-pressed from the same state. cx from @/lib/cx joins the class names that are true:
import { useState } from "react";
import { cx } from "@/lib/cx";
export function PinButton() {
const [pinned, setPinned] = useState(false);
return (
<button
type="button"
className={cx("btn btn-outline-primary", pinned && "active")}
aria-pressed={pinned}
onClick={() => setPinned(!pinned)}
>
{pinned ? "Pinned" : "Pin to dashboard"}
</button>
);
}Icons and links
Put an icon next to the label, or use it alone for a compact button. Lucide icons from lucide-react render as an svg with the lucide class. Inside a .btn they are 14px. A button with only an icon needs an aria-label, so screen readers can name it:
import { Download, Trash } from "lucide-react";
<button type="button" className="btn btn-primary me-2">
<Download /> Export
</button>
<button type="button" className="btn btn-danger" aria-label="Delete">
<Trash />
</button>A button that takes the user to another page is really a link. Give the .btn classes to React Router's Link, not to a <button> with an onClick that navigates:
import { Link } from "react-router";
<Link to="/pages-projects" className="btn btn-primary">
View projects
</Link>Rounded and square buttons
These classes are only available in AdminKit PRO.
Change the corners when a button should look softer or sharper than the rest. btn-pill rounds the ends of a button. btn-square removes its border radius.
<button type="button" className="btn btn-pill btn-primary me-2">Rounded</button>
<button type="button" className="btn btn-square btn-primary">Square</button>Accessibility
- Give every
<button>atype. Without it, a button in a form submits the form. - An icon-only button needs an
aria-label, as in the buttons demo. - A toggle button sets
aria-pressedfrom its state, so screen readers announce it as pressed or not. - While a button is loading, keep a visible text such as "Saving..." and hide the spinner with
aria-hidden="true". - For a disabled link, prefer a
<button disabled>: a link with.disabledstill needsaria-disabled="true"andtabIndex={-1}.
Related
- Next.js Bootstrap buttons: the same markup in AdminKit for Next.js
- Bootstrap 5 buttons: the buttons of the HTML version
- Button group: buttons joined in a group or a toolbar
- Buttons demo
Last updated on
Badge
React Bootstrap badge markup for AdminKit: theme and light colors, pill badges, counters in buttons and a status badge picked from your data.
Button group
A React Bootstrap button group in AdminKit: joined buttons, toolbars, sizes, vertical groups and a radio group that keeps its value in React state.