mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 18:05:11 +03:00
## Context As per PR title, just adjusting the Assistant's header a little to improve the UX ### Before <img width="442" height="71" alt="image" src="https://github.com/user-attachments/assets/c714e264-7724-451a-aeaf-7ced456d0639" /> ### After <img width="438" height="77" alt="image" src="https://github.com/user-attachments/assets/11467bf2-7306-4ec9-80e0-2aadd959eff1" /> ## Changes involved - Shift permission settings into "More" dropdown - Chat selection is now "history" - Added keyboard shortcuts for history and copy chat ID <img width="185" height="95" alt="image" src="https://github.com/user-attachments/assets/fc1c9bdc-9180-48ba-940f-2f39fef53a1d" /> <img width="287" height="159" alt="image" src="https://github.com/user-attachments/assets/8f597306-9ea0-4282-884b-722bab16e4d0" /> - Chat name is now clickable to directly edit it - Saves on Enter or on blur - Resets on Esc <img width="433" height="70" alt="image" src="https://github.com/user-attachments/assets/f0c6fb4a-c368-4722-97a2-22ae94cc5511" /> <img width="439" height="64" alt="image" src="https://github.com/user-attachments/assets/1eb21aaf-3979-433a-acc2-378b47b79e94" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added keyboard shortcuts to toggle the AI Assistant chat history and copy the active chat ID. * Added shortcut hint pills to AI Assistant tooltips and the “More options” menu. * Enabled inline editing of the active chat name with save/cancel and blur support. * **Improvements** * Refreshed AI Assistant header actions and icons (including “New chat” and menu controls) for clearer navigation. * Updated onboarding header styling with an assistant icon/animation. * Standardized shortcut rendering in tooltip pill formatting. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
87 lines
2.8 KiB
TypeScript
87 lines
2.8 KiB
TypeScript
import { HotkeySequence } from '@tanstack/react-hotkeys'
|
|
import { TooltipContentProps } from '@ui/components/shadcn/ui/tooltip'
|
|
import { Fragment, useState, type ReactNode } from 'react'
|
|
import { KeyboardShortcut, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
|
|
|
|
import { hotkeyToKeys } from '@/state/shortcuts/formatShortcut'
|
|
import { SHORTCUT_DEFINITIONS, type ShortcutId } from '@/state/shortcuts/registry'
|
|
|
|
interface ShortcutTooltipProps {
|
|
shortcutId: ShortcutId
|
|
children: ReactNode
|
|
side?: TooltipContentProps['side']
|
|
align?: TooltipContentProps['align']
|
|
sideOffset?: number
|
|
delayDuration?: number
|
|
/**
|
|
* Override the label from the registry. Use when the wrapped element's
|
|
* action is a narrower/contextual variant of the registered shortcut.
|
|
*/
|
|
label?: string
|
|
/**
|
|
* Override the tooltip's open state. Pass `false` to force the tooltip closed
|
|
* (e.g. while a popover or dialog opened by the wrapped element is visible).
|
|
* Leave `undefined` to let hover/focus drive it. The tooltip is always
|
|
* controlled internally so toggling this prop won't trigger Radix's
|
|
* controlled/uncontrolled warning.
|
|
*/
|
|
open?: boolean
|
|
}
|
|
|
|
/**
|
|
* Wraps any element to show its bound keyboard shortcut on hover/focus, in the
|
|
* style of Linear's shortcut tooltips: `"<label> <key> [then <key>]"`.
|
|
*
|
|
* Uses Radix's `asChild` trigger, so the wrapped element remains fully
|
|
* interactive — clicks, focus, and event handlers pass through untouched.
|
|
*
|
|
* @example
|
|
* <ShortcutTooltip shortcutId={SHORTCUT_IDS.RESULTS_COPY_MARKDOWN}>
|
|
* <Button onClick={handleCopy}>Copy</Button>
|
|
* </ShortcutTooltip>
|
|
*/
|
|
export const ShortcutTooltip = ({
|
|
shortcutId,
|
|
children,
|
|
side,
|
|
align,
|
|
sideOffset,
|
|
delayDuration,
|
|
label: labelOverride,
|
|
open,
|
|
}: ShortcutTooltipProps) => {
|
|
const def = SHORTCUT_DEFINITIONS[shortcutId]
|
|
const label = labelOverride ?? def.label
|
|
|
|
const [hoverOpen, setHoverOpen] = useState(false)
|
|
const resolvedOpen = open ?? hoverOpen
|
|
|
|
return (
|
|
<Tooltip delayDuration={delayDuration} open={resolvedOpen} onOpenChange={setHoverOpen}>
|
|
<TooltipTrigger asChild>{children}</TooltipTrigger>
|
|
<TooltipContent
|
|
side={side}
|
|
align={align}
|
|
sideOffset={sideOffset}
|
|
className="flex items-center gap-2"
|
|
>
|
|
<span>{label}</span>
|
|
<ShortcutPills sequence={def.sequence} />
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
)
|
|
}
|
|
|
|
export const ShortcutPills = ({ sequence }: { sequence: HotkeySequence }) => {
|
|
return (
|
|
<span className="flex items-center gap-1">
|
|
{sequence.map((step, i) => (
|
|
<Fragment key={i}>
|
|
{i > 0 && <span className="text-foreground-lighter text-[11px]">then</span>}
|
|
<KeyboardShortcut keys={hotkeyToKeys(step)} />
|
|
</Fragment>
|
|
))}
|
|
</span>
|
|
)
|
|
}
|