fix(studio): keep infrastructure overview out of the viewport flex column

The compute form is a flex item of ProjectLayout's h-full main. In production that makes descendant height:100% resolve against the viewport, which next dev does not. Wrap the form in a block box, drop the flex PageSection around topology plus charts, and size the cards to their content.
This commit is contained in:
Danny White committed 2026-08-21 11:32:17 +10:00
1 parent bdcccc0eee
commit 32e7f5bfe2
3 files changed
+143 -139

No files matched your search

@@ -93,9 +93,7 @@ const PERCENTAGE_Y_AXIS_PROPS = {
const getUsageCardClassName = (status: UsageMetricStatus) =>
cn(
// flex-1 equalises the two cards inside the grid. Avoid h-full: it
// resolves against ProjectLayout's viewport-sized main in production.
'flex flex-1 flex-col min-h-0 transition-colors',
'flex flex-col transition-colors',
status === 'warning' && 'border-warning-400 bg-warning-200/30',
status === 'negative' && 'border-destructive-400 bg-destructive-200/30'
)
@@ -166,10 +164,10 @@ export const ComputeAndDiskUsageCharts = ({ className }: { className?: string })
className
)}
>
<div id="cpu" className="scroll-mt-24 min-h-0 flex flex-col">
<div id="cpu" className="scroll-mt-24 min-h-0">
<span id="ram" className="block h-0 scroll-mt-24" aria-hidden />
<span id="disk_io" className="block h-0 scroll-mt-24" aria-hidden />
<Chart isLoading={isLoading} isErrored={isError} className="flex flex-1 flex-col min-h-0">
<Chart isLoading={isLoading} isErrored={isError}>
<ChartCard className={getUsageCardClassName(computeUsageStatus)}>
<ChartHeader align="start" className="min-h-[5.5rem]">
<ChartMetric
@@ -247,8 +245,8 @@ export const ComputeAndDiskUsageCharts = ({ className }: { className?: string })
</Chart>
</div>
<div id="disk" className="scroll-mt-24 min-h-0 flex flex-col">
<Chart isLoading={isLoading} isErrored={isError} className="flex flex-1 flex-col min-h-0">
<div id="disk" className="scroll-mt-24 min-h-0">
<Chart isLoading={isLoading} isErrored={isError}>
<ChartCard className={getUsageCardClassName(diskUsageStatus)}>
<ChartHeader align="start" className="min-h-[5.5rem]">
<ChartMetric
@@ -453,145 +453,151 @@ export function DiskManagementForm({
return (
<Form {...form}>
<form id="disk-compute-form" onSubmit={form.handleSubmit(onSubmit)}>
<PageContainer size="default" className="pb-16">
<PageSection>
<PageSectionContent>
{/*
ProjectLayout's main is a viewport-tall flex column. If this form is a
direct flex item, production builds resolve descendant h-full / flex-1
against that main (next dev often does not). Keep a block wrapper so
height stays content-sized.
*/}
<div className="w-full">
<form id="disk-compute-form" onSubmit={form.handleSubmit(onSubmit)}>
<PageContainer size="default" className="pb-16">
<div className="pt-12">
{overviewExtra}
<ComputeAndDiskUsageCharts className={cn(overviewExtra && 'mt-6', chartsClassName)} />
</PageSectionContent>
</PageSection>
{(isProjectResizing ||
isProjectRequestingDiskChanges ||
(isEntitlementsLoaded && !isPlanUpgradeRequired && noPermissions)) && (
<div className="relative flex flex-col gap-10">
<DiskMangementRestartRequiredSection
visible={isProjectResizing}
title="Your project will now automatically restart."
description="Your project will be unavailable for up to 2 mins."
/>
<NoticeBar
type="default"
visible={isProjectRequestingDiskChanges}
title="Disk configuration changes have been requested"
description="The requested changes will be applied to your disk shortly"
/>
<NoticeBar
type="default"
visible={isEntitlementsLoaded && !isPlanUpgradeRequired && noPermissions}
title="You do not have permission to update disk configuration"
description="Please contact your organization administrator to update your disk configuration"
/>
</div>
)}
{beforeScaling}
<PageSection>
<PageSectionMeta>
<PageSectionSummary>
<PageSectionTitle>Scaling</PageSectionTitle>
</PageSectionSummary>
</PageSectionMeta>
{isEntitlementsLoaded && isPlanUpgradeRequired && (
<UpgradeToPro
featureProposition="configure compute and disk"
primaryText="Only available on Pro Plan and above"
secondaryText="Upgrade to the Pro Plan to configure compute and disk settings."
/>
)}
<PageSectionContent>
<ComputeSection
form={form}
settingsRef={computeSettingsRef}
showBillingBadge={showComputeBillingBadge}
beforePrice={Number(computeSizePrice.oldPrice)}
afterPrice={Number(computeSizePrice.newPrice)}
disabled={disableComputeInputs}
/>
<DiskSection
form={form}
settingsRef={diskSizeSettingsRef}
showBillingBadge={showDiskBillingBadge}
beforePrice={Number(diskSizePrice.oldPrice)}
afterPrice={Number(diskSizePrice.newPrice)}
isAws={isAws}
isAwsK8s={isAwsK8s}
isBranch={isBranch}
isNoticeVisible={isDiskNoticeVisible}
isReadOnlyMode={!!isReadOnlyMode}
usedPercentage={usedPercentage}
isWithinCooldownWindow={isWithinCooldownWindow}
currentDiskSizeGb={defaultValues.totalSize}
disableDiskSizeInput={disableDiskSizeInput}
/>
{isAws && (
<AdvancedSection
form={form}
autoscaleSettingsRef={autoscaleSettingsRef}
storageSettingsRef={storageSettingsRef}
showBillingBadge={showAdvancedBillingBadge}
beforePrice={advancedBeforePrice}
afterPrice={advancedAfterPrice}
disableIopsThroughputConfig={disableIopsThroughputConfig}
canUpdateDiskConfiguration={canUpdateDiskConfiguration}
isDiskTooSmallForCustomIops={isDiskTooSmallForCustomIops}
disableDiskInputs={disableDiskInputs}
disableDiskSizeInput={disableDiskSizeInput}
suggestedDiskSizeForCustomIops={suggestedDiskSizeForCustomIops}
{(isProjectResizing ||
isProjectRequestingDiskChanges ||
(isEntitlementsLoaded && !isPlanUpgradeRequired && noPermissions)) && (
<div className="relative flex flex-col gap-10">
<DiskMangementRestartRequiredSection
visible={isProjectResizing}
title="Your project will now automatically restart."
description="Your project will be unavailable for up to 2 mins."
/>
)}
</PageSectionContent>
</PageSection>
</PageContainer>
<AnimatePresence>
{isDirty ? (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 20 }}
transition={{ duration: 0.1, delay: 0.2 }}
className="z-10 w-full left-0 right-0 sticky bottom-0 bg-surface-100 border-t h-16 items-center flex"
>
<div
className={cn(
'mx-auto w-full max-w-[1200px]',
PADDING_CLASSES,
'flex items-center justify-end gap-3'
)}
>
<BillingChangeBadge
show={isDirty}
beforePrice={totalBeforePrice}
afterPrice={totalAfterPrice}
<NoticeBar
type="default"
visible={isProjectRequestingDiskChanges}
title="Disk configuration changes have been requested"
description="The requested changes will be applied to your disk shortly"
/>
<Button
variant="default"
onClick={() => form.reset()}
disabled={!isDirty}
size="medium"
>
Cancel
</Button>
<DiskManagementReviewAndSubmitDialog
loading={isUpdatingConfig}
disabled={noPermissions}
form={form}
numReplicas={readReplicas.length}
isDialogOpen={isDialogOpen}
onSubmit={onSubmit}
setIsDialogOpen={setIsDialogOpen}
message={message}
<NoticeBar
type="default"
visible={isEntitlementsLoaded && !isPlanUpgradeRequired && noPermissions}
title="You do not have permission to update disk configuration"
description="Please contact your organization administrator to update your disk configuration"
/>
</div>
</motion.div>
) : null}
</AnimatePresence>
</form>
)}
{beforeScaling}
<PageSection>
<PageSectionMeta>
<PageSectionSummary>
<PageSectionTitle>Scaling</PageSectionTitle>
</PageSectionSummary>
</PageSectionMeta>
{isEntitlementsLoaded && isPlanUpgradeRequired && (
<UpgradeToPro
featureProposition="configure compute and disk"
primaryText="Only available on Pro Plan and above"
secondaryText="Upgrade to the Pro Plan to configure compute and disk settings."
/>
)}
<PageSectionContent>
<ComputeSection
form={form}
settingsRef={computeSettingsRef}
showBillingBadge={showComputeBillingBadge}
beforePrice={Number(computeSizePrice.oldPrice)}
afterPrice={Number(computeSizePrice.newPrice)}
disabled={disableComputeInputs}
/>
<DiskSection
form={form}
settingsRef={diskSizeSettingsRef}
showBillingBadge={showDiskBillingBadge}
beforePrice={Number(diskSizePrice.oldPrice)}
afterPrice={Number(diskSizePrice.newPrice)}
isAws={isAws}
isAwsK8s={isAwsK8s}
isBranch={isBranch}
isNoticeVisible={isDiskNoticeVisible}
isReadOnlyMode={!!isReadOnlyMode}
usedPercentage={usedPercentage}
isWithinCooldownWindow={isWithinCooldownWindow}
currentDiskSizeGb={defaultValues.totalSize}
disableDiskSizeInput={disableDiskSizeInput}
/>
{isAws && (
<AdvancedSection
form={form}
autoscaleSettingsRef={autoscaleSettingsRef}
storageSettingsRef={storageSettingsRef}
showBillingBadge={showAdvancedBillingBadge}
beforePrice={advancedBeforePrice}
afterPrice={advancedAfterPrice}
disableIopsThroughputConfig={disableIopsThroughputConfig}
canUpdateDiskConfiguration={canUpdateDiskConfiguration}
isDiskTooSmallForCustomIops={isDiskTooSmallForCustomIops}
disableDiskInputs={disableDiskInputs}
disableDiskSizeInput={disableDiskSizeInput}
suggestedDiskSizeForCustomIops={suggestedDiskSizeForCustomIops}
/>
)}
</PageSectionContent>
</PageSection>
</PageContainer>
<AnimatePresence>
{isDirty ? (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 20 }}
transition={{ duration: 0.1, delay: 0.2 }}
className="z-10 w-full left-0 right-0 sticky bottom-0 bg-surface-100 border-t h-16 items-center flex"
>
<div
className={cn(
'mx-auto w-full max-w-[1200px]',
PADDING_CLASSES,
'flex items-center justify-end gap-3'
)}
>
<BillingChangeBadge
show={isDirty}
beforePrice={totalBeforePrice}
afterPrice={totalAfterPrice}
/>
<Button
variant="default"
onClick={() => form.reset()}
disabled={!isDirty}
size="medium"
>
Cancel
</Button>
<DiskManagementReviewAndSubmitDialog
loading={isUpdatingConfig}
disabled={noPermissions}
form={form}
numReplicas={readReplicas.length}
isDialogOpen={isDialogOpen}
onSubmit={onSubmit}
setIsDialogOpen={setIsDialogOpen}
message={message}
/>
</div>
</motion.div>
) : null}
</AnimatePresence>
</form>
</div>
</Form>
)
}
@@ -8,7 +8,7 @@ export const InfrastructureTopology = () => {
if (!infrastructureReadReplicas) return null
return (
<div className="w-full h-[400px] border border-muted rounded-md overflow-hidden flex flex-col relative">
<div className="w-full h-[400px] shrink-0 border border-muted rounded-md overflow-hidden relative">
<InstanceConfiguration />
</div>
)