mirror of
https://github.com/supabase/supabase.git
synced 2026-10-11 04:15:04 +03:00
## Problem The `_Shadcn_` suffix isn't needed anymore on `Command` components ## Solution - Remove the `_Shadcn_` suffix - Simplify UI package exports - Apply prettier <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Simplified command component imports and exports across the UI library by removing internal naming aliases and adopting direct component references. Updated the public UI package barrel export to use wildcard re-exports for cleaner API surface. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46153?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
164 lines
6.1 KiB
TypeScript
164 lines
6.1 KiB
TypeScript
import { useFlag } from 'common'
|
|
import { CheckIcon, ChevronsUpDown, Globe } from 'lucide-react'
|
|
import { useId, useMemo, useState } from 'react'
|
|
import {
|
|
Button,
|
|
Card,
|
|
CardContent,
|
|
cn,
|
|
Command,
|
|
CommandEmpty,
|
|
CommandGroup,
|
|
CommandInput,
|
|
CommandItem,
|
|
CommandList,
|
|
Popover,
|
|
PopoverContent,
|
|
PopoverTrigger,
|
|
ScrollArea,
|
|
} from 'ui'
|
|
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
|
|
import {
|
|
PageSection,
|
|
PageSectionContent,
|
|
PageSectionDescription,
|
|
PageSectionMeta,
|
|
PageSectionSummary,
|
|
PageSectionTitle,
|
|
} from 'ui-patterns/PageSection'
|
|
|
|
import { findTimezoneByIana, TIMEZONES_BY_IANA } from '@/lib/constants/timezones'
|
|
import { useTimezone } from '@/lib/datetime'
|
|
import { guessLocalTimezone } from '@/lib/dayjs'
|
|
import { useTrack } from '@/lib/telemetry/track'
|
|
|
|
const AUTO_OPTION_VALUE = '__auto__'
|
|
|
|
export const TimezoneSettings = () => {
|
|
const timezonePickerEnabled = useFlag('timezonePicker')
|
|
const { timezone, storedTimezone, setTimezone, isAutoDetected } = useTimezone()
|
|
const track = useTrack()
|
|
const [open, setOpen] = useState(false)
|
|
const listboxId = useId()
|
|
|
|
// Browser timezone is captured once and stays stable even when the user has
|
|
// overridden the dashboard timezone — that's the value the "Auto detect"
|
|
// option will revert to.
|
|
const browserTimezone = useMemo(() => guessLocalTimezone(), [])
|
|
|
|
const triggerLabel = useMemo(() => findTimezoneByIana(timezone)?.text ?? timezone, [timezone])
|
|
|
|
if (!timezonePickerEnabled) return null
|
|
|
|
const handleSelect = (nextStored: string) => {
|
|
setTimezone(nextStored)
|
|
const resolvedNext = nextStored || guessLocalTimezone()
|
|
track('timezone_picker_clicked', {
|
|
previousTimezone: timezone,
|
|
nextTimezone: resolvedNext,
|
|
isAutoDetected: nextStored === '',
|
|
source: 'account_preferences',
|
|
})
|
|
setOpen(false)
|
|
}
|
|
|
|
return (
|
|
<PageSection>
|
|
<PageSectionMeta>
|
|
<PageSectionSummary>
|
|
<PageSectionTitle>Timezone</PageSectionTitle>
|
|
<PageSectionDescription>
|
|
Choose how dates and times in logs and other dashboard surfaces are displayed.
|
|
</PageSectionDescription>
|
|
</PageSectionSummary>
|
|
</PageSectionMeta>
|
|
<PageSectionContent>
|
|
<Card>
|
|
<CardContent>
|
|
<FormItemLayout
|
|
isReactForm={false}
|
|
label="Display timezone"
|
|
layout="flex-row-reverse"
|
|
description={
|
|
isAutoDetected
|
|
? `Auto detected from your browser (${browserTimezone}).`
|
|
: 'Pick "Auto detect" to follow your browser timezone again.'
|
|
}
|
|
>
|
|
<Popover open={open} onOpenChange={setOpen}>
|
|
<PopoverTrigger asChild>
|
|
<Button
|
|
role="combobox"
|
|
aria-expanded={open}
|
|
aria-controls={listboxId}
|
|
className="w-full justify-between"
|
|
type="default"
|
|
size="small"
|
|
icon={<Globe />}
|
|
iconRight={<ChevronsUpDown size={14} strokeWidth={1.5} />}
|
|
>
|
|
<span className="truncate text-left">
|
|
{isAutoDetected ? `Auto detect (${timezone})` : triggerLabel}
|
|
</span>
|
|
</Button>
|
|
</PopoverTrigger>
|
|
<PopoverContent id={listboxId} className="w-[--radix-popover-trigger-width] p-0">
|
|
<Command>
|
|
<CommandInput placeholder="Search timezone..." className="h-9" />
|
|
<CommandList>
|
|
<CommandEmpty>No timezones found</CommandEmpty>
|
|
<CommandGroup>
|
|
<ScrollArea className="h-72">
|
|
<CommandItem
|
|
key={AUTO_OPTION_VALUE}
|
|
value={`Auto detect ${browserTimezone}`}
|
|
onSelect={() => handleSelect('')}
|
|
>
|
|
<div className="flex flex-col">
|
|
<span>Auto detect</span>
|
|
<span className="text-xs text-foreground-lighter">
|
|
{browserTimezone}
|
|
</span>
|
|
</div>
|
|
<CheckIcon
|
|
className={cn(
|
|
'ml-auto h-4 w-4',
|
|
isAutoDetected ? 'opacity-100' : 'opacity-0'
|
|
)}
|
|
/>
|
|
</CommandItem>
|
|
{TIMEZONES_BY_IANA.map((entry) => {
|
|
const ianaName = entry.utc[0]
|
|
const isSelected = !isAutoDetected && storedTimezone === ianaName
|
|
return (
|
|
<CommandItem
|
|
key={ianaName}
|
|
// CommandItem matches against the `value` prop for the input filter — include
|
|
// both the human label and the IANA name so search works for either.
|
|
value={`${entry.text} ${ianaName}`}
|
|
onSelect={() => handleSelect(ianaName)}
|
|
>
|
|
{entry.text}
|
|
<CheckIcon
|
|
className={cn(
|
|
'ml-auto h-4 w-4',
|
|
isSelected ? 'opacity-100' : 'opacity-0'
|
|
)}
|
|
/>
|
|
</CommandItem>
|
|
)
|
|
})}
|
|
</ScrollArea>
|
|
</CommandGroup>
|
|
</CommandList>
|
|
</Command>
|
|
</PopoverContent>
|
|
</Popover>
|
|
</FormItemLayout>
|
|
</CardContent>
|
|
</Card>
|
|
</PageSectionContent>
|
|
</PageSection>
|
|
)
|
|
}
|