Files
supabase/apps/studio/components/interfaces/ProjectCreation/ComputeSizeSelector.tsx
T
Alaister YoungandAlaister Young caceeb429f [MUL-1336] fix(studio): show HA project costs as free during Alpha (#49383)
HA (Multigres) projects are free during Alpha, but the project creation
form still presented the forced large compute as a real charge. The
footer now shows **$0/m** for HA projects, with the usual compute price
struck through + a "Free during Alpha" note in the cost-breakdown
tooltip and the compute size dropdown. Follows the pattern from #49249.

Addresses
[MUL-1336](https://linear.app/supabase/issue/MUL-1336/bug-when-creating-new-projects).

<img width="688" height="167" alt="Screenshot 2026-08-21 at 5 27 39 PM"
src="https://github.com/user-attachments/assets/804b9243-77ae-4961-9083-5e1290734d3a"
/>
<img width="503" height="202" alt="Screenshot 2026-08-21 at 5 27 32 PM"
src="https://github.com/user-attachments/assets/f217edd4-2204-4e5e-87f8-f54974e3c6fa"
/>

**Changed:**
- `ProjectCreationFooter`: "Additional costs" shows `$0/m` when HA is
on; the tooltip gains a "High availability projects are free during
Alpha for up to 2 projects." sentence; the New-project row's price
renders struck through with a "Free during Alpha" sub-line; the HA
project's compute is excluded from "Total Monthly Compute Costs"
(clamped at 0 so credits can't produce a negative total — a no-op for
non-HA since spend already floors above zero)
- `ComputeSizeSelector`: the per-option `$X/hour (~$Y/month)` line
renders struck through with "Free during Alpha" beneath it when HA is on
(both tagged `data-field="instance-details"` so the collapsed trigger
keeps hiding them)
- `ProjectCreationForm`: threads the watched `highAvailability` value
into the footer

The "Confirm compute costs" modal was already suppressed for HA by the
existing `!values.highAvailability` guard — no change needed there.

## To test

- On a paid org, open New Project and toggle High Availability on: the
footer should read `$0/m` (brand green, no strikethrough), its ⓘ tooltip
should show the HA sentence and the New row's `$110` struck through with
"Free during Alpha", and the Total should exclude the $110; the compute
dropdown's Large option should show its price struck through with "Free
during Alpha"
- Toggle HA off (and on/off a few times): all cost displays should
revert exactly to normal — green real price, no strikethrough, no "Free
during Alpha" anywhere outside the HA toggle's own description
- With HA off and compute size Medium, submit: the "Confirm compute
costs" modal should still appear as before (Cancel works)
- Collapsed compute-size trigger should never show a price line or "Free
during Alpha" in either state

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## New Features

- High-availability project options now show compute pricing as free
during Alpha.
- Standard compute prices are displayed with a strikethrough alongside
the Alpha-free notice.
- Project cost summaries accurately show no additional compute charge
for high-availability selections.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-08-24 16:10:14 +08:00

134 lines
4.9 KiB
TypeScript

import { useMemo } from 'react'
import { UseFormReturn } from 'react-hook-form'
import { CloudProvider } from 'shared-data'
import {
cn,
FormField,
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
useWatch,
} from 'ui'
import { ComputeBadge } from 'ui-patterns/ComputeBadge'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import { HIGH_AVAILABILITY_INSTANCE_SIZE, sizes } from './ProjectCreation.constants'
import { CreateProjectForm } from './ProjectCreation.schema'
import { InlineLink } from '@/components/ui/InlineLink'
import Panel from '@/components/ui/Panel'
import { instanceSizeSpecs } from '@/data/projects/new-project.constants'
import { DOCS_URL } from '@/lib/constants'
interface ComputeSizeSelectorProps {
form: UseFormReturn<CreateProjectForm>
}
export const ComputeSizeSelector = ({ form }: ComputeSizeSelectorProps) => {
const cloudProvider = useWatch({ control: form.control, name: 'cloudProvider' }) as CloudProvider
const highAvailability = useWatch({ control: form.control, name: 'highAvailability' })
const sizeOptions = useMemo(
() =>
highAvailability
? [HIGH_AVAILABILITY_INSTANCE_SIZE]
: sizes.filter((option) =>
instanceSizeSpecs[option].cloud_providers.includes(cloudProvider)
),
[highAvailability, cloudProvider]
)
return (
<Panel.Content>
<FormField
control={form.control}
name="instanceSize"
render={({ field }) => (
<FormItemLayout
id="instanceSize"
layout="horizontal"
label="Compute size"
description={
<p>
The size for your dedicated database. You can change this later. Learn more about{' '}
<InlineLink href={`${DOCS_URL}/guides/platform/compute-add-ons`}>
compute add-ons
</InlineLink>{' '}
and{' '}
<InlineLink href={`${DOCS_URL}/guides/platform/manage-your-usage/compute`}>
compute billing
</InlineLink>
.
</p>
}
>
<Select
value={field.value}
onValueChange={(value) => value !== '' && field.onChange(value)}
>
<SelectTrigger
id="instanceSize"
className="[&>span>div>div>[data-field=instance-details]]:hidden"
>
<SelectValue placeholder="Select a compute size" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
{sizeOptions.map((option) => {
return (
<SelectItem key={option} value={option}>
<div className="flex flex-row gap-4 items-center">
<div className="w-14 flex items-center">
<ComputeBadge infraComputeSize={option} />
</div>
<div className="text-sm">
<span className="text-foreground">
{instanceSizeSpecs[option].ram} RAM / {instanceSizeSpecs[option].cpu}{' '}
CPU
</span>
<p
translate="no"
className={cn(
'text-xs',
highAvailability
? 'line-through text-foreground-lighter'
: 'text-foreground-light'
)}
data-field="instance-details"
>
${instanceSizeSpecs[option].priceHourly}/hour (~$
{instanceSizeSpecs[option].priceMonthly}/month)
</p>
{highAvailability && (
<p
className="text-xs text-foreground-light"
data-field="instance-details"
>
Free during Alpha
</p>
)}
</div>
</div>
</SelectItem>
)
})}
{!highAvailability && (
<SelectItem key={'disabled'} value={'disabled'} disabled>
<div className="flex items-center justify-center w-full">
<span>Larger instance sizes available after creation</span>
</div>
</SelectItem>
)}
</SelectGroup>
</SelectContent>
</Select>
</FormItemLayout>
)}
/>
</Panel.Content>
)
}