diff --git a/apps/design-system/registry/default/example/form-patterns-pagelayout.tsx b/apps/design-system/registry/default/example/form-patterns-pagelayout.tsx index a58732fb100..b95b8c91c39 100644 --- a/apps/design-system/registry/default/example/form-patterns-pagelayout.tsx +++ b/apps/design-system/registry/default/example/form-patterns-pagelayout.tsx @@ -13,12 +13,12 @@ import { Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, + FormInputGroupTextArea, Input_Shadcn_, InputGroup, InputGroupAddon, - InputGroupInput, InputGroupText, - InputGroupTextarea, Popover_Shadcn_, PopoverContent_Shadcn_, PopoverTrigger_Shadcn_, @@ -237,7 +237,13 @@ export default function FormPatternsPageLayout() { > - + field.onChange(Number(e.target.value))} + type="number" + min={5} + max={30} + /> MB @@ -285,7 +291,7 @@ export default function FormPatternsPageLayout() { > - - + MB diff --git a/apps/studio/components/interfaces/Auth/AuthProvidersForm/FormField.tsx b/apps/studio/components/interfaces/Auth/AuthProvidersForm/FormField.tsx index 4dcd7e4cf17..3993465467a 100644 --- a/apps/studio/components/interfaces/Auth/AuthProvidersForm/FormField.tsx +++ b/apps/studio/components/interfaces/Auth/AuthProvidersForm/FormField.tsx @@ -7,10 +7,10 @@ import { Calendar, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, Input_Shadcn_, InputGroup, InputGroupAddon, - InputGroupInput, Popover_Shadcn_, PopoverContent_Shadcn_, PopoverTrigger_Shadcn_, @@ -229,17 +229,17 @@ const FormField = ({ {properties.units ? ( - - - {properties.units} - - - field.onChange(Number(e.target.value))} /> + + + {properties.units} + + ) : ( custom: - { > - - factors - - + + factors + @@ -481,16 +481,16 @@ export const MfaAuthSettingsForm = () => { > - - digits - - + + digits + diff --git a/apps/studio/components/interfaces/Auth/PerformanceSettingsForm.tsx b/apps/studio/components/interfaces/Auth/PerformanceSettingsForm.tsx index bfcbcd3dc6b..71fe409e6e3 100644 --- a/apps/studio/components/interfaces/Auth/PerformanceSettingsForm.tsx +++ b/apps/studio/components/interfaces/Auth/PerformanceSettingsForm.tsx @@ -11,9 +11,9 @@ import { Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, InputGroup, InputGroupAddon, - InputGroupInput, InputGroupText, Select_Shadcn_, SelectContent_Shadcn_, @@ -226,22 +226,22 @@ export const PerformanceSettingsForm = () => { } >
- -
+
+ - - seconds - - + + seconds + -
- + +

10+ seconds recommended @@ -368,16 +368,11 @@ export const PerformanceSettingsForm = () => {

} > - -
-
+
+
+ - - - {chosenUnit === 'percent' ? '%' : 'connections'} - - - { } disabled={!canUpdateConfig || promptUpgrade} /> + + + {chosenUnit === 'percent' ? '%' : 'connections'} + + -
- {isLoadingMaxConns ? ( - - ) : ( -

- - {chosenUnit === 'percent' - ? Math.floor( - maxConnectionLimit * (Math.min(100, field.value!) / 100) - ).toString() - : Math.min(maxConnectionLimit, field.value!)} - {' '} - / {maxConnectionLimit} -

- )} +
- + {isLoadingMaxConns ? ( + + ) : ( +

+ + {chosenUnit === 'percent' + ? Math.floor( + maxConnectionLimit * (Math.min(100, field.value!) / 100) + ).toString() + : Math.min(maxConnectionLimit, field.value!)} + {' '} + / {maxConnectionLimit} +

+ )} +
)} /> diff --git a/apps/studio/components/interfaces/Auth/RateLimits/RateLimits.tsx b/apps/studio/components/interfaces/Auth/RateLimits/RateLimits.tsx index 902e500a962..c286afce068 100644 --- a/apps/studio/components/interfaces/Auth/RateLimits/RateLimits.tsx +++ b/apps/studio/components/interfaces/Auth/RateLimits/RateLimits.tsx @@ -13,9 +13,9 @@ import { Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, InputGroup, InputGroupAddon, - InputGroupInput, InputGroupText, Switch, Tooltip, @@ -238,15 +238,15 @@ export const RateLimits = () => { - - emails/h - - + + emails/h + @@ -309,15 +309,15 @@ export const RateLimits = () => { - - sms/h - - + + sms/h + @@ -358,15 +358,15 @@ export const RateLimits = () => { - - requests/5 min - - + + requests/5 min + @@ -406,15 +406,15 @@ export const RateLimits = () => { - - requests/5 min - - + + requests/5 min + @@ -454,15 +454,15 @@ export const RateLimits = () => { - - requests/h - - + + requests/h + @@ -501,15 +501,15 @@ export const RateLimits = () => { - - requests/5 min - - + + requests/5 min + @@ -549,15 +549,15 @@ export const RateLimits = () => { - - requests/5 min - - + + requests/5 min + diff --git a/apps/studio/components/interfaces/Auth/SessionsAuthSettingsForm/SessionsAuthSettingsForm.tsx b/apps/studio/components/interfaces/Auth/SessionsAuthSettingsForm/SessionsAuthSettingsForm.tsx index 36f55050999..4bd9dde293a 100644 --- a/apps/studio/components/interfaces/Auth/SessionsAuthSettingsForm/SessionsAuthSettingsForm.tsx +++ b/apps/studio/components/interfaces/Auth/SessionsAuthSettingsForm/SessionsAuthSettingsForm.tsx @@ -12,9 +12,9 @@ import { Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, InputGroup, InputGroupAddon, - InputGroupInput, InputGroupText, Switch, } from 'ui' @@ -242,15 +242,15 @@ export const SessionsAuthSettingsForm = () => { > - - seconds - - + + seconds + @@ -329,17 +329,17 @@ export const SessionsAuthSettingsForm = () => { > - - - - - - + + + + + @@ -359,17 +359,17 @@ export const SessionsAuthSettingsForm = () => { > - - - - - - + + + + + diff --git a/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx b/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx index 0101102944d..9d5343a4301 100644 --- a/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx +++ b/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx @@ -13,10 +13,10 @@ import { Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, Input_Shadcn_, InputGroup, InputGroupAddon, - InputGroupInput, InputGroupText, Switch, } from 'ui' @@ -396,15 +396,15 @@ export const SmtpForm = () => { > - - seconds - - field.onChange(Number(e.target.value))} disabled={!canUpdateConfig} /> + + seconds + diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/AdvancedSettings.tsx b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/AdvancedSettings.tsx index 63096351d16..fd20f1e5416 100644 --- a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/AdvancedSettings.tsx +++ b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/AdvancedSettings.tsx @@ -8,9 +8,9 @@ import { Badge, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, InputGroup, InputGroupAddon, - InputGroupInput, InputGroupText, Select_Shadcn_, SelectContent_Shadcn_, @@ -71,16 +71,16 @@ export const AdvancedSettings = ({ > - - milliseconds - - + + milliseconds + @@ -105,16 +105,16 @@ export const AdvancedSettings = ({ > - - workers - - + + workers + @@ -142,16 +142,16 @@ export const AdvancedSettings = ({ > - - connections - - + + connections + @@ -217,16 +217,16 @@ export const AdvancedSettings = ({ > - - connections - - + + connections + @@ -260,16 +260,16 @@ export const AdvancedSettings = ({ > - - minutes - - + + minutes + diff --git a/apps/studio/components/interfaces/DiskManagement/fields/AutoScaleFields.tsx b/apps/studio/components/interfaces/DiskManagement/fields/AutoScaleFields.tsx index b19c104a2b1..c12bcdd0d0c 100644 --- a/apps/studio/components/interfaces/DiskManagement/fields/AutoScaleFields.tsx +++ b/apps/studio/components/interfaces/DiskManagement/fields/AutoScaleFields.tsx @@ -5,9 +5,9 @@ import { cn, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, InputGroup, InputGroupAddon, - InputGroupInput, InputGroupText, } from 'ui' import { Admonition } from 'ui-patterns' @@ -70,10 +70,7 @@ export const AutoScaleFields = ({ form }: AutoScaleFieldProps) => { > - - % - - { }} placeholder={String(DISK_AUTOSCALE_CONFIG_DEFAULTS.growthPercent)} /> + + % + @@ -116,10 +116,7 @@ export const AutoScaleFields = ({ form }: AutoScaleFieldProps) => { > - - GB - - { }} placeholder={String(DISK_AUTOSCALE_CONFIG_DEFAULTS.minIncrementSize)} /> + + GB + @@ -157,10 +157,7 @@ export const AutoScaleFields = ({ form }: AutoScaleFieldProps) => { > - - GB - - { }} placeholder={String(DISK_AUTOSCALE_CONFIG_DEFAULTS.maxSizeGb)} /> + + GB + diff --git a/apps/studio/components/interfaces/DiskManagement/fields/DiskSizeField.tsx b/apps/studio/components/interfaces/DiskManagement/fields/DiskSizeField.tsx index 7ccde9883c6..296df80f45f 100644 --- a/apps/studio/components/interfaces/DiskManagement/fields/DiskSizeField.tsx +++ b/apps/studio/components/interfaces/DiskManagement/fields/DiskSizeField.tsx @@ -6,10 +6,10 @@ import { Button, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, InputGroup, InputGroupAddon, InputGroupButton, - InputGroupInput, InputGroupText, } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' @@ -100,6 +100,22 @@ export function DiskSizeField({ + e.currentTarget.blur()} + onChange={(e) => { + setValue('totalSize', e.target.valueAsNumber, { + shouldDirty: true, + shouldValidate: true, + }) + trigger('provisionedIOPS') + trigger('throughput') + }} + min={includedDiskGB} + /> GB {isDirty ? ( @@ -118,22 +134,6 @@ export function DiskSizeField({ ) : null} - e.currentTarget.blur()} - onChange={(e) => { - setValue('totalSize', e.target.valueAsNumber, { - shouldDirty: true, - shouldValidate: true, - }) - trigger('provisionedIOPS') - trigger('throughput') - }} - min={includedDiskGB} - /> diff --git a/apps/studio/components/interfaces/DiskManagement/fields/IOPSField.tsx b/apps/studio/components/interfaces/DiskManagement/fields/IOPSField.tsx index 604fdb3c487..a2f8a8c615f 100644 --- a/apps/studio/components/interfaces/DiskManagement/fields/IOPSField.tsx +++ b/apps/studio/components/interfaces/DiskManagement/fields/IOPSField.tsx @@ -5,9 +5,9 @@ import { Button, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, InputGroup, InputGroupAddon, - InputGroupInput, } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' @@ -107,8 +107,7 @@ export function IOPSField({ form, disableInput }: IOPSFieldProps) { > - IOPS - + IOPS diff --git a/apps/studio/components/interfaces/DiskManagement/fields/ThroughputField.tsx b/apps/studio/components/interfaces/DiskManagement/fields/ThroughputField.tsx index 10cd39b1edc..d10856ad819 100644 --- a/apps/studio/components/interfaces/DiskManagement/fields/ThroughputField.tsx +++ b/apps/studio/components/interfaces/DiskManagement/fields/ThroughputField.tsx @@ -6,9 +6,9 @@ import { UseFormReturn } from 'react-hook-form' import { FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, InputGroup, InputGroupAddon, - InputGroupInput, InputGroupText, } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' @@ -120,10 +120,7 @@ export function ThroughputField({ form, disableInput }: ThroughputFieldProps) { > - - MB/s - - + + MB/s + diff --git a/apps/studio/components/interfaces/JwtSecrets/jwt-settings.tsx b/apps/studio/components/interfaces/JwtSecrets/jwt-settings.tsx index 48d75ab8eec..47eb143e01f 100644 --- a/apps/studio/components/interfaces/JwtSecrets/jwt-settings.tsx +++ b/apps/studio/components/interfaces/JwtSecrets/jwt-settings.tsx @@ -35,10 +35,10 @@ import { Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, Input_Shadcn_, InputGroup, InputGroupAddon, - InputGroupInput, InputGroupText, Modal, } from 'ui' @@ -329,10 +329,7 @@ const JWTSettings = () => { > - - seconds - - { ) } /> + + seconds + diff --git a/apps/studio/components/interfaces/Realtime/RealtimeSettings.tsx b/apps/studio/components/interfaces/Realtime/RealtimeSettings.tsx index 97fc2b1a8c3..fbc8c875aa3 100644 --- a/apps/studio/components/interfaces/Realtime/RealtimeSettings.tsx +++ b/apps/studio/components/interfaces/Realtime/RealtimeSettings.tsx @@ -13,10 +13,10 @@ import { Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, FormMessage_Shadcn_, InputGroup, InputGroupAddon, - InputGroupInput, InputGroupText, Switch, } from 'ui' @@ -278,15 +278,15 @@ export const RealtimeSettings = () => { > - - connections - - + + connections + @@ -314,15 +314,15 @@ export const RealtimeSettings = () => { > - - clients - - + + clients + @@ -341,15 +341,15 @@ export const RealtimeSettings = () => { > - - events/s - - + + events/s + @@ -395,15 +395,15 @@ export const RealtimeSettings = () => { > - - events/s - - + + events/s + @@ -449,15 +449,15 @@ export const RealtimeSettings = () => { > - - KB - - + + KB + diff --git a/apps/studio/components/interfaces/Settings/API/PostgrestConfig.tsx b/apps/studio/components/interfaces/Settings/API/PostgrestConfig.tsx index 792790537e5..cc87a0c80f2 100644 --- a/apps/studio/components/interfaces/Settings/API/PostgrestConfig.tsx +++ b/apps/studio/components/interfaces/Settings/API/PostgrestConfig.tsx @@ -15,10 +15,10 @@ import { Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, FormItem_Shadcn_, InputGroup, InputGroupAddon, - InputGroupInput, InputGroupText, Skeleton, Switch, @@ -611,16 +611,16 @@ export const PostgrestConfig = () => { > - - rows - - field.onChange(Number(e.target.value))} /> + + rows + @@ -641,10 +641,7 @@ export const PostgrestConfig = () => { > - - connections - - { } value={field.value === null ? '' : field.value} /> + + connections + diff --git a/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.tsx b/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.tsx index 260222d6464..5a9880f9e7e 100644 --- a/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.tsx +++ b/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.tsx @@ -15,9 +15,9 @@ import { Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, InputGroup, InputGroupAddon, - InputGroupInput, InputGroupText, Separator, } from 'ui' @@ -266,10 +266,7 @@ export const ConnectionPooling = () => { > - - connections - - { ) } /> + + connections + {!!maxConnData && @@ -330,10 +330,7 @@ export const ConnectionPooling = () => { > - - clients - - { ) } /> + + clients + diff --git a/apps/studio/components/interfaces/Settings/Database/DiskSizeConfigurationModal.tsx b/apps/studio/components/interfaces/Settings/Database/DiskSizeConfigurationModal.tsx index 7cda259ed0a..c259d7219c1 100644 --- a/apps/studio/components/interfaces/Settings/Database/DiskSizeConfigurationModal.tsx +++ b/apps/studio/components/interfaces/Settings/Database/DiskSizeConfigurationModal.tsx @@ -15,10 +15,10 @@ import { Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, InfoIcon, InputGroup, InputGroupAddon, - InputGroupInput, InputGroupText, Modal, WarningIcon, @@ -195,19 +195,19 @@ const DiskSizeConfigurationModal = ({ layout="vertical" label="New disk size" > - - - GB - - - + + field.onChange(Number(e.target.value))} /> - - + + GB + + + )} /> diff --git a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/CreateTable/CreateTableSheet.tsx b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/CreateTable/CreateTableSheet.tsx index ff9a0b2e8c2..1857b1aeea0 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/CreateTable/CreateTableSheet.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/CreateTable/CreateTableSheet.tsx @@ -10,10 +10,10 @@ import { Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, + FormInputGroupInput, Input_Shadcn_, InputGroup, InputGroupAddon, - InputGroupInput, Select_Shadcn_, SelectContent_Shadcn_, SelectItem_Shadcn_, @@ -256,14 +256,16 @@ export const CreateTableSheet = ({ open, onOpenChange }: CreateTableSheetProps) control={form.control} name={`columns.${idx}.name`} render={({ field }) => ( - - - + + + + + )} /> ( - - - {x.name} - + - - field.onChange( - isNaN(event.target.valueAsNumber) - ? null - : event.target.valueAsNumber - ) - } - /> + + + {x.name} + + + field.onChange( + isNaN(event.target.valueAsNumber) + ? null + : event.target.valueAsNumber + ) + } + /> + - + )} /> ))} diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx index 25bc69cd3e1..277d28b6cc9 100644 --- a/packages/ui/index.tsx +++ b/packages/ui/index.tsx @@ -142,6 +142,8 @@ export { FormMessage as FormMessage_Shadcn_, FormField as FormField_Shadcn_, useWatch as useWatch_Shadcn_, + FormInputGroupInput, + FormInputGroupTextArea, } from './src/components/shadcn/ui/form' export { diff --git a/packages/ui/src/components/shadcn/ui/form.tsx b/packages/ui/src/components/shadcn/ui/form.tsx index 2f562dc2c92..9d812d322c9 100644 --- a/packages/ui/src/components/shadcn/ui/form.tsx +++ b/packages/ui/src/components/shadcn/ui/form.tsx @@ -15,7 +15,10 @@ import { } from 'react-hook-form' import { cn } from '../../../lib/utils/cn' +import type { InputProps } from './input' +import { InputGroupInput, InputGroupTextarea } from './input-group' import { Label } from './label' +import type { TextareaProps } from './textarea' const Form = FormProvider @@ -179,6 +182,32 @@ const FormMessage = React.forwardRef< FormMessage.displayName = 'FormMessage' +function FormInputGroupInput(props: InputProps) { + const { error, formItemId, formDescriptionId, formMessageId } = useFormField() + + return ( + + ) +} + +function FormInputGroupTextArea(props: TextareaProps) { + const { error, formItemId, formDescriptionId, formMessageId } = useFormField() + + return ( + + ) +} + export { Form, FormControl, @@ -188,5 +217,7 @@ export { FormLabel, FormMessage, useFormField, + FormInputGroupInput, + FormInputGroupTextArea, useWatch, } diff --git a/packages/ui/src/components/shadcn/ui/input-group.tsx b/packages/ui/src/components/shadcn/ui/input-group.tsx index 44057a3970e..8d5cef5dbf8 100644 --- a/packages/ui/src/components/shadcn/ui/input-group.tsx +++ b/packages/ui/src/components/shadcn/ui/input-group.tsx @@ -6,7 +6,39 @@ import { Button } from '../../Button' import { Input, type InputProps } from './input' import { Textarea, type TextareaProps } from './textarea' -function InputGroup({ className, ...props }: React.ComponentProps<'div'>) { +interface InputGroupProps extends React.ComponentProps<'div'> { + /** + * This props is passed in by but they should be applied on the input itself. When using + * inside a , use and instead of the + * regular and