Popover ui component to use portal by default, remove all manual declaration of portal for PopoverContent in dashboard (#41818)

* Popover ui component to use portal by default, remove all manual declaration of portal for PopoverContent in dashboard

* Forgot to add ui changes lol

* Clean uop
This commit is contained in:
Joshen Lim authored and GitHub committed 2026-01-20 11:58:31 +08:00
1 parent 1dbd86a8c0
commit c6b2fe6fee
52 files changed
+128 -218

No files matched your search

@@ -76,7 +76,7 @@ function BaseEditor<TRow, TSummaryRow = unknown>({
{value === null ? 'NULL' : value}
</div>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ portal align="start" className="p-0 rounded-none w-64">
<PopoverContent_Shadcn_ align="start" className="p-0 rounded-none w-64">
<BlockKeys
ignoreOutsideClicks
value={inputValue}
@@ -83,7 +83,7 @@ export const ForeignKeyFormatter = (props: Props) => {
tooltip={{ content: { side: 'bottom', text: 'View referencing record' } }}
/>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ portal align="end" className="p-0 w-96">
<PopoverContent_Shadcn_ align="end" className="p-0 w-96">
<ReferenceRecordPeek
table={targetTable}
column={relationship.target_column_name}
@@ -4,11 +4,7 @@ import { useTableFilter } from 'components/grid/hooks/useTableFilter'
import { formatFilterURLParams } from 'components/grid/SupabaseGrid.utils'
import { FilterPopoverPrimitive } from './FilterPopoverPrimitive'
export interface FilterPopoverProps {
portal?: boolean
}
export const FilterPopover = ({ portal = true }: FilterPopoverProps) => {
export const FilterPopover = () => {
const { urlFilters, onApplyFilters } = useTableFilter()
// Convert string[] to Filter[]
@@ -16,7 +12,5 @@ export const FilterPopover = ({ portal = true }: FilterPopoverProps) => {
return formatFilterURLParams(urlFilters ?? [])
}, [urlFilters])
return (
<FilterPopoverPrimitive portal={portal} filters={filters} onApplyFilters={onApplyFilters} />
)
return <FilterPopoverPrimitive filters={filters} onApplyFilters={onApplyFilters} />
}
@@ -17,14 +17,12 @@ export interface FilterPopoverPrimitiveProps {
buttonText?: string
filters: Filter[]
onApplyFilters: (filters: Filter[]) => void
portal?: boolean
}
export const FilterPopoverPrimitive = ({
buttonText,
filters,
onApplyFilters,
portal = true,
}: FilterPopoverPrimitiveProps) => {
const [open, setOpen] = useState(false)
const snap = useTableEditorTableStateSnapshot()
@@ -94,7 +92,7 @@ export const FilterPopoverPrimitive = ({
{displayButtonText}
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ className="p-0 w-96" side="bottom" align="start" portal={portal}>
<PopoverContent_Shadcn_ className="p-0 w-96" side="bottom" align="start">
<div className="space-y-2 py-2">
<div className="space-y-2">
{localFilters.map((filter, index) => (
@@ -6,11 +6,10 @@ import { useTableEditorTableStateSnapshot } from 'state/table-editor-table'
import { SortPopoverPrimitive } from './SortPopoverPrimitive'
export interface SortPopoverProps {
portal?: boolean
tableQueriesEnabled?: boolean
}
export const SortPopover = ({ portal = true, tableQueriesEnabled }: SortPopoverProps) => {
export const SortPopover = ({ tableQueriesEnabled }: SortPopoverProps) => {
const { urlSorts, onApplySorts } = useTableSort()
const snap = useTableEditorTableStateSnapshot()
@@ -23,7 +22,6 @@ export const SortPopover = ({ portal = true, tableQueriesEnabled }: SortPopoverP
return (
<SortPopoverPrimitive
portal={portal}
sorts={sorts}
onApplySorts={onApplySorts}
tableQueriesEnabled={tableQueriesEnabled}
@@ -30,7 +30,6 @@ export interface SortPopoverPrimitiveProps {
buttonText?: string
sorts: Sort[]
onApplySorts: (sorts: Sort[]) => void
portal?: boolean
defaultOpen?: boolean
tableQueriesEnabled?: boolean
}
@@ -48,7 +47,6 @@ export const SortPopoverPrimitive = ({
buttonText,
sorts,
onApplySorts,
portal = true,
defaultOpen = false,
tableQueriesEnabled = true,
}: SortPopoverPrimitiveProps) => {
@@ -225,7 +223,7 @@ export const SortPopoverPrimitive = ({
{displayButtonText}
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ className="p-0 w-96" side="bottom" align="start" portal={portal}>
<PopoverContent_Shadcn_ className="p-0 w-96" side="bottom" align="start">
<div className="space-y-2 py-2">
{localSorts.map((sort, index) => (
<SortRow
@@ -360,7 +360,6 @@ export const CreateHookSheet = ({
>
<FormControl_Shadcn_>
<SchemaSelector
portal={false}
size="small"
showError={false}
selectedSchemaName={field.value}
@@ -67,7 +67,7 @@ export const BranchSelector = ({
{isUpdating ? 'Creating...' : 'New merge request'}
</ButtonTooltip>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ portal className="p-0 w-80" side="bottom" align="end">
<PopoverContent_Shadcn_ className="p-0 w-80" side="bottom" align="end">
<Command_Shadcn_>
<CommandInput_Shadcn_ placeholder="Find branch to review..." />
<CommandList_Shadcn_>
@@ -300,7 +300,7 @@ export const DatabaseConnectionString = () => {
</Select_Shadcn_>
</div>
<DatabaseSelector
portal={false}
align="start"
buttonProps={{
size: 'small',
className: 'w-full justify-between pr-2.5 [&_svg]:h-4',
@@ -48,7 +48,7 @@ export const TimezoneSelection = ({
: 'Select timezone...'}
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ portal className="w-[350px] p-0">
<PopoverContent_Shadcn_ className="w-[350px] p-0">
<Command_Shadcn_>
<CommandInput_Shadcn_ placeholder="Search timezone..." className="h-9" />
<CommandList_Shadcn_>
@@ -203,7 +203,6 @@ export const CreateFunction = ({
>
<FormControl_Shadcn_>
<SchemaSelector
portal={false}
selectedSchemaName={field.value}
excludedSchemas={protectedSchemas?.map((s) => s.name)}
size="small"
@@ -44,7 +44,7 @@ interface CreateIndexSidePanelProps {
onClose: () => void
}
const CreateIndexSidePanel = ({ visible, onClose }: CreateIndexSidePanelProps) => {
export const CreateIndexSidePanel = ({ visible, onClose }: CreateIndexSidePanelProps) => {
const { data: project } = useSelectedProjectQuery()
const isOrioleDb = useIsOrioleDb()
@@ -420,5 +420,3 @@ CREATE INDEX ON "${selectedSchema}"."${selectedEntity}" USING ${selectedIndexTyp
</SidePanel>
)
}
export default CreateIndexSidePanel
@@ -30,7 +30,7 @@ import { Input } from 'ui-patterns/DataInputs/Input'
import { ConfirmationModal } from 'ui-patterns/Dialogs/ConfirmationModal'
import { GenericSkeletonLoader, ShimmeringLoader } from 'ui-patterns/ShimmeringLoader'
import { ProtectedSchemaWarning } from '../ProtectedSchemaWarning'
import CreateIndexSidePanel from './CreateIndexSidePanel'
import { CreateIndexSidePanel } from './CreateIndexSidePanel'
const Indexes = () => {
const { data: project } = useSelectedProjectQuery()
@@ -235,7 +235,7 @@ export const TableList = ({
icon={<Filter />}
/>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ className="p-0 w-56" side="bottom" align="center" portal={true}>
<PopoverContent_Shadcn_ className="p-0 w-56" side="bottom" align="center">
<div className="px-3 pt-3 pb-2 flex flex-col gap-y-2">
<p className="text-xs">Show entity types</p>
<div className="flex flex-col">
@@ -428,7 +428,7 @@ export const EdgeFunctionTesterSheet = ({ visible, onClose }: EdgeFunctionTester
<RoleImpersonationStateContextProvider
key={`role-impersonation-state-${projectRef}`}
>
<RoleImpersonationPopover portal={false} disallowAuthenticatedOption={true} />
<RoleImpersonationPopover disallowAuthenticatedOption />
</RoleImpersonationStateContextProvider>
<Button
type="primary"
@@ -325,7 +325,7 @@ export const ServiceStatus = () => {
{isBranch ? 'Branch' : 'Project'} Status
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ portal className="p-0 w-56" side="bottom" align="center">
<PopoverContent_Shadcn_ className="p-0 w-56" side="bottom" align="center">
{services.map((service) => (
<Link
href={`/project/${ref}${service.logsUrl}`}
@@ -1,3 +1,6 @@
import { ConnectionType } from 'components/interfaces/Connect/Connect.constants'
import { ConnectionIcon } from 'components/interfaces/Connect/ConnectionIcon'
import { Box, Check, ChevronDown } from 'lucide-react'
import { useState } from 'react'
import {
Button,
@@ -12,9 +15,6 @@ import {
Popover_Shadcn_,
cn,
} from 'ui'
import { Box, Check, ChevronDown } from 'lucide-react'
import { ConnectionType } from 'components/interfaces/Connect/Connect.constants'
import { ConnectionIcon } from 'components/interfaces/Connect/ConnectionIcon'
interface FrameworkSelectorProps {
value: string
@@ -55,12 +55,10 @@ export const FrameworkSelector = ({
</Button>
</PopoverTrigger_Shadcn_>
</div>
{/* Render in a portal to avoid layout/stacking shifts; prevent auto-focus to stop scroll jump */}
<PopoverContent_Shadcn_
className="p-0 max-w-48"
side="bottom"
align="start"
portal
onOpenAutoFocus={(e) => e.preventDefault()}
>
<Command_Shadcn_>
@@ -269,7 +269,7 @@ export const ServiceStatus = () => {
value={<span>{overallStatusLabel}</span>}
/>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ portal className="p-0 w-60" side="bottom" align="start">
<PopoverContent_Shadcn_ className="p-0 w-60" side="bottom" align="start">
{services.map((service) => (
<Link
href={`/project/${ref}${service.logsUrl}`}
@@ -84,13 +84,7 @@ export const HomePageActions = ({
icon={<Filter />}
/>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_
className="p-0 w-56"
side="bottom"
align="center"
sideOffset={6}
portal={true}
>
<PopoverContent_Shadcn_ className="p-0 w-56" side="bottom" align="center" sideOffset={6}>
<div className="px-3 pt-3 pb-2 flex flex-col gap-y-2">
<p className="text-xs">Filter projects by status</p>
<div className="flex flex-col">
@@ -21,7 +21,6 @@ export const SqlFunctionSection = ({ form }: SqlFunctionSectionProps) => {
render={({ field }) => (
<FormItemLayout label="Schema" className="gap-1">
<SchemaSelector
portal={false}
size="small"
className="w-56 2xl:w-full"
selectedSchemaName={field.value}
@@ -88,7 +88,6 @@ const OrganizationPicker = ({
className="p-0 w-full"
side="bottom"
align="center"
portal
sameWidthAsTrigger
>
<Command_Shadcn_>
@@ -328,7 +328,6 @@ const ProjectLinker = ({
side="bottom"
align="center"
sameWidthAsTrigger
portal
>
<Command_Shadcn_>
<CommandInput_Shadcn_ placeholder="Search for a project" />
@@ -154,7 +154,7 @@ export const BillingCustomerDataForm = ({
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent portal sameWidthAsTrigger className="p-0" align="start">
<PopoverContent sameWidthAsTrigger className="p-0" align="start">
<Command>
<CommandInput placeholder="Search country..." />
<CommandList>
@@ -260,7 +260,7 @@ export const BillingCustomerDataForm = ({
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent portal sameWidthAsTrigger className="p-0" align="start">
<PopoverContent sameWidthAsTrigger className="p-0" align="start">
<Command>
<CommandInput placeholder="Search tax ID..." />
<CommandList>
@@ -92,7 +92,7 @@ export const ChooseChannelPopover = ({ config, onChangeConfig }: ChooseChannelPo
</p>
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ portal className="p-0 w-[320px]" align="start">
<PopoverContent_Shadcn_ className="p-0 w-[320px]" align="start">
<div className="p-4 flex flex-col text-sm">
{config.channelName.length === 0 ? (
<>
@@ -2,6 +2,9 @@ import { PlusCircle } from 'lucide-react'
import Link from 'next/link'
import { Dispatch, SetStateAction, useEffect, useState } from 'react'
import { InlineLink } from '@/components/ui/InlineLink'
import { useDatabasePublicationsQuery } from '@/data/database-publications/database-publications-query'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { useParams } from 'common'
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
@@ -35,9 +38,18 @@ export const RealtimeFilterPopover = ({ config, onChangeConfig }: RealtimeFilter
const [tempConfig, setTempConfig] = useState(config)
const { ref } = useParams()
const { data: project } = useSelectedProjectQuery()
const { data: org } = useSelectedOrganizationQuery()
const { mutate: sendEvent } = useSendEventMutation()
const { data: publications } = useDatabasePublicationsQuery({
projectRef: project?.ref,
connectionString: project?.connectionString,
})
const realtimePublication = (publications ?? []).find(
(publication) => publication.name === 'supabase_realtime'
)
// Update tempConfig when config changes to ensure consistency
useEffect(() => {
setTempConfig(config)
@@ -75,7 +87,7 @@ export const RealtimeFilterPopover = ({ config, onChangeConfig }: RealtimeFilter
)}
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ className="p-0 w-[365px]" align="start" portal={true}>
<PopoverContent_Shadcn_ className="p-0 w-[365px]" align="start">
<div className="border-b border-overlay text-xs px-4 py-3 text-foreground">
Listen to event types
</div>
@@ -155,10 +167,19 @@ export const RealtimeFilterPopover = ({ config, onChangeConfig }: RealtimeFilter
/>
</div>
<p className="text-xs text-foreground-light pt-1">
{config.enableDbChanges
? 'Listen for Database inserts, updates, deletes and more'
: 'Enable realtime publications to listen for database changes'}
Listen for Database inserts, updates, deletes and more
</p>
{!config.enableDbChanges && (
<p className="text-xs text-foreground-light mt-2">
Enable{' '}
<InlineLink
href={`/project/${ref}/database/publications${!!realtimePublication ? `/${realtimePublication.id}` : ''}`}
>
realtime publications
</InlineLink>{' '}
for your tables to listen for database changes
</p>
)}
</div>
{tempConfig.enableDbChanges && config.enableDbChanges && (
@@ -1,15 +1,15 @@
import { useParams } from 'common'
import { useState, useEffect } from 'react'
import { useEffect, useState } from 'react'
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { useDatabasePublicationsQuery } from 'data/database-publications/database-publications-query'
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { EmptyRealtime } from './EmptyRealtime'
import { Header } from './Header'
import MessagesTable from './MessagesTable'
import { SendMessageModal } from './SendMessageModal'
import { RealtimeConfig, useRealtimeMessages } from './useRealtimeMessages'
import { EmptyRealtime } from './EmptyRealtime'
/**
* Acts as a container component for the entire log display
@@ -289,11 +289,7 @@ const ReportFilterBar = ({
<span>Add filter</span>
</Button>
</PopoverTrigger>
<PopoverContent
align={filters.length > 0 ? 'end' : 'start'}
portal={true}
className="p-0 w-60"
>
<PopoverContent align={filters.length > 0 ? 'end' : 'start'} className="p-0 w-60">
<div className="flex flex-col gap-3 p-3">
<Select
size="tiny"
@@ -1,26 +1,26 @@
import { ChevronDown, Filter as FilterIcon, Plus, X } from 'lucide-react'
import { KeyboardEvent, useCallback, useState, useMemo, useEffect } from 'react'
import { isEqual } from 'lodash'
import { ChevronDown, Filter as FilterIcon, Plus, X } from 'lucide-react'
import { KeyboardEvent, useCallback, useEffect, useMemo, useState } from 'react'
import { DropdownControl } from 'components/grid/components/common/DropdownControl'
import {
Button,
PopoverContent_Shadcn_,
PopoverSeparator_Shadcn_,
PopoverTrigger_Shadcn_,
Popover_Shadcn_,
Input,
Command_Shadcn_,
CommandEmpty_Shadcn_,
CommandGroup_Shadcn_,
CommandInput_Shadcn_,
CommandItem_Shadcn_,
CommandList_Shadcn_,
Command_Shadcn_,
Input,
PopoverContent_Shadcn_,
PopoverSeparator_Shadcn_,
PopoverTrigger_Shadcn_,
Popover_Shadcn_,
cn,
} from 'ui'
import type { ReportFilter, ReportFilterProperty } from './Reports.types'
import { sizes } from 'ui/src/lib/commonCva'
import defaultTheme from 'ui/src/lib/theme/defaultTheme'
import type { ReportFilter, ReportFilterProperty } from './Reports.types'
const FilterableInput = ({
value,
@@ -125,7 +125,6 @@ export interface ReportFilterPopoverProps {
filters: ReportFilter[]
filterProperties: ReportFilterProperty[]
onFiltersChange: (filters: ReportFilter[]) => void
portal?: boolean
disabled?: boolean
}
@@ -265,7 +264,6 @@ export const ReportFilterPopover = ({
filters,
filterProperties,
onFiltersChange,
portal = true,
disabled = false,
}: ReportFilterPopoverProps) => {
const [open, setOpen] = useState(false)
@@ -343,7 +341,7 @@ export const ReportFilterPopover = ({
{displayButtonText}
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ className="p-0 w-[500px]" side="bottom" align="start" portal={portal}>
<PopoverContent_Shadcn_ className="p-0 w-[500px]" side="bottom" align="start">
<div className="space-y-2 py-2">
<div>
{localFilters.map((filter, index) => (
@@ -129,7 +129,7 @@ export const ReportsNumericFilter = ({
</span>
</Button>
</PopoverTrigger>
<PopoverContent align="start" className="p-0 w-72" portal={true}>
<PopoverContent align="start" className="p-0 w-72">
<form
onSubmit={(e) => {
e.preventDefault()
@@ -2,18 +2,19 @@ import { ChevronDown } from 'lucide-react'
import { useEffect, useState } from 'react'
import { Checkbox } from '@ui/components/shadcn/ui/checkbox'
import { CommandGroup } from '@ui/components/shadcn/ui/command'
import { Label } from '@ui/components/shadcn/ui/label'
import { Popover, PopoverContent, PopoverTrigger } from '@ui/components/shadcn/ui/popover'
import {
Button,
cn,
Command_Shadcn_ as Command,
CommandEmpty_Shadcn_ as CommandEmpty,
CommandInput_Shadcn_ as CommandInput,
CommandItem_Shadcn_,
CommandList_Shadcn_ as CommandList,
} from 'ui'
import { CommandList_Shadcn_ as CommandList, CommandEmpty_Shadcn_ as CommandEmpty } from 'ui'
import { z } from 'zod'
import { CommandGroup } from '@ui/components/shadcn/ui/command'
export interface ReportSelectOption {
label: React.ReactNode
@@ -88,7 +89,7 @@ export const ReportsSelectFilter = ({
</span>
</Button>
</PopoverTrigger>
<PopoverContent align="start" className="p-0 w-72" portal={true}>
<PopoverContent align="start" className="p-0 w-72">
<Command>
{showSearch && <CommandInput placeholder="Search..." />}
<CommandList>
@@ -1,7 +1,6 @@
import { ReactNode, useState } from 'react'
import { PopoverContent_Shadcn_, PopoverTrigger_Shadcn_, Popover_Shadcn_, cn } from 'ui'
import { useState } from 'react'
import { Button, PopoverContent_Shadcn_, PopoverTrigger_Shadcn_, Popover_Shadcn_, cn } from 'ui'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import type { User } from 'data/auth/users-infinite-query'
import { ChevronDown, User as IconUser } from 'lucide-react'
import { useRoleImpersonationStateSnapshot } from 'state/role-impersonation-state'
@@ -9,25 +8,17 @@ import { RoleImpersonationSelector } from '.'
import { getAvatarUrl, getDisplayName } from '../Auth/Users/Users.utils'
export interface RoleImpersonationPopoverProps {
portal?: boolean
serviceRoleLabel?: string
variant?: 'regular' | 'connected-on-right' | 'connected-on-left' | 'connected-on-both'
align?: 'center' | 'start' | 'end'
disabled?: boolean
disabledTooltip?: ReactNode
disallowAuthenticatedOption?: boolean
}
export const RoleImpersonationPopover = ({
portal = true,
serviceRoleLabel,
variant = 'regular',
align = 'end',
disallowAuthenticatedOption = false,
// [Joshen] We can clean these up once the API keys fix is done
disabled = false,
disabledTooltip,
}: RoleImpersonationPopoverProps) => {
const state = useRoleImpersonationStateSnapshot()
@@ -38,7 +29,7 @@ export const RoleImpersonationPopover = ({
return (
<Popover_Shadcn_ open={isOpen} onOpenChange={setIsOpen}>
<PopoverTrigger_Shadcn_ asChild>
<ButtonTooltip
<Button
size="tiny"
type="default"
className={cn(
@@ -47,10 +38,6 @@ export const RoleImpersonationPopover = ({
variant === 'connected-on-left' && 'rounded-l-none border-l-0',
variant === 'connected-on-both' && 'rounded-none border-x-0'
)}
disabled={disabled}
tooltip={{
content: { side: 'bottom', text: disabledTooltip, className: 'text-center w-72' },
}}
>
<div className="flex items-center gap-1">
<span className="text-foreground-muted">Role</span>
@@ -69,14 +56,9 @@ export const RoleImpersonationPopover = ({
)}
<ChevronDown className="text-muted" strokeWidth={1} size={12} />
</div>
</ButtonTooltip>
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_
portal={portal}
className="p-0 w-[592px] overflow-hidden"
side="bottom"
align={align}
>
<PopoverContent_Shadcn_ className="p-0 overflow-hidden w-min" side="bottom" align={align}>
<RoleImpersonationSelector
serviceRoleLabel={serviceRoleLabel}
disallowAuthenticatedOption={disallowAuthenticatedOption}
@@ -99,31 +99,27 @@ export const RoleImpersonationSelector = ({
{selectedOption === 'service_role' && (
<p className="text-foreground-light text-sm">
The default Postgres/superuser role.
{disallowAuthenticatedOption ? <br /> : ' '}
This has admin privileges.
<span className="text-foreground">The default Postgres/superuser role</span>
<br />
It will bypass Row Level Security (RLS) policies.
This has admin privileges and will bypass Row Level Security (RLS) policies.
</p>
)}
{selectedOption === 'anon' && (
<p className="text-foreground-light text-sm">
For "anonymous access".
{disallowAuthenticatedOption ? <br /> : ' '}
This is the role which the API (PostgREST)
<span className="text-foreground">For "anonymous access"</span>
<br />
will use when a user is not logged in.
{disallowAuthenticatedOption ? <br /> : ' '}
This is the role which the API (PostgREST) will use when a user is not logged in. <br />
It will respect Row Level Security (RLS) policies.
</p>
)}
{selectedOption === 'authenticated' && (
<p className="text-foreground-light text-sm">
For "authenticated access". This is the role which the API (PostgREST)
<span className="text-foreground">For "authenticated access"</span>
<br />
will use when a user is logged in. It will respect Row Level Security (RLS) policies.
This is the role which the API (PostgREST) will use when a user is logged in. <br />
It will respect Row Level Security (RLS) policies.
</p>
)}
</div>
@@ -467,12 +467,7 @@ const GitHubIntegrationConnectionForm = ({
</Button>
</FormControl_Shadcn_>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_
portal
className="p-0 w-80"
side="bottom"
align="start"
>
<PopoverContent_Shadcn_ className="p-0 w-80" side="bottom" align="start">
<Command_Shadcn_>
<CommandInput_Shadcn_ placeholder="Search repositories..." />
<CommandList_Shadcn_ className="!max-h-[200px]">
@@ -351,7 +351,6 @@ export const LogsDatePicker = ({
className="flex w-full p-0"
side="bottom"
align={align}
portal={true}
{...popoverContentProps}
>
<div className="border-r p-2 flex flex-col gap-px">
@@ -1,10 +1,10 @@
import { useEffect, useMemo, useState } from 'react'
import { Checkbox } from '@ui/components/shadcn/ui/checkbox'
import { Label } from '@ui/components/shadcn/ui/label'
import { Popover, PopoverContent, PopoverTrigger } from '@ui/components/shadcn/ui/popover'
import { Button, cn } from 'ui'
import type { FilterSet, Filters } from './Logs.types'
import { Popover, PopoverContent, PopoverTrigger } from '@ui/components/shadcn/ui/popover'
import { Label } from '@ui/components/shadcn/ui/label'
import { Checkbox } from '@ui/components/shadcn/ui/checkbox'
interface LogsFilterPopoverProps {
options: FilterSet
@@ -69,7 +69,7 @@ const LogsFilterPopover = ({
<span>{options.label}</span>
</Button>
</PopoverTrigger>
<PopoverContent align={align} className="p-0 w-60" portal={true}>
<PopoverContent align={align} className="p-0 w-60">
<form
onSubmit={(e) => {
e.preventDefault()
@@ -315,12 +315,7 @@ export const GridHeaderActions = ({ table, isRefetching }: GridHeaderActionsProp
RLS disabled
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_
// using `portal` for a safari fix. issue with rendering outside of body element
portal
className="w-80 text-sm"
align="end"
>
<PopoverContent_Shadcn_ className="w-80 text-sm" align="end">
<h4 className="flex items-center gap-2">
<Lock size={16} /> Row Level Security (RLS)
</h4>
@@ -355,7 +350,7 @@ export const GridHeaderActions = ({ table, isRefetching }: GridHeaderActionsProp
Index Advisor
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ portal className="w-80 text-sm" align="end">
<PopoverContent_Shadcn_ className="w-80 text-sm" align="end">
<h4 className="flex items-center gap-2">
<Lightbulb size={16} /> Index Advisor
</h4>
@@ -431,12 +426,7 @@ export const GridHeaderActions = ({ table, isRefetching }: GridHeaderActionsProp
Security Definer view
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_
// using `portal` for a safari fix. issue with rendering outside of body element
portal
className="min-w-[395px] text-sm"
align="end"
>
<PopoverContent_Shadcn_ className="min-w-[395px] text-sm" align="end">
<h3 className="flex items-center gap-2">
<Unlock size={16} /> Secure your View
</h3>
@@ -482,12 +472,7 @@ export const GridHeaderActions = ({ table, isRefetching }: GridHeaderActionsProp
Security Definer view
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_
// using `portal` for a safari fix. issue with rendering outside of body element
portal
className="min-w-[395px] text-sm"
align="end"
>
<PopoverContent_Shadcn_ className="min-w-[395px] text-sm" align="end">
<h3 className="flex items-center gap-2">
<Unlock size={16} /> Secure your View
</h3>
@@ -525,12 +510,7 @@ export const GridHeaderActions = ({ table, isRefetching }: GridHeaderActionsProp
Unprotected Data API access
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_
// using `portal` for a safari fix. issue with rendering outside of body element
portal
className="min-w-[395px] text-sm"
align="end"
>
<PopoverContent_Shadcn_ className="min-w-[395px] text-sm" align="end">
<h3 className="flex items-center gap-2">
<Unlock size={16} /> Secure Foreign table
</h3>
@@ -216,17 +216,9 @@ export const ForeignRowSelector = ({
<div className="flex items-center justify-between my-2 mx-3">
<div className="flex items-center">
<RefreshButton tableId={table?.id} isRefetching={isRefetching} />
<FilterPopoverPrimitive
portal={false}
filters={filters}
onApplyFilters={onApplyFilters}
/>
<FilterPopoverPrimitive filters={filters} onApplyFilters={onApplyFilters} />
<DndProvider backend={HTML5Backend} context={window}>
<SortPopoverPrimitive
portal={false}
sorts={sorts}
onApplySorts={onApplySorts}
/>
<SortPopoverPrimitive sorts={sorts} onApplySorts={onApplySorts} />
</DndProvider>
</div>
@@ -144,7 +144,7 @@ const Column = ({
<PopoverContent_Shadcn_
className={cn('p-0', hasChangesInRelations ? 'w-96' : 'w-72')}
side="bottom"
align="end"
align="center"
>
<div className="text-xs px-2 pt-2">
Involved in {relations.length} foreign key{relations.length > 1 ? 's' : ''}
@@ -266,7 +266,7 @@ const EdgeFunctionDetailsLayout = ({
Download
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ align="end" portal className="p-0">
<PopoverContent_Shadcn_ align="end" className="p-0">
<div className="p-3 flex flex-col gap-y-2">
<p className="text-xs text-foreground-light">Download via CLI</p>
<Input
@@ -168,7 +168,6 @@ export const TableEditorMenu = () => {
setSelectedSchema(name)
}}
onSelectCreateSchema={() => snap.onAddSchema()}
portal={!isMobile}
/>
<div className="grid gap-3 mx-4">
@@ -98,7 +98,7 @@ export const AIAssistantChatSelector = ({ disabled = false }: AIAssistantChatSel
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ className="w-[250px] p-0" align="start">
<Command_Shadcn_>
<CommandInput_Shadcn_ placeholder="Search chats..." />
<CommandInput_Shadcn_ className="text-xs" placeholder="Search chats..." />
<CommandList_Shadcn_>
<CommandEmpty_Shadcn_>No chats found.</CommandEmpty_Shadcn_>
<CommandGroup_Shadcn_>
@@ -1,22 +1,22 @@
import { Pencil, ThumbsDown, ThumbsUp, Trash2 } from 'lucide-react'
import { type PropsWithChildren, useState, useEffect } from 'react'
import { zodResolver } from '@hookform/resolvers/zod'
import { Pencil, ThumbsDown, ThumbsUp, Trash2 } from 'lucide-react'
import { type PropsWithChildren, useEffect, useState } from 'react'
import { useForm } from 'react-hook-form'
import * as z from 'zod'
import { ButtonTooltip } from '../ButtonTooltip'
import {
cn,
Button,
Popover_Shadcn_,
PopoverTrigger_Shadcn_,
PopoverContent_Shadcn_,
cn,
Form_Shadcn_,
FormField_Shadcn_,
FormControl_Shadcn_,
FormField_Shadcn_,
Popover_Shadcn_,
PopoverContent_Shadcn_,
PopoverTrigger_Shadcn_,
TextArea_Shadcn_,
} from 'ui'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import { ButtonTooltip } from '../ButtonTooltip'
export function MessageActions({
children,
@@ -172,7 +172,7 @@ function MessageActionsThumbsDown({
/>
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ portal className="w-80" align="start">
<PopoverContent_Shadcn_ className="w-80" align="start">
{form.formState.isSubmitSuccessful ? (
<p className="text-sm">We appreciate your feedback!</p>
) : (
@@ -46,7 +46,7 @@ export function DataTableViewOptions() {
tooltip={{ content: { side: 'bottom', text: 'Toggle column visibility' } }}
/>
</PopoverTrigger>
<PopoverContent portal side="bottom" align="end" className="w-[200px] p-0">
<PopoverContent side="bottom" align="end" className="w-[200px] p-0">
<Command>
<CommandInput value={search} onValueChange={setSearch} placeholder="Search columns..." />
<CommandList>
@@ -38,8 +38,8 @@ interface DatabaseSelectorProps {
additionalOptions?: { id: string; name: string }[]
buttonProps?: ButtonProps
onSelectId?: (id: string) => void // Optional callback
portal?: boolean
className?: string
align?: 'start' | 'end'
}
export const DatabaseSelector = ({
@@ -48,7 +48,7 @@ export const DatabaseSelector = ({
additionalOptions = [],
onSelectId = noop,
buttonProps,
portal = true,
align = 'end',
className,
}: DatabaseSelectorProps) => {
const router = useRouter()
@@ -118,7 +118,7 @@ export const DatabaseSelector = ({
</Button>
</div>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ className="p-0 w-64" side="bottom" align="end" portal={portal}>
<PopoverContent_Shadcn_ className="p-0 w-64" side="bottom" align={align}>
<Command_Shadcn_>
<CommandList_Shadcn_>
{additionalOptions.length > 0 && (
@@ -208,7 +208,6 @@ export const FilterPopover = <T extends Record<string, any>>({
<PopoverContent_Shadcn_
className={cn('p-0', search !== undefined ? 'w-64' : 'w-44', className)}
align="start"
portal={true}
>
<div className="border-b border-overlay bg-surface-200 rounded-t pb-1 px-3">
<span className="text-xs text-foreground-light">
@@ -150,7 +150,6 @@ export const OrganizationProjectSelector = ({
)}
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_
portal
sameWidthAsTrigger={sameWidthAsTrigger}
className="p-0"
side="bottom"
+1 -4
View File
@@ -34,7 +34,6 @@ interface SchemaSelectorProps {
excludedSchemas?: string[]
onSelectSchema: (name: string) => void
onSelectCreateSchema?: () => void
portal?: boolean
align?: 'start' | 'end'
}
@@ -48,7 +47,6 @@ export const SchemaSelector = ({
excludedSchemas = [],
onSelectSchema,
onSelectCreateSchema,
portal = true,
align = 'start',
}: SchemaSelectorProps) => {
const [open, setOpen] = useState(false)
@@ -133,11 +131,10 @@ export const SchemaSelector = ({
className="p-0 min-w-[200px] pointer-events-auto"
side="bottom"
align={align}
portal={portal}
sameWidthAsTrigger
>
<Command_Shadcn_>
<CommandInput_Shadcn_ placeholder="Find schema..." />
<CommandInput_Shadcn_ className="text-xs" placeholder="Find schema..." />
<CommandList_Shadcn_>
<CommandEmpty_Shadcn_>No schemas found</CommandEmpty_Shadcn_>
<CommandGroup_Shadcn_>
@@ -290,7 +290,7 @@ const NewFunctionPage = () => {
Templates
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ portal className="w-[300px] p-0" align="end">
<PopoverContent_Shadcn_ className="w-[300px] p-0" align="end">
<Command_Shadcn_>
<CommandInput_Shadcn_ placeholder="Search templates..." />
<CommandList_Shadcn_>
@@ -227,7 +227,6 @@ export function FilterCondition({
className="min-w-[220px] p-0"
align="start"
side="bottom"
portal
onOpenAutoFocus={(e) => e.preventDefault()}
onCloseAutoFocus={(e) => e.preventDefault()}
onInteractOutside={(e) => {
@@ -269,7 +268,6 @@ export function FilterCondition({
className="min-w-[220px] w-fit p-0"
align="start"
side="bottom"
portal
onOpenAutoFocus={(e) => e.preventDefault()}
onCloseAutoFocus={(e) => e.preventDefault()}
onInteractOutside={(e) => {
@@ -201,7 +201,6 @@ export function FilterGroup({ group, path }: FilterGroupProps) {
className="min-w-[220px] p-0"
align="start"
side="bottom"
portal
onOpenAutoFocus={(e) => e.preventDefault()}
onCloseAutoFocus={(e) => e.preventDefault()}
onInteractOutside={(e) => {
@@ -77,7 +77,7 @@ export const ClientSelectDropdown = ({
</Button>
</PopoverTrigger_Shadcn_>
</div>
<PopoverContent_Shadcn_ className="mt-0 p-0 max-w-48" side="bottom" align="start" portal>
<PopoverContent_Shadcn_ className="mt-0 p-0 max-w-48" side="bottom" align="start">
<Command_Shadcn_>
<CommandInput_Shadcn_ placeholder="Search..." />
<CommandList_Shadcn_>
@@ -11,7 +11,6 @@ const PopoverTrigger = PopoverPrimitive.Trigger
const PopoverAnchor = PopoverPrimitive.Anchor
type PopoverContentProps = {
portal?: boolean
align?: 'center' | 'start' | 'end'
sideOffset?: number
sameWidthAsTrigger?: boolean
@@ -20,36 +19,23 @@ type PopoverContentProps = {
const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
PopoverContentProps
>(
(
{
className,
align = 'center',
sideOffset = 4,
portal = false,
sameWidthAsTrigger = false,
...props
},
ref
) => {
const Portal = portal ? PopoverPrimitive.Portal : React.Fragment
return (
<Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
sameWidthAsTrigger ? styles['popover-trigger-width'] : '',
'z-50 w-72 rounded-md border border-overlay bg-overlay p-4 text-popover-foreground shadow-md outline-none animate-in data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className
)}
{...props}
/>
</Portal>
)
}
)
>(({ className, align = 'center', sideOffset = 4, sameWidthAsTrigger = false, ...props }, ref) => {
return (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
sameWidthAsTrigger ? styles['popover-trigger-width'] : '',
'z-50 w-72 rounded-md border border-overlay bg-overlay p-4 text-popover-foreground shadow-md outline-none animate-in data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className
)}
{...props}
/>
</PopoverPrimitive.Portal>
)
})
PopoverContent.displayName = 'PopoverContent'
const PopoverSeparator = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
@@ -59,4 +45,4 @@ const PopoverSeparator = React.forwardRef<HTMLDivElement, React.HTMLAttributes<H
)
PopoverSeparator.displayName = 'PopoverSeparator'
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverSeparator }
export { Popover, PopoverAnchor, PopoverContent, PopoverSeparator, PopoverTrigger }