authorgravatar for admin@snappeh.comTristan Knight <admin@snappeh.com> 2026-09-16 21:39:46+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-16 17:39:46-03:00
log384de0858d1f59ca2ad7c660544a5290fd9138cb
tree97b855bf0e26d2a71a0cd43ee81459f198495598
parentd1a644897119300688cbd8bf26e0b64aeb92c382
signature Signed by PGP key B5690EEEBB952194

fix(web): adapt provider settings to available content width (#12138)


4 files changed, 25 insertions(+), 17 deletions(-)

apps/web/src/components/settings/ProviderInstanceCard.tsx+2-2
...@@ -817,7 +817,7 @@ export function ProviderInstanceCard({...@@ -817,7 +817,7 @@ export function ProviderInstanceCard({
817 inert={readOnly}817 inert={readOnly}
818 aria-disabled={readOnly || undefined}818 aria-disabled={readOnly || undefined}
819 className={cn(819 className={cn(
820 "flex w-full items-center justify-end gap-2 sm:w-auto",820 "flex w-full min-w-0 items-center justify-end gap-2 @min-[32rem]/settings-row:w-auto",
821 readOnly && "opacity-50 select-none",821 readOnly && "opacity-50 select-none",
822 )}822 )}
823 >823 >
...@@ -831,7 +831,7 @@ export function ProviderInstanceCard({...@@ -831,7 +831,7 @@ export function ProviderInstanceCard({
831 <DraftInput831 <DraftInput
832 id={`provider-instance-${instanceId}-display-name`}832 id={`provider-instance-${instanceId}-display-name`}
833 size="sm"833 size="sm"
834 className="min-w-0 flex-1 sm:w-56 sm:flex-none"834 className="min-w-0 flex-1 @min-[32rem]/settings-row:w-56"
835 value={instance.displayName ?? ""}835 value={instance.displayName ?? ""}
836 onCommit={updateDisplayName}836 onCommit={updateDisplayName}
837 placeholder={driverOption?.label ?? "Instance label"}837 placeholder={driverOption?.label ?? "Instance label"}
apps/web/src/components/settings/ProviderSettingsForm.tsx+3-3
...@@ -265,14 +265,14 @@ function ProviderSettingsFieldRow({...@@ -265,14 +265,14 @@ function ProviderSettingsFieldRow({
265 value={value}265 value={value}
266 inputId={inputId}266 inputId={inputId}
267 size="sm"267 size="sm"
268 className="w-full sm:w-56"268 className="w-full max-w-full @min-[32rem]/settings-row:w-56"
269 onChange={onChange}269 onChange={onChange}
270 />270 />
271 ) : field.control === "textarea" ? (271 ) : field.control === "textarea" ? (
272 <Textarea272 <Textarea
273 id={inputId}273 id={inputId}
274 aria-describedby={descriptionId}274 aria-describedby={descriptionId}
275 className="w-full sm:w-96"275 className="w-full max-w-full @min-[32rem]/settings-row:w-[min(24rem,50cqw)]"
276 value={readProviderConfigString(value, field.key)}276 value={readProviderConfigString(value, field.key)}
277 onChange={(event) =>277 onChange={(event) =>
278 onChange(nextProviderConfigWithFieldValue(value, field, event.target.value))278 onChange(nextProviderConfigWithFieldValue(value, field, event.target.value))
...@@ -285,7 +285,7 @@ function ProviderSettingsFieldRow({...@@ -285,7 +285,7 @@ function ProviderSettingsFieldRow({
285 id={inputId}285 id={inputId}
286 aria-describedby={descriptionId}286 aria-describedby={descriptionId}
287 size="sm"287 size="sm"
288 className="w-full sm:w-56"288 className="w-full max-w-full @min-[32rem]/settings-row:w-56"
289 type={field.control === "password" ? "password" : undefined}289 type={field.control === "password" ? "password" : undefined}
290 autoComplete={field.control === "password" ? "off" : undefined}290 autoComplete={field.control === "password" ? "off" : undefined}
291 value={readProviderConfigString(value, field.key)}291 value={readProviderConfigString(value, field.key)}
apps/web/src/components/settings/ProviderSettingsPanel.tsx+12-7
...@@ -174,7 +174,8 @@ function providerEnvironmentDetail(environment: EnvironmentPresentation): string...@@ -174,7 +174,8 @@ function providerEnvironmentDetail(environment: EnvironmentPresentation): string
174const providerCardClassName = "rounded-xl border border-border/60 bg-card/40 shadow-xs/5";174const providerCardClassName = "rounded-xl border border-border/60 bg-card/40 shadow-xs/5";
175// Shared by the editor grid and the placeholder states so switching devices175// Shared by the editor grid and the placeholder states so switching devices
176// never changes the card's footprint.176// never changes the card's footprint.
177const providerCardHeightClassName = "lg:h-[min(44rem,calc(100dvh-11rem))] lg:min-h-[32rem]";177const providerCardHeightClassName =
178 "@min-[48rem]/providers:h-[min(44rem,calc(100dvh-11rem))] @min-[48rem]/providers:min-h-[32rem]";
178179
179/**180/**
180 * Same chrome as the provider editor (section heading, floating device tabs,181 * Same chrome as the provider editor (section heading, floating device tabs,
...@@ -271,7 +272,7 @@ interface ProviderSettingsTarget {...@@ -271,7 +272,7 @@ interface ProviderSettingsTarget {
271272
272export function ProviderSettingsPanel(target: ProviderSettingsTarget) {273export function ProviderSettingsPanel(target: ProviderSettingsTarget) {
273 return (274 return (
274 <SettingsPageContainer width="wide" className="gap-8">275 <SettingsPageContainer width="wide" className="@container/providers gap-8">
275 <ProviderSettingsPanelContent276 <ProviderSettingsPanelContent
276 key={`${target.environmentId ?? ""}:${target.instanceId ?? ""}`}277 key={`${target.environmentId ?? ""}:${target.instanceId ?? ""}`}
277 {...target}278 {...target}
...@@ -1054,20 +1055,24 @@ export function EnvironmentProviderSettings({...@@ -1054,20 +1055,24 @@ export function EnvironmentProviderSettings({
1054 className={cn(1055 className={cn(
1055 providerCardClassName,1056 providerCardClassName,
1056 providerCardHeightClassName,1057 providerCardHeightClassName,
1057 "overflow-hidden lg:grid lg:grid-cols-[17rem_minmax(0,1fr)]",1058 "overflow-hidden @min-[48rem]/providers:grid @min-[48rem]/providers:grid-cols-[17rem_minmax(0,1fr)]",
1058 )}1059 )}
1059 >1060 >
1060 <div className="border-b border-border/60 bg-muted/10 lg:flex lg:min-h-0 lg:flex-col lg:border-r lg:border-b-0">1061 <div className="border-b border-border/60 bg-muted/10 @min-[48rem]/providers:flex @min-[48rem]/providers:min-h-0 @min-[48rem]/providers:flex-col @min-[48rem]/providers:border-r @min-[48rem]/providers:border-b-0">
1061 <ScrollArea scrollFade chainVerticalScroll className="lg:min-h-0 lg:flex-1">1062 <ScrollArea
1063 scrollFade
1064 chainVerticalScroll
1065 className="@min-[48rem]/providers:min-h-0 @min-[48rem]/providers:flex-1"
1066 >
1062 <div className="divide-y divide-border/50">1067 <div className="divide-y divide-border/50">
1063 {rows.map((row) => renderProviderInstance(row, "list"))}1068 {rows.map((row) => renderProviderInstance(row, "list"))}
1064 </div>1069 </div>
1065 </ScrollArea>1070 </ScrollArea>
1066 </div>1071 </div>
10671072
1068 <div className="min-w-0 lg:min-h-0">1073 <div className="min-w-0 @min-[48rem]/providers:min-h-0">
1069 {selectedRow ? (1074 {selectedRow ? (
1070 <ScrollArea scrollFade chainVerticalScroll className="lg:h-full">1075 <ScrollArea scrollFade chainVerticalScroll className="@min-[48rem]/providers:h-full">
1071 <div className="space-y-6 p-4">{renderProviderInstance(selectedRow, "editor")}</div>1076 <div className="space-y-6 p-4">{renderProviderInstance(selectedRow, "editor")}</div>
1072 </ScrollArea>1077 </ScrollArea>
1073 ) : (1078 ) : (
apps/web/src/components/settings/settingsLayout.tsx+8-5
...@@ -368,11 +368,14 @@ export function SettingsRow({...@@ -368,11 +368,14 @@ export function SettingsRow({
368 // Focusable so keyboard users can still reach the explanation.368 // Focusable so keyboard users can still reach the explanation.
369 <span369 <span
370 tabIndex={0}370 tabIndex={0}
371 className="flex w-full items-center rounded-md outline-none focus-visible:ring-2 focus-visible:ring-ring sm:w-auto"371 className="flex w-full items-center rounded-md outline-none focus-visible:ring-2 focus-visible:ring-ring @min-[32rem]/settings-row:w-auto"
372 />372 />
373 }373 }
374 >374 >
375 <div inert className="flex w-full items-center gap-2 opacity-50 sm:w-auto">375 <div
376 inert
377 className="flex w-full items-center gap-2 opacity-50 @min-[32rem]/settings-row:w-auto"
378 >
376 {control}379 {control}
377 </div>380 </div>
378 </TooltipTrigger>381 </TooltipTrigger>
...@@ -437,12 +440,12 @@ export function SettingsRow({...@@ -437,12 +440,12 @@ export function SettingsRow({
437 tabIndex={rowProps.id ? -1 : rowProps.tabIndex}440 tabIndex={rowProps.id ? -1 : rowProps.tabIndex}
438 data-slot="settings-row"441 data-slot="settings-row"
439 className={cn(442 className={cn(
440 "rounded-xl px-3 sm:px-4 aria-disabled:opacity-50 aria-disabled:[&_*]:text-muted-foreground",443 "@container/settings-row rounded-xl px-3 sm:px-4 aria-disabled:opacity-50 aria-disabled:[&_*]:text-muted-foreground",
441 children ? "pt-3 pb-1" : "py-3",444 children ? "pt-3 pb-1" : "py-3",
442 className,445 className,
443 )}446 )}
444 >447 >
445 <div className="flex flex-col gap-3 sm:grid sm:grid-cols-[minmax(0,1fr)_minmax(10rem,auto)] sm:items-center sm:gap-8">448 <div className="flex flex-col gap-3 @min-[32rem]/settings-row:grid @min-[32rem]/settings-row:grid-cols-[minmax(0,1fr)_minmax(10rem,auto)] @min-[32rem]/settings-row:items-center @min-[32rem]/settings-row:gap-8">
446 <div className="min-w-0 flex-1 space-y-1">449 <div className="min-w-0 flex-1 space-y-1">
447 <div className="flex min-h-5 items-center gap-1.5">450 <div className="flex min-h-5 items-center gap-1.5">
448 <h3 className="text-sm font-medium tracking-[-0.005em] text-foreground">{title}</h3>451 <h3 className="text-sm font-medium tracking-[-0.005em] text-foreground">{title}</h3>
...@@ -465,7 +468,7 @@ export function SettingsRow({...@@ -465,7 +468,7 @@ export function SettingsRow({
465 ) : null}468 ) : null}
466 </div>469 </div>
467 {renderedControl ? (470 {renderedControl ? (
468 <div className="flex w-full shrink-0 items-center gap-2 sm:w-auto sm:justify-end">471 <div className="flex w-full min-w-0 shrink-0 items-center gap-2 @min-[32rem]/settings-row:w-auto @min-[32rem]/settings-row:justify-end">
469 {renderedControl}472 {renderedControl}
470 </div>473 </div>
471 ) : null}474 ) : null}