The frame for a model list section: a header over a scrolling content area that dims any item marked unavailable.
Model list
gpt-4o
claude-opus-4-5
gemini-2.5-pro
1
2
3'use client';
import { AiProviderIcon } from '@zeroxsolutions/icons/ai-provider-icon';Installation#
pnpm dlx shadcn@latest add https://ui.zeroxsolutions.com/r/model-list.jsonUsage#
import {
ModelList,
ModelListAction,
ModelListContent,
ModelListHeader,
ModelListRemoveButton,
ModelListTitle,
} from '@/components/layout/model-list';<ModelList>
<ModelListHeader>
<ModelListTitle>Model list</ModelListTitle>
<ModelListAction>
<span className="text-muted-foreground text-xs">3 models</span>
</ModelListAction>
</ModelListHeader>
<ModelListContent>
<ItemGroup>
<Item size="sm" data-unavailable={unavailable}>
<ItemMedia>
<AiProviderIcon provider="openai" />
</ItemMedia>
<ItemContent>
<ItemTitle>GPT-4o</ItemTitle>
<ItemDescription>gpt-4o</ItemDescription>
</ItemContent>
<ItemActions>
<Switch checked={enabled} disabled={unavailable} onCheckedChange={setEnabled} />
<ModelListRemoveButton onClick={remove} />
</ItemActions>
</Item>
</ItemGroup>
</ModelListContent>
</ModelList>It owns no list state: filtering, grouping, sorting and pagination are the caller's. Place it in a
height-constrained flex parent so ModelListContent scrolls, and swap in ModelListSkeleton for the item
group while the list loads.
Composition#
ModelList
|-- ModelListHeader
| |-- ModelListTitle
| `-- ModelListAction
`-- ModelListContent
`-- ItemGroup
`-- Item
|-- ItemMedia
|-- ItemContent
| |-- ItemTitle
| `-- ItemDescription
`-- ItemActions
|-- Switch
`-- ModelListRemoveButtonAPI reference#
ModelList#
Renders a div and takes every prop a div takes. The frame for a model list section: a ModelListHeader
over a scrolling ModelListContent. It owns no list state, so it does not filter, group, sort or paginate;
place it in a height-constrained flex parent so the content scrolls. It sets data-slot="model-list".
ModelListAction#
Renders a div and takes every prop a div takes. Trailing header controls, such as search or refresh. It
sets data-slot="model-list-action".
ModelListContent#
Renders shadcn's ScrollArea and takes every prop
it takes. The scrolling region filling the rest of the frame: item groups, an empty state or a
ModelListSkeleton, stacked. An Item inside it with data-unavailable={true} is dimmed from here, because
upstream Item has no disabled variant to carry it. It sets data-slot="model-list-content".
ModelListHeader#
Renders a div and takes every prop a div takes. The row above the list: a title and trailing controls; a
TabsList placed in it takes a line of its own. It sets data-slot="model-list-header".
ModelListRemoveButton#
Renders shadcn's Button and takes every prop it
takes. The ghost remove button for one model item, labelled "Remove model" unless an aria-label is given;
children replace its trash icon. It sets data-slot="model-list-remove-button".
ModelListSkeleton#
Renders a div and takes every prop a div takes, plus:
| Prop | Type | Default |
|---|---|---|
count | number | 6 |
Placeholder items shown while a model list loads, each a small Item in the shape of a model item: a media
placeholder, two text lines and a trailing control. It sets data-slot="model-list-skeleton", and each
placeholder row carries data-slot="model-list-skeleton-item".
ModelListTitle#
Renders an h3 and takes every prop an h3 takes. The section's heading, growing to push the header's
controls to its end. It sets data-slot="model-list-title".