Files
supabase/apps/studio/components/layouts/AppLayout/AppLayoutDropdown.tsx
Gildas GarciaandIvan Vasilov 96d43099bb chore: refactor Button API so that it can be used a standard button (#46880)
## Problem

Our `<Button>` component breaks the default `button` contract by
redefining the `type` prop to set its variant (`primary`, `default`,
etc) instead of the button type (`submit`, `button`, etc).
This is confusing and forces to write more code when using it with
shadcn components that expect/inject the standard button props.

## Solution

- rename the `type` prop to `variant`
- rename the `htmlType` prop to `type`
- propagate the changes where necessary
- format code

## How to test

As this is just prop renaming, if it builds it's ok

---------

Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
2026-06-16 23:59:58 +02:00

73 lines
2.1 KiB
TypeScript

import { AlertCircle, ChevronsUpDown } from 'lucide-react'
import Link from 'next/link'
import { forwardRef, type ReactNode } from 'react'
import { Button, cn, Popover, PopoverContent, PopoverTrigger } from 'ui'
interface AppLayoutDropdownErrorProps {
message: string
}
export function AppLayoutDropdownError({ message }: AppLayoutDropdownErrorProps) {
return (
<div className="flex items-center space-x-2 text-amber-900">
<AlertCircle size={16} strokeWidth={1.5} />
<p className="text-sm">{message}</p>
</div>
)
}
interface AppLayoutDropdownTriggerButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
className?: string
}
export const AppLayoutDropdownTriggerButton = forwardRef<
HTMLButtonElement,
AppLayoutDropdownTriggerButtonProps
>(({ className, ...props }, ref) => (
<Button
ref={ref}
size="tiny"
className={cn('px-1.5 py-4 [&_svg]:w-5 [&_svg]:h-5 ml-1', className)}
iconRight={<ChevronsUpDown strokeWidth={1.5} />}
{...props}
variant="text"
/>
))
AppLayoutDropdownTriggerButton.displayName = 'AppLayoutDropdownTriggerButton'
export interface AppLayoutDropdownWithPopoverProps {
linkHref: string
linkContent: ReactNode
linkClassName?: string
commandContent: ReactNode
open: boolean
onOpenChange: (open: boolean) => void
triggerButtonClassName?: string
}
export function AppLayoutDropdownWithPopover({
linkHref,
linkContent,
linkClassName = 'flex items-center gap-2 shrink-0 text-sm',
commandContent,
open,
onOpenChange,
triggerButtonClassName,
}: AppLayoutDropdownWithPopoverProps) {
return (
<Popover open={open} onOpenChange={onOpenChange} modal={false}>
<div className="flex items-center shrink-0">
<Link href={linkHref} className={linkClassName}>
{linkContent}
</Link>
<PopoverTrigger asChild>
<AppLayoutDropdownTriggerButton className={triggerButtonClassName} />
</PopoverTrigger>
</div>
<PopoverContent className="p-0" side="bottom" align="start">
{commandContent}
</PopoverContent>
</Popover>
)
}