Skip to content

Commit 6ecd2cc

Browse files
committed
feat(webapp): tidy environment variables table layout
Adjust column widths and consolidate the "Updated" columns into a single cell to simplify the table header and row layout. Increase Key/Value/Environment header widths slightly to better match content when Vercel integration is enabled. Replace separate columns for version, updated-by, and updated-at with one "Updated" column that renders the actor (user avatar/name or Vercel integration) and the timestamp together. Also simplify the Actions header sizing to remove a tiny fixed width and use hiddenLabel with zero width, improving responsiveness. These changes clean up the table markup, reduce cluttered columns, and improve alignment and responsiveness of the environment variables list.
1 parent 738ce5c commit 6ecd2cc

File tree

2 files changed

+87
-49
lines changed

2 files changed

+87
-49
lines changed

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -316,13 +316,13 @@ export default function Page() {
316316
<Table containerClassName={cn(filteredItems.length === 0 && "border-t-0")}>
317317
<TableHeader>
318318
<TableRow>
319-
<TableHeaderCell className={vercelIntegration?.enabled ? "w-[21%]" : "w-[24%]"}>
319+
<TableHeaderCell className={vercelIntegration?.enabled ? "w-[22%]" : "w-[25%]"}>
320320
Key
321321
</TableHeaderCell>
322-
<TableHeaderCell className={vercelIntegration?.enabled ? "w-[30%]" : "w-[35%]"}>
322+
<TableHeaderCell className={vercelIntegration?.enabled ? "w-[32%]" : "w-[37%]"}>
323323
Value
324324
</TableHeaderCell>
325-
<TableHeaderCell className={vercelIntegration?.enabled ? "w-[12%]" : "w-[15%]"}>
325+
<TableHeaderCell className={vercelIntegration?.enabled ? "w-[13%]" : "w-[15%]"}>
326326
Environment
327327
</TableHeaderCell>
328328
{vercelIntegration?.enabled && (
@@ -338,10 +338,10 @@ export default function Page() {
338338
/>
339339
</TableHeaderCell>
340340
)}
341-
<TableHeaderCell className="w-[3%]">Ver</TableHeaderCell>
342-
<TableHeaderCell className="w-[15%]">Updated by</TableHeaderCell>
343-
<TableHeaderCell className="w-[14%]">Updated at</TableHeaderCell>
344-
<TableHeaderCell hiddenLabel className="w-[1%] min-w-[3rem]">
341+
<TableHeaderCell className={vercelIntegration?.enabled ? "w-[24%]" : "w-[22%]"}>
342+
Updated
343+
</TableHeaderCell>
344+
<TableHeaderCell hiddenLabel className="w-0">
345345
Actions
346346
</TableHeaderCell>
347347
</TableRow>
@@ -420,35 +420,34 @@ export default function Page() {
420420
</TableCell>
421421
)}
422422
<TableCell className={cn(cellClassName, borderedCellClassName)}>
423-
<span className="text-sm text-text-dimmed">{variable.version}</span>
424-
</TableCell>
425-
<TableCell className={cn(cellClassName, borderedCellClassName)}>
426-
{variable.updatedByUser ? (
427-
<div className="flex items-center gap-2">
428-
<UserAvatar
429-
avatarUrl={variable.updatedByUser.avatarUrl}
430-
name={variable.updatedByUser.name}
431-
className="size-5"
432-
/>
433-
<span className="text-sm">{variable.updatedByUser.name}</span>
434-
</div>
435-
) : variable.lastUpdatedBy?.type === "integration" ? (
436-
<div className="flex items-center gap-2">
437-
<VercelLogo className="size-4 text-text-dimmed group-hover/table-row:text-text-bright transition-colors" />
438-
<span className="text-sm text-text-dimmed group-hover/table-row:text-text-bright capitalize transition-colors">
439-
{variable.lastUpdatedBy.integration}
423+
<div className="flex items-center gap-3">
424+
{variable.updatedByUser ? (
425+
<div className="flex items-center gap-2">
426+
<UserAvatar
427+
avatarUrl={variable.updatedByUser.avatarUrl}
428+
name={variable.updatedByUser.name}
429+
className="size-5"
430+
/>
431+
<span className="text-sm">{variable.updatedByUser.name}</span>
432+
</div>
433+
) : (variable.lastUpdatedBy?.type === "integration" && variable.lastUpdatedBy?.integration === 'vercel' ) ? (
434+
<div className="flex items-center gap-2">
435+
<VercelLogo className="size-4 text-text-dimmed group-hover/table-row:text-text-bright transition-colors" />
436+
<span className="text-sm text-text-dimmed group-hover/table-row:text-text-bright capitalize transition-colors">
437+
{variable.lastUpdatedBy.integration}
438+
</span>
439+
</div>
440+
) : null}
441+
{variable.updatedAt ? (
442+
<span className="text-sm text-text-dimmed">
443+
<DateTime date={variable.updatedAt} includeSeconds={false} />
440444
</span>
441-
</div>
442-
) : null}
443-
</TableCell>
444-
<TableCell className={cn(cellClassName, borderedCellClassName)}>
445-
{variable.updatedAt ? (
446-
<DateTime date={variable.updatedAt} includeSeconds={false} />
447-
) : null}
445+
) : null}
446+
</div>
448447
</TableCell>
449448
<TableCellMenu
450449
isSticky
451-
className="w-[1%] min-w-[3rem] [&:has(.group-hover/table-row:block)]:w-auto"
450+
className="w-0 [&:has(.group-hover/table-row:block)]:w-auto"
452451
hiddenButtons={
453452
<>
454453
<EditEnvironmentVariablePanel
@@ -464,7 +463,7 @@ export default function Page() {
464463
})
465464
) : (
466465
<TableRow>
467-
<TableCell colSpan={vercelIntegration?.enabled ? 8 : 7}>
466+
<TableCell colSpan={vercelIntegration?.enabled ? 6 : 5}>
468467
{environmentVariables.length === 0 ? (
469468
<div className="flex flex-col items-center justify-center gap-y-4 py-8">
470469
<Header2>You haven't set any environment variables yet.</Header2>
@@ -535,7 +534,7 @@ function EditEnvironmentVariablePanel({
535534
<Dialog open={isOpen} onOpenChange={setIsOpen}>
536535
<DialogTrigger asChild>
537536
<Button variant="small-menu-item" LeadingIcon={PencilSquareIcon} fullWidth textAlignLeft>
538-
Edit
537+
539538
</Button>
540539
</DialogTrigger>
541540
<DialogContent>
@@ -631,7 +630,7 @@ function DeleteEnvironmentVariableButton({
631630
leadingIconClassName="text-rose-500 group-hover/button:text-text-bright transition-colors"
632631
className="ml-0.5 transition-colors group-hover/button:bg-error"
633632
>
634-
{isLoading ? "Deleting" : "Delete"}
633+
{isLoading ? "Deleting" : ""}
635634
</Button>
636635
</Form>
637636
);

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,7 @@ function VercelOnboardingModal({
12951295
// Env var sync state (for env-var-sync step - one-time sync)
12961296
const [syncEnvVarsMapping, setSyncEnvVarsMapping] = useState<SyncEnvVarsMapping>({});
12971297
const [expandedEnvVars, setExpandedEnvVars] = useState(false);
1298+
const [expandedSecretEnvVars, setExpandedSecretEnvVars] = useState(false);
12981299
const [projectSelectionError, setProjectSelectionError] = useState<string | null>(null);
12991300

13001301
// GitHub connection state (for github-connection step)
@@ -1876,8 +1877,8 @@ function VercelOnboardingModal({
18761877
/>
18771878
</div>
18781879

1879-
{/* Expandable env var list */}
1880-
{envVars.length > 0 && (
1880+
{/* Expandable syncable env var list */}
1881+
{syncableEnvVars.length > 0 && (
18811882
<div className="rounded border">
18821883
<button
18831884
type="button"
@@ -1896,7 +1897,7 @@ function VercelOnboardingModal({
18961897

18971898
{expandedEnvVars && (
18981899
<div className="max-h-64 overflow-y-auto border-t">
1899-
{envVars.map((envVar) => (
1900+
{syncableEnvVars.map((envVar) => (
19001901
<div
19011902
key={envVar.id}
19021903
className="flex items-center justify-between gap-2 border-b px-3 py-2 last:border-b-0"
@@ -1927,17 +1928,55 @@ function VercelOnboardingModal({
19271928
</span>
19281929
)}
19291930
</div>
1930-
{envVar.isSecret ? (
1931-
<span className="shrink-0 text-xs text-amber-400">Secret</span>
1932-
) : (
1933-
<Switch
1934-
variant="small"
1935-
checked={shouldSyncEnvVarForAnyEnvironment(syncEnvVarsMapping, envVar.key)}
1936-
onCheckedChange={(checked) =>
1937-
handleToggleEnvVar(envVar.key, checked)
1938-
}
1939-
/>
1940-
)}
1931+
<Switch
1932+
variant="small"
1933+
checked={shouldSyncEnvVarForAnyEnvironment(syncEnvVarsMapping, envVar.key)}
1934+
onCheckedChange={(checked) =>
1935+
handleToggleEnvVar(envVar.key, checked)
1936+
}
1937+
/>
1938+
</div>
1939+
))}
1940+
</div>
1941+
)}
1942+
</div>
1943+
)}
1944+
1945+
{/* Expandable secret env var list */}
1946+
{secretEnvVars.length > 0 && (
1947+
<div className="rounded border">
1948+
<button
1949+
type="button"
1950+
className="flex w-full items-center justify-between p-3 text-left"
1951+
onClick={() => setExpandedSecretEnvVars(!expandedSecretEnvVars)}
1952+
>
1953+
<span className="text-sm text-text-dimmed">
1954+
{secretEnvVars.length} secret {secretEnvVars.length === 1 ? "variable" : "variables"} (cannot be pulled)
1955+
</span>
1956+
{expandedSecretEnvVars ? (
1957+
<ChevronUpIcon className="size-4" />
1958+
) : (
1959+
<ChevronDownIcon className="size-4" />
1960+
)}
1961+
</button>
1962+
1963+
{expandedSecretEnvVars && (
1964+
<div className="max-h-64 overflow-y-auto border-t">
1965+
{secretEnvVars.map((envVar) => (
1966+
<div
1967+
key={envVar.id}
1968+
className="flex items-center justify-between gap-2 border-b px-3 py-2 last:border-b-0"
1969+
>
1970+
<div className="flex min-w-0 flex-1 flex-col gap-0.5">
1971+
<span className="truncate font-mono text-xs">{envVar.key}</span>
1972+
{envVar.target && envVar.target.length > 0 && (
1973+
<span className="text-xs text-text-dimmed">
1974+
{formatVercelTargets(envVar.target)}
1975+
{envVar.isShared && " · Shared"}
1976+
</span>
1977+
)}
1978+
</div>
1979+
<span className="shrink-0 text-xs text-amber-400">Secret</span>
19411980
</div>
19421981
))}
19431982
</div>

0 commit comments

Comments
 (0)