mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
## What kind of change does this PR introduce? Bug fix. Follow-up to #49660. ## What is the current behavior? `AccordionTrigger` adds horizontal padding at the shared primitive level. This shifts content at call sites that already own their spacing. In the Studio Advanced settings sections, padding around the whole accordion also constrains the trigger and its hit area instead of letting it fill the row. ## What is the new behavior? The shared trigger no longer adds horizontal padding and its header explicitly fills its container. Both Studio Advanced settings sections now apply their padding inside the full-width trigger and content, keeping the text aligned while extending the focus outline and hit area across the row. The inset focus treatment from #49660 is unchanged. | Before | After | | --- | --- | | <img width="1334" height="286" alt="CleanShot 2026-09-08 at 16 18 57@2x" src="https://github.com/user-attachments/assets/3a057b45-1eb4-4928-ae69-2d636b0c4678" /> | <img width="1302" height="278" alt="CleanShot 2026-09-08 at 16 18 12@2x" src="https://github.com/user-attachments/assets/0454493e-4fbc-4ad2-a9fd-1b9dc1d486dc" /> | ## To test ### Studio replication destination 1. Open the [Studio staging preview](https://studio-staging-git-dnywh-fixaccordion-trigger-width-supabase.vercel.app) and select a project with Pipelines enabled. 2. Go to **Database > Replication**. Under **Destinations**, click **Add destination**. 3. Tab to **Advanced settings** and press Enter to expand it. 4. Confirm the text aligns with the form content, the focus outline spans the full row between the sheet edges, and clicking near the far right of the row toggles it. ### Studio access-token permissions 1. In the [Studio staging preview](https://studio-staging-git-dnywh-fixaccordion-trigger-width-supabase.vercel.app), go to **Account > Access Tokens**. 2. Click **Generate new token** and scroll to **Permissions**. 3. Tab to any permission category, then click near the far right of its row. 4. Confirm the focus outline fills the category row, the label keeps its existing inset, and the full row toggles the category. ### Pricing FAQs 1. Open the [Pricing preview](https://zone-www-dot-com-git-dnywh-fixaccordion-trigger-width-supabase.vercel.app/pricing) and scroll to **Frequently asked questions**. 2. Tab to any question, then click near the far right of its row. 3. Confirm the question has not gained extra horizontal inset and the full row remains interactive. ### Design-system Accordion 1. Open the [design-system Accordion preview](https://design-system-git-dnywh-fixaccordion-trigger-width-supabase.vercel.app/docs/components/accordion). 2. Tab through the three accordion triggers and toggle each one. 3. Confirm each focus outline fills its row, with no extra horizontal padding around the label.
177 lines
7.1 KiB
TypeScript
177 lines
7.1 KiB
TypeScript
import { useMemo, type Dispatch, type SetStateAction } from 'react'
|
|
import {
|
|
Accordion,
|
|
AccordionContent,
|
|
AccordionItem,
|
|
AccordionTrigger,
|
|
Badge,
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectSeparator,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
SheetSection,
|
|
} from 'ui'
|
|
import { Input } from 'ui-patterns/DataInputs/Input'
|
|
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
|
|
|
|
import { getExtensionDefaultSchema } from '../IntegrationOverviewTabV2.utils'
|
|
import { type ExtensionsSchema, type InstallIntegrationSheetProps } from './InstallIntegrationSheet'
|
|
import { extensionsWithRecommendedSchemas } from '@/components/interfaces/Database/Extensions/Extensions.constants'
|
|
import { useDatabaseExtensionsQuery } from '@/data/database-extensions/database-extensions-query'
|
|
import { useSchemasQuery } from '@/data/database/schemas-query'
|
|
import { useSchemasFilteredForHighAvailability } from '@/hooks/misc/useHighAvailability'
|
|
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
|
|
import { useProtectedSchemas } from '@/hooks/useProtectedSchemas'
|
|
|
|
type AdvancedSettingsProps = InstallIntegrationSheetProps & {
|
|
extensionsSchema: ExtensionsSchema
|
|
setExtensionsSchema: Dispatch<SetStateAction<ExtensionsSchema>>
|
|
}
|
|
|
|
export const AdvancedSettings = ({
|
|
integration,
|
|
extensionsSchema,
|
|
setExtensionsSchema,
|
|
}: AdvancedSettingsProps) => {
|
|
const { data: project } = useSelectedProjectQuery()
|
|
const { data: protectedSchemas } = useProtectedSchemas({ excludeSchemas: ['extensions'] })
|
|
const { requiredExtensions: requiredExtensionNames } = integration
|
|
|
|
const involvesExtensions = requiredExtensionNames.length > 0
|
|
const { data: extensions = [] } = useDatabaseExtensionsQuery(
|
|
{ projectRef: project?.ref, connectionString: project?.connectionString },
|
|
{ enabled: involvesExtensions }
|
|
)
|
|
|
|
const { data: schemas = [] } = useSchemasQuery(
|
|
{ projectRef: project?.ref, connectionString: project?.connectionString },
|
|
{ enabled: involvesExtensions }
|
|
)
|
|
const visibleSchemas = useSchemasFilteredForHighAvailability(schemas)
|
|
const availableSchemas = useMemo(
|
|
() =>
|
|
visibleSchemas.filter(
|
|
(schema) =>
|
|
!protectedSchemas.some((protectedSchema) => protectedSchema.name === schema.name)
|
|
),
|
|
[visibleSchemas, protectedSchemas]
|
|
)
|
|
|
|
return (
|
|
<SheetSection className="px-0">
|
|
<Accordion type="single" collapsible>
|
|
<AccordionItem value="advanced-settings" className="border-none">
|
|
<AccordionTrigger className="font-normal gap-2 px-5 py-0 justify-between text-sm hover:no-underline">
|
|
Advanced settings
|
|
</AccordionTrigger>
|
|
<AccordionContent className="pb-0! pt-3 [&>div]:flex [&>div]:flex-col [&>div]:gap-y-4 [&>div]:px-5">
|
|
<p className="text-foreground-light">
|
|
Select which schemas to install the database extensions under
|
|
</p>
|
|
{requiredExtensionNames.map((extName) => {
|
|
const ext = extensions.find((x) => x.name === extName)
|
|
const extMeta = extensionsSchema[extName]
|
|
const { schema, value } = extMeta
|
|
const recommendedSchema = extensionsWithRecommendedSchemas[extName]
|
|
const defaultSchema = getExtensionDefaultSchema(ext)
|
|
|
|
return (
|
|
<FormItemLayout
|
|
key={extName}
|
|
isReactForm={false}
|
|
layout="horizontal"
|
|
label={extName}
|
|
description={
|
|
ext?.installed_version ? (
|
|
<>
|
|
Installed in <code className="text-code-inline">{ext.schema}</code> schema
|
|
</>
|
|
) : defaultSchema ? (
|
|
<>
|
|
Must be installed in the{' '}
|
|
<code className="text-code-inline">{defaultSchema}</code> schema
|
|
</>
|
|
) : recommendedSchema ? (
|
|
<>
|
|
Use the <code className="text-code-inline">{recommendedSchema}</code> schema
|
|
for full compatibility with related features
|
|
</>
|
|
) : undefined
|
|
}
|
|
>
|
|
<Select
|
|
disabled={!!defaultSchema || !!ext?.installed_version}
|
|
value={schema}
|
|
onValueChange={(schema) =>
|
|
setExtensionsSchema((prev) => ({
|
|
...prev,
|
|
[extName]: {
|
|
schema,
|
|
value: schema === 'custom' ? extName : undefined,
|
|
},
|
|
}))
|
|
}
|
|
>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Select a schema" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="custom">Create a new schema</SelectItem>
|
|
<SelectSeparator />
|
|
{availableSchemas.map((schema) => {
|
|
return (
|
|
<SelectItem key={schema.id} value={schema.name}>
|
|
{schema.name}
|
|
{schema.name === recommendedSchema ? (
|
|
<Badge className="ml-2" variant="success">
|
|
Recommended
|
|
</Badge>
|
|
) : schema.name === 'extensions' ? (
|
|
<Badge className="ml-2">Default</Badge>
|
|
) : null}
|
|
</SelectItem>
|
|
)
|
|
})}
|
|
{defaultSchema &&
|
|
!availableSchemas.some((schema) => schema.name === defaultSchema) ? (
|
|
<SelectItem key={defaultSchema} value={defaultSchema}>
|
|
{defaultSchema}
|
|
<Badge className="ml-2">Default</Badge>
|
|
</SelectItem>
|
|
) : null}
|
|
</SelectContent>
|
|
</Select>
|
|
|
|
{schema === 'custom' && (
|
|
<FormItemLayout
|
|
isReactForm={false}
|
|
className="mt-2"
|
|
label="Provide a name for your new schema"
|
|
>
|
|
<Input
|
|
value={value}
|
|
onChange={(e) =>
|
|
setExtensionsSchema((prev) => ({
|
|
...prev,
|
|
[extName]: {
|
|
schema: prev[extName].schema,
|
|
value: e.target.value,
|
|
},
|
|
}))
|
|
}
|
|
placeholder="Provide a name for your schema"
|
|
/>
|
|
</FormItemLayout>
|
|
)}
|
|
</FormItemLayout>
|
|
)
|
|
})}
|
|
</AccordionContent>
|
|
</AccordionItem>
|
|
</Accordion>
|
|
</SheetSection>
|
|
)
|
|
}
|