Next.js Bootstrap List Group
Next.js Bootstrap list group markup: static lists in server components, next/link items with the active route from usePathname, badges and cards.
List groups line up related items, such as messages, folders or the links of a settings page. The demo uses them in cards, in the navbar's message and notification menus, and in the settings navigation. You write them as Bootstrap's .list-group and .list-group-item markup in JSX, usually mapped from an array. There is no component to import. List groups work in the free and PRO versions of AdminKit for Next.js.
In the App Router, pages are server components: they render on the server and have no state. A list without state renders there with no "use client". A list that tracks a selected item, or highlights the current route with usePathname, needs state or a hook that runs in the browser. It goes in a client component, a file that starts with "use client".
Example
const tasks = [
{ id: 1, title: "Design review" },
{ id: 2, title: "Sprint planning" },
{ id: 3, title: "Release notes" },
];
<ul className="list-group">
{tasks.map((task) => (
<li key={task.id} className="list-group-item">
{task.title}
</li>
))}
</ul>The key is a stable value from the data, such as an id, so React matches items correctly when the list changes.
Classes
| Class | Effect |
|---|---|
list-group | The container: <ul>, <ol> or <div> |
list-group-item | An item |
list-group-item-action | Hover and focus styles for link and button items |
active, disabled | The selected or disabled item |
list-group-flush | Drops the outer borders and corners, for a list in a card |
list-group-numbered | CSS numbers on an <ol> |
list-group-horizontal | The items in a row; list-group-horizontal-md from a breakpoint |
list-group-item-<color> | An item in a theme color, such as list-group-item-success |
Selectable items
When the user picks an item, such as a folder, make each item a <button> with list-group-item-action. The selection is state, so the component is a client component:
"use client";
import { useState } from "react";
import { cx } from "@/lib/cx";
const folders = ["Inbox", "Sent", "Archive"];
export function FolderList() {
const [folder, setFolder] = useState("Inbox");
return (
<div className="list-group">
{folders.map((name) => (
<button
key={name}
type="button"
className={cx("list-group-item list-group-item-action", name === folder && "active")}
aria-current={name === folder ? "true" : undefined}
onClick={() => setFolder(name)}
>
{name}
</button>
))}
</div>
);
}Links to routes
For a list of links to other pages, render each item with next/link. A list of links without an active item stays a server component. To highlight the current page, read the route with usePathname. That hook runs in the browser, so the component needs "use client", as the sidebar does:
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { cx } from "@/lib/cx";
const sections = [
{ href: "/pages-settings", label: "Account" },
{ href: "/pages-profile", label: "Profile" },
];
export function SettingsNav() {
const pathname = usePathname();
return (
<div className="list-group list-group-flush">
{sections.map((section) => (
<Link
key={section.href}
href={section.href}
className={cx("list-group-item list-group-item-action", pathname === section.href && "active")}
aria-current={pathname === section.href ? "page" : undefined}
>
{section.label}
</Link>
))}
</div>
);
}a.list-group-item has no underline in AdminKit.
With badges
Put a count at the end of an item with a badge and the flex utilities.
<ul className="list-group">
{queues.map((queue) => (
<li
key={queue.id}
className="list-group-item d-flex justify-content-between align-items-center"
>
{queue.name}
<span className={`badge bg-${queue.color} rounded-pill`}>{queue.count}</span>
</li>
))}
</ul>In a card
A list inside a card needs no border of its own. With list-group-flush, the list runs edge to edge in a .card, as on the cards demo:
<div className="card">
<div className="card-header">
<h2 className="card-title mb-0">Recent activity</h2>
</div>
<ul className="list-group list-group-flush">
<li className="list-group-item">Invoice #1042 paid</li>
<li className="list-group-item">New client added</li>
<li className="list-group-item">Project archived</li>
</ul>
</div>Accessibility
- Mark the selected or current item with
aria-currentas well asactive. - Use
<button>items for actions, links for navigation, and no.btnclasses on list group items. - A checkbox in an item needs a
<label htmlFor>or anaria-label. - A disabled
<button>item takes thedisabledattribute. A disabled link needsaria-disabled="true"andtabIndex={-1}.
Related
- React Bootstrap list group: the same markup in AdminKit for React (Vite)
- Bootstrap 5 list group: the list group of the HTML version
- Cards: the container most list groups sit in
- Cards demo: a flush list group inside a card
Last updated on
Dropdowns
Next.js Bootstrap dropdown menus that server component pages can render as is: split buttons, alignment, auto close, keyboard support and next/link items.
Modal
A Next.js Bootstrap modal for the App Router: a client component opened from state in a server component page, with static, centered and fullscreen variants.