authorgravatar for me@t3.ggTheo Browne <me@t3.gg> 2026-10-08 03:01:07-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-08 03:01:07-07:00
log5e2225671f705fcd33f1ea5591b79ba612fb6974
treed2fd8c06701ccf35d978660bd0b43b46538b968b
parent37eaf5d293ef83ce86d2ce9a1583792696c82bbc
signature Signed by PGP key B5690EEEBB952194

feat(web): Add provider button sits with the provider list (#17152)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

2 files changed, 34 insertions(+), 18 deletions(-)

apps/web/src/components/settings/ProviderSettingsPanel.tsx+29-17
......@@ -1154,6 +1154,25 @@ export function EnvironmentProviderSettings({
11541154 <SettingsSection
11551155 {...searchableSetting("providers")}
11561156 variant="plain"
1157 titleAction={
1158 !readOnly ? (
1159 <Tooltip>
1160 <TooltipTrigger
1161 render={
1162 <Button
1163 size="icon-xs"
1164 variant="ghost-muted"
1165 onClick={() => setIsAddInstanceDialogOpen(true)}
1166 aria-label="Add provider"
1167 >
1168 <PlusIcon />
1169 </Button>
1170 }
1171 />
1172 <TooltipPopup side="top">Add provider</TooltipPopup>
1173 </Tooltip>
1174 ) : null
1175 }
11571176 headerAction={
11581177 <div className="flex min-w-0 items-center gap-2">
11591178 <ProviderUpdatesAction />
......@@ -1181,23 +1200,6 @@ export function EnvironmentProviderSettings({
11811200 />
11821201 <TooltipPopup side="top">Refresh provider status</TooltipPopup>
11831202 </Tooltip>
1184 {!readOnly ? (
1185 <Tooltip>
1186 <TooltipTrigger
1187 render={
1188 <Button
1189 size="icon-xs"
1190 variant="ghost-muted"
1191 onClick={() => setIsAddInstanceDialogOpen(true)}
1192 aria-label="Add provider"
1193 >
1194 <PlusIcon />
1195 </Button>
1196 }
1197 />
1198 <TooltipPopup side="top">Add provider</TooltipPopup>
1199 </Tooltip>
1200 ) : null}
12011203 </div>
12021204 }
12031205 >
......@@ -1227,6 +1229,16 @@ export function EnvironmentProviderSettings({
12271229 >
12281230 <div className="divide-y divide-border/50">
12291231 {rows.map((row) => renderProviderInstance(row, "list"))}
1232 {!readOnly ? (
1233 <button
1234 type="button"
1235 className="flex w-full cursor-pointer items-center gap-3 px-3 py-3 text-left text-sm text-muted-foreground transition-colors outline-none hover:bg-muted/25 hover:text-foreground focus-visible:bg-muted/25 focus-visible:text-foreground sm:px-4"
1236 onClick={() => setIsAddInstanceDialogOpen(true)}
1237 >
1238 <PlusIcon className="size-4 shrink-0" />
1239 Add provider
1240 </button>
1241 ) : null}
12301242 </div>
12311243 </ScrollArea>
12321244 </div>
apps/web/src/components/settings/settingsLayout.tsx+5-1
......@@ -176,6 +176,7 @@ export function SettingsSection({
176176 title,
177177 hideTitle = false,
178178 icon,
179 titleAction,
179180 headerAction,
180181 variant = "grouped",
181182 children,
......@@ -185,6 +186,8 @@ export function SettingsSection({
185186 title: string;
186187 hideTitle?: boolean;
187188 icon?: ReactNode;
189 /** Small control shown right after the title, such as an add button. */
190 titleAction?: ReactNode;
188191 headerAction?: ReactNode;
189192 variant?: "grouped" | "plain";
190193 children: ReactNode;
......@@ -205,11 +208,12 @@ export function SettingsSection({
205208 data-settings-scroll-target
206209 className="flex min-h-7 items-start justify-between gap-4 px-3 sm:px-4"
207210 >
208 <div className="min-w-0">
211 <div className="flex min-w-0 items-center gap-1">
209212 <h2 className="flex min-h-7 items-center gap-2 text-sm font-normal text-foreground/70">
210213 {icon}
211214 {title}
212215 </h2>
216 {titleAction}
213217 </div>
214218 <div className="flex min-h-7 min-w-7 items-center justify-end">{headerAction}</div>
215219 </div>