mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(site/src/pages/AISettingsPage/ModelsPage): duplicate Add model dropdown in empty state (#26685)
Mirrors the providers page on `/ai/settings/providers`: when the models
table is empty on `/ai/settings/models`, the empty state now renders an
**Add model** dropdown alongside the description so users have an
obvious next step.
## Changes
- `AddModelDropdown` accepts an optional `align` prop (defaults to
`"end"`), so the existing header instance is unchanged.
- The empty state passes a second instance via `TableEmpty`'s `cta` prop
with `align="start"`, matching how `ProvidersPageView` duplicates
`AddProviderDropdown`.
- Updated the `Empty` Storybook story to assert two **Add model**
buttons render (header + empty state).
## Verification
- `pnpm --dir site exec biome check
src/pages/AISettingsPage/ModelsPage/`
- `pnpm --dir site exec tsc -p . --noEmit`
- `pnpm --dir site exec vitest run --project=storybook
src/pages/AISettingsPage/ModelsPage/` (20/20 stories pass, including the
updated `Empty` play)
<details>
<summary>Reference: providers page pattern</summary>
`ProvidersPageView.tsx` already does this with `AddProviderDropdown`:
```tsx
<TableEmpty
message="No providers configured"
cta={<AddProviderDropdown align="start" />}
/>
```
This PR brings the models page in line with that pattern.
</details>
---
> [!NOTE]
> Opened by Coder Agents on behalf of @tracyjohnsonux.
This commit is contained in:
@@ -65,6 +65,9 @@ export const Empty: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
await expect(canvas.getByText("No models configured")).toBeInTheDocument();
|
||||
await expect(
|
||||
canvas.getAllByRole("button", { name: /add model/i }).length,
|
||||
).toBe(2);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -35,9 +35,10 @@ import { ModelRow } from "./components/ModelRow";
|
||||
|
||||
const MODELS_PAGE_SIZE = 10;
|
||||
|
||||
const AddModelDropdown: FC<{ providerStates: readonly ProviderState[] }> = ({
|
||||
providerStates,
|
||||
}) => {
|
||||
const AddModelDropdown: FC<{
|
||||
providerStates: readonly ProviderState[];
|
||||
align?: "start" | "end";
|
||||
}> = ({ providerStates, align = "end" }) => {
|
||||
const navigate = useNavigate();
|
||||
const manageableProviderStates = providerStates.filter(
|
||||
canManageProviderModels,
|
||||
@@ -52,7 +53,7 @@ const AddModelDropdown: FC<{ providerStates: readonly ProviderState[] }> = ({
|
||||
<ChevronDownIcon className="ml-1 size-icon-xs" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="min-w-56">
|
||||
<DropdownMenuContent align={align} className="min-w-56">
|
||||
<div className="px-2 py-1.5 text-xs font-medium text-content-secondary">
|
||||
Select a provider
|
||||
</div>
|
||||
@@ -140,6 +141,12 @@ const ModelsPageView: FC<ModelsPageViewProps> = ({
|
||||
<TableEmpty
|
||||
message="No models configured"
|
||||
description="Configured models will appear here."
|
||||
cta={
|
||||
<AddModelDropdown
|
||||
providerStates={providerStates}
|
||||
align="start"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
pagedItems.map((model) => (
|
||||
|
||||
Reference in New Issue
Block a user