mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 01:45:10 +03:00
## Problem People using screen readers can't find how to navigate back to the organization dashboard. ## Solution - Add an invisible label for screen readers - Add a tooltip for all users <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a tooltip to the home navigation icon on hover (“Back to organization home”). * Enhanced app layout dropdowns to accept custom trigger content, improving accessibility with updated labels for branches, organizations, and projects. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
103 lines
3.4 KiB
TypeScript
103 lines
3.4 KiB
TypeScript
import { useParams } from 'common'
|
|
import { Boxes } from 'lucide-react'
|
|
import { useRouter } from 'next/router'
|
|
import { useState } from 'react'
|
|
import { Badge, cn } from 'ui'
|
|
import { GenericSkeletonLoader, ShimmeringLoader } from 'ui-patterns/ShimmeringLoader'
|
|
|
|
import {
|
|
AppLayoutDropdownError,
|
|
AppLayoutDropdownTriggerButton,
|
|
AppLayoutDropdownWithPopover,
|
|
} from './AppLayoutDropdown'
|
|
import { OrganizationDropdownCommandContent } from './OrganizationDropdownCommandContent'
|
|
import { useEmbeddedCloseHandler } from './useEmbeddedCloseHandler'
|
|
import PartnerIcon from '@/components/ui/PartnerIcon'
|
|
import { useOrganizationsQuery } from '@/data/organizations/organizations-query'
|
|
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
|
|
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
|
|
import { useTrack } from '@/lib/telemetry/track'
|
|
|
|
interface OrganizationDropdownProps {
|
|
embedded?: boolean
|
|
className?: string
|
|
onClose?: () => void
|
|
}
|
|
|
|
export const OrganizationDropdown = ({
|
|
embedded = false,
|
|
className,
|
|
onClose,
|
|
}: OrganizationDropdownProps = {}) => {
|
|
const router = useRouter()
|
|
const { slug: routeSlug } = useParams()
|
|
const { data: selectedOrganization } = useSelectedOrganizationQuery()
|
|
const {
|
|
data: organizations,
|
|
isPending: isLoadingOrganizations,
|
|
isError,
|
|
} = useOrganizationsQuery()
|
|
|
|
const organizationCreationEnabled = useIsFeatureEnabled('organizations:create')
|
|
|
|
const slug = selectedOrganization?.slug
|
|
const orgName = selectedOrganization?.name
|
|
|
|
const [open, setOpen] = useState(false)
|
|
const close = useEmbeddedCloseHandler(embedded, onClose, setOpen)
|
|
const track = useTrack()
|
|
|
|
const handleOpenChange = (next: boolean) => {
|
|
if (next) track('header_organization_dropdown_opened')
|
|
setOpen(next)
|
|
}
|
|
|
|
if (isLoadingOrganizations && !embedded)
|
|
return <ShimmeringLoader className="p-2 md:mr-2 w-[90px]" />
|
|
|
|
if (isError) return <AppLayoutDropdownError message="Failed to load organizations" />
|
|
|
|
const commandContent = (
|
|
<OrganizationDropdownCommandContent
|
|
embedded={embedded}
|
|
className={className}
|
|
organizations={organizations ?? []}
|
|
selectedSlug={slug}
|
|
routePathname={router.pathname}
|
|
hasRouteSlug={!!routeSlug}
|
|
organizationCreationEnabled={organizationCreationEnabled}
|
|
onClose={close}
|
|
/>
|
|
)
|
|
|
|
if (embedded)
|
|
return isLoadingOrganizations ? <GenericSkeletonLoader className="p-2" /> : commandContent
|
|
|
|
return (
|
|
<AppLayoutDropdownWithPopover
|
|
linkHref={slug ? `/org/${slug}` : '/organizations'}
|
|
linkContent={
|
|
<>
|
|
<Boxes size={14} strokeWidth={1.5} className="text-foreground-lighter" />
|
|
<span
|
|
className={cn(
|
|
'md:max-w-32 lg:max-w-none truncate hidden md:block',
|
|
!!selectedOrganization ? 'text-foreground' : 'text-foreground-lighter'
|
|
)}
|
|
>
|
|
{orgName ?? 'Select an organization'}
|
|
</span>
|
|
{!!selectedOrganization && <PartnerIcon organization={selectedOrganization} />}
|
|
{!!selectedOrganization && (
|
|
<Badge variant="default">{selectedOrganization?.plan.name}</Badge>
|
|
)}
|
|
</>
|
|
}
|
|
commandContent={commandContent}
|
|
open={open}
|
|
onOpenChange={handleOpenChange}
|
|
triggerButton={<AppLayoutDropdownTriggerButton aria-label="Show organizations" />}
|
|
/>
|
|
)
|
|
}
|