fix(webui): improve mobile responsiveness

This commit is contained in:
chengyongru 2026-06-14 16:46:34 +08:00 committed by Xubin Ren
parent f30ef9f28e
commit 946ed6690a
9 changed files with 44 additions and 38 deletions

View File

@ -69,6 +69,7 @@ const COMPLETED_RUNS_STORAGE_KEY = "nanobot-webui.sidebar.completed-runs.v1";
const RESTART_STARTED_KEY = "nanobot-webui.restartStartedAt"; const RESTART_STARTED_KEY = "nanobot-webui.restartStartedAt";
const SIDEBAR_WIDTH = 272; const SIDEBAR_WIDTH = 272;
const SIDEBAR_RAIL_WIDTH = 56; const SIDEBAR_RAIL_WIDTH = 56;
const MOBILE_SIDEBAR_WIDTH = `min(${SIDEBAR_WIDTH}px, calc(100vw - 0.75rem))`;
const TOKEN_REFRESH_MARGIN_MS = 30_000; const TOKEN_REFRESH_MARGIN_MS = 30_000;
const TOKEN_REFRESH_MIN_DELAY_MS = 5_000; const TOKEN_REFRESH_MIN_DELAY_MS = 5_000;
type ShellView = "chat" | "settings" | "apps" | "skills"; type ShellView = "chat" | "settings" | "apps" | "skills";
@ -1498,7 +1499,7 @@ function Shell({
showCloseButton={false} showCloseButton={false}
aria-describedby={undefined} aria-describedby={undefined}
className="p-0 lg:hidden" className="p-0 lg:hidden"
style={{ width: SIDEBAR_WIDTH, maxWidth: SIDEBAR_WIDTH }} style={{ width: MOBILE_SIDEBAR_WIDTH, maxWidth: MOBILE_SIDEBAR_WIDTH }}
> >
<SheetTitle className="sr-only">{t("sidebar.navigation")}</SheetTitle> <SheetTitle className="sr-only">{t("sidebar.navigation")}</SheetTitle>
<Sidebar <Sidebar
@ -1604,7 +1605,7 @@ function Shell({
{restartToast ? ( {restartToast ? (
<div <div
role="status" role="status"
className="fixed left-1/2 top-4 z-50 -translate-x-1/2 rounded-full border border-border/70 bg-popover px-4 py-2 text-sm font-medium text-popover-foreground shadow-lg" className="fixed left-1/2 top-[calc(0.75rem+env(safe-area-inset-top))] z-50 max-w-[calc(100vw-1rem)] -translate-x-1/2 rounded-full border border-border/70 bg-popover px-4 py-2 text-sm font-medium text-popover-foreground shadow-lg"
> >
{restartToast} {restartToast}
</div> </div>

View File

@ -80,7 +80,7 @@ export function DeleteConfirm({
</div> </div>
) : null} ) : null}
</AlertDialogHeader> </AlertDialogHeader>
<AlertDialogFooter className="mt-7 grid grid-cols-2 gap-3 space-x-0"> <AlertDialogFooter className="mt-7 grid grid-cols-1 gap-3 space-x-0 sm:grid-cols-2">
<AlertDialogCancel <AlertDialogCancel
onClick={onCancel} onClick={onCancel}
className="mt-0 h-11 rounded-full border-0 bg-muted/70 px-5 text-[15px] font-semibold text-foreground shadow-none hover:bg-muted" className="mt-0 h-11 rounded-full border-0 bg-muted/70 px-5 text-[15px] font-semibold text-foreground shadow-none hover:bg-muted"

View File

@ -107,7 +107,7 @@ export function FilePreviewPanel({
"--file-preview-slot-width": !entered || isClosing ? "0px" : `${desktopWidth}px`, "--file-preview-slot-width": !entered || isClosing ? "0px" : `${desktopWidth}px`,
} as CSSProperties} } as CSSProperties}
className={cn( className={cn(
"absolute inset-y-0 right-0 z-30 w-[min(92vw,var(--file-preview-slot-width))] overflow-hidden", "absolute inset-y-0 right-0 z-30 w-[min(100vw,var(--file-preview-slot-width))] overflow-hidden",
"transition-[width] duration-300 ease-out will-change-[width]", "transition-[width] duration-300 ease-out will-change-[width]",
"md:relative md:z-auto md:w-[var(--file-preview-slot-width)] md:min-w-0 md:shrink-0", "md:relative md:z-auto md:w-[var(--file-preview-slot-width)] md:min-w-0 md:shrink-0",
isClosing && "pointer-events-none", isClosing && "pointer-events-none",
@ -117,7 +117,7 @@ export function FilePreviewPanel({
> >
<div <div
className={cn( className={cn(
"absolute inset-y-0 right-0 flex w-[min(92vw,var(--file-preview-width))] flex-col overflow-hidden md:w-[var(--file-preview-width)]", "absolute inset-y-0 right-0 flex w-[min(100vw,var(--file-preview-width))] flex-col overflow-hidden pb-[env(safe-area-inset-bottom)] md:w-[var(--file-preview-width)] md:pb-0",
"border-l border-border/70 bg-background shadow-2xl md:shadow-none", "border-l border-border/70 bg-background shadow-2xl md:shadow-none",
"transition-[opacity,transform] duration-300 ease-out will-change-transform", "transition-[opacity,transform] duration-300 ease-out will-change-transform",
!entered || isClosing ? "translate-x-full opacity-0" : "translate-x-0 opacity-100", !entered || isClosing ? "translate-x-full opacity-0" : "translate-x-0 opacity-100",

View File

@ -1566,7 +1566,7 @@ export function SettingsView({
<main className="min-w-0 flex-1 overflow-y-auto [scrollbar-gutter:stable]"> <main className="min-w-0 flex-1 overflow-y-auto [scrollbar-gutter:stable]">
<div <div
className={cn( className={cn(
"mx-auto w-full max-w-[920px] px-5 py-8 sm:px-8 lg:py-12", "mx-auto w-full max-w-[920px] px-4 py-6 sm:px-8 sm:py-8 lg:py-12",
hostChromeInset && "pt-[4.25rem] sm:pt-[4.25rem] lg:pt-[4.75rem]", hostChromeInset && "pt-[4.25rem] sm:pt-[4.25rem] lg:pt-[4.75rem]",
)} )}
> >
@ -1652,7 +1652,7 @@ function SettingsSidebar({
return ( return (
<aside <aside
className={cn( className={cn(
"flex w-full shrink-0 flex-col border-b border-border/55 bg-card/62 px-4 pb-3 shadow-[inset_0_-1px_0_rgba(255,255,255,0.55)] backdrop-blur-xl dark:bg-card/45 dark:shadow-none md:w-[17rem] md:border-b-0 md:border-r md:px-3 md:pb-4 md:shadow-[inset_-1px_0_0_rgba(255,255,255,0.55)]", "flex w-full shrink-0 flex-col border-b border-border/55 bg-card/62 px-3 pb-2 shadow-[inset_0_-1px_0_rgba(255,255,255,0.55)] backdrop-blur-xl dark:bg-card/45 dark:shadow-none md:w-[17rem] md:border-b-0 md:border-r md:px-3 md:pb-4 md:shadow-[inset_-1px_0_0_rgba(255,255,255,0.55)]",
hostChromeInset ? "pt-[4.25rem] md:pt-[4.25rem]" : "pt-4 md:pt-4", hostChromeInset ? "pt-[4.25rem] md:pt-[4.25rem]" : "pt-4 md:pt-4",
)} )}
> >
@ -5556,7 +5556,7 @@ function SettingsRow({
</div> </div>
) : null} ) : null}
</div> </div>
{children ? <div className="shrink-0 sm:ml-6">{children}</div> : null} {children ? <div className="min-w-0 sm:ml-6 sm:shrink-0">{children}</div> : null}
</div> </div>
); );
} }
@ -5572,7 +5572,7 @@ function ReadOnlyRow({
}) { }) {
return ( return (
<SettingsRow title={title} description={description}> <SettingsRow title={title} description={description}>
<span className="block max-w-[320px] truncate text-right text-[13px] text-muted-foreground"> <span className="block max-w-full truncate text-left text-[13px] text-muted-foreground sm:max-w-[320px] sm:text-right">
{value} {value}
</span> </span>
</SettingsRow> </SettingsRow>
@ -6018,7 +6018,7 @@ function NumberInput({
const parsed = Number(event.target.value); const parsed = Number(event.target.value);
if (Number.isFinite(parsed)) onChange(parsed); if (Number.isFinite(parsed)) onChange(parsed);
}} }}
className="h-8 w-24 rounded-full text-[13px]" className="h-8 w-24 max-w-full rounded-full text-[13px]"
/> />
{suffix ? <span className="text-[12px] text-muted-foreground">{suffix}</span> : null} {suffix ? <span className="text-[12px] text-muted-foreground">{suffix}</span> : null}
</div> </div>

View File

@ -177,7 +177,7 @@ export function TokenUsageHeatmap({
return ( return (
<div className="overflow-x-auto pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"> <div className="overflow-x-auto pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden">
<div className="mx-auto w-full min-w-[760px] max-w-[1054px] px-0.5"> <div className="mx-auto w-full min-w-0 max-w-[1054px] px-0.5 sm:min-w-[760px]">
<div className="mb-2 flex justify-end"> <div className="mb-2 flex justify-end">
<span className="text-[11px] font-normal leading-none text-muted-foreground/64"> <span className="text-[11px] font-normal leading-none text-muted-foreground/64">
{tx("settings.usage.shortTitle", "Token Usage")} {tx("settings.usage.shortTitle", "Token Usage")}
@ -195,7 +195,7 @@ export function TokenUsageHeatmap({
))} ))}
</div> </div>
<div <div
className="grid grid-flow-col grid-rows-7 gap-1.5" className="grid grid-flow-col grid-rows-7 gap-[3px] sm:gap-1.5"
style={{ gridTemplateColumns: `repeat(${TOKEN_HEATMAP_COLUMNS}, minmax(0, 1fr))` }} style={{ gridTemplateColumns: `repeat(${TOKEN_HEATMAP_COLUMNS}, minmax(0, 1fr))` }}
aria-label={tx("settings.usage.title", "Token activity")} aria-label={tx("settings.usage.title", "Token activity")}
> >
@ -224,7 +224,7 @@ export function TokenUsageHeatmap({
<span <span
aria-label={ariaLabel} aria-label={ariaLabel}
className={cn( className={cn(
"aspect-square w-full rounded-[4px] transition-transform hover:scale-110", "aspect-square w-full rounded-[2px] transition-transform hover:scale-110 sm:rounded-[4px]",
tokenUsageCellClass(level, cell.future), tokenUsageCellClass(level, cell.future),
)} )}
/> />

View File

@ -1544,10 +1544,10 @@ export function ThreadComposer({
"w-full resize-none bg-transparent", "w-full resize-none bg-transparent",
isHero isHero
? cn( ? cn(
"min-h-[78px] px-5 text-[15px] leading-6", "min-h-[78px] px-4 text-[15px] leading-6 sm:px-5",
relaxedHeroInput ? "pb-2 pt-[27px]" : "pb-1.5 pt-4", relaxedHeroInput ? "pb-2 pt-[27px]" : "pb-1.5 pt-4",
) )
: "min-h-[50px] px-4 pb-1.5 pt-3 text-[13.5px] leading-5", : "min-h-[50px] px-3.5 pb-1.5 pt-3 text-[13.5px] leading-5 sm:px-4",
); );
return ( return (
@ -1699,11 +1699,13 @@ export function ThreadComposer({
) : null} ) : null}
<div <div
className={cn( className={cn(
"flex items-center justify-between", "flex flex-wrap items-center justify-between gap-y-2",
isHero ? cn("gap-1.5 px-4", showProjectPicker ? "pb-1.5" : "pb-3.5") : "gap-2 px-3 pb-2", isHero
? cn("gap-x-1.5 px-3 sm:px-4", showProjectPicker ? "pb-1.5" : "pb-3.5")
: "gap-x-2 px-2.5 pb-2 sm:px-3",
)} )}
> >
<div className={cn("flex min-w-0 flex-1 items-center", isHero ? "gap-1.5" : "gap-2")}> <div className={cn("flex min-w-0 flex-1 basis-[8rem] items-center", isHero ? "gap-1.5" : "gap-2")}>
<input <input
ref={fileInputRef} ref={fileInputRef}
type="file" type="file"
@ -1746,7 +1748,7 @@ export function ThreadComposer({
/> />
) : null} ) : null}
</div> </div>
<div className={cn("flex shrink-0 items-center", isHero ? "gap-1.5" : "gap-2")}> <div className={cn("ml-auto flex min-w-0 shrink-0 items-center", isHero ? "gap-1.5" : "gap-2")}>
{modelLabel && !voiceRecorder.isRecording ? ( {modelLabel && !voiceRecorder.isRecording ? (
<ComposerModelBadge <ComposerModelBadge
label={modelLabel} label={modelLabel}
@ -1768,6 +1770,7 @@ export function ThreadComposer({
disabled={voiceRecorder.buttonDisabled} disabled={voiceRecorder.buttonDisabled}
aria-label={voiceButtonLabel} aria-label={voiceButtonLabel}
aria-keyshortcuts={VOICE_SHORTCUT_ARIA} aria-keyshortcuts={VOICE_SHORTCUT_ARIA}
title={voiceButtonTooltip}
onPointerDown={voiceRecorder.beginPress} onPointerDown={voiceRecorder.beginPress}
onPointerUp={voiceRecorder.endPress} onPointerUp={voiceRecorder.endPress}
onPointerCancel={voiceRecorder.endPress} onPointerCancel={voiceRecorder.endPress}
@ -2071,7 +2074,9 @@ function ComposerModelBadge({
"shadow-[0_2px_8px_rgba(15,23,42,0.045)]", "shadow-[0_2px_8px_rgba(15,23,42,0.045)]",
interactive && "cursor-pointer hover:bg-accent/55 hover:text-foreground", interactive && "cursor-pointer hover:bg-accent/55 hover:text-foreground",
needsSetup && "border-amber-500/35 bg-amber-50/70 text-amber-900 dark:bg-amber-500/10 dark:text-amber-200", needsSetup && "border-amber-500/35 bg-amber-50/70 text-amber-900 dark:bg-amber-500/10 dark:text-amber-200",
isHero ? "h-8 max-w-[12.5rem] gap-1.5 px-2 text-[11.5px]" : "h-9 max-w-[12rem] gap-2 px-2.5 text-[12px]", isHero
? "h-8 max-w-[min(12.5rem,44vw)] gap-1.5 px-2 text-[11.5px]"
: "h-9 max-w-[min(12rem,44vw)] gap-2 px-2.5 text-[12px]",
)} )}
> >
<span <span
@ -2252,7 +2257,7 @@ function CliAppMentionPalette({
onChoose(candidate); onChoose(candidate);
}} }}
className={cn( className={cn(
"flex h-10 w-full items-center gap-2.5 rounded-[13px] px-2.5 text-left transition-colors", "flex min-h-10 w-full items-center gap-2.5 rounded-[13px] px-2.5 py-1.5 text-left transition-colors",
selected selected
? "bg-foreground/[0.055] text-foreground" ? "bg-foreground/[0.055] text-foreground"
: "text-foreground/90 hover:bg-foreground/[0.04]", : "text-foreground/90 hover:bg-foreground/[0.04]",
@ -2260,7 +2265,7 @@ function CliAppMentionPalette({
> >
<MentionCandidateLogo candidate={candidate} selected={selected} /> <MentionCandidateLogo candidate={candidate} selected={selected} />
<span className="flex min-w-0 flex-1 items-baseline gap-2"> <span className="flex min-w-0 flex-1 items-baseline gap-2">
<span className="shrink-0 text-[15px] font-medium tracking-normal text-foreground"> <span className="min-w-0 truncate text-[15px] font-medium tracking-normal text-foreground">
{displayName} {displayName}
</span> </span>
<span className="truncate text-[15px] font-normal tracking-normal text-muted-foreground/72"> <span className="truncate text-[15px] font-normal tracking-normal text-muted-foreground/72">
@ -2396,7 +2401,7 @@ function SlashCommandPalette({
> >
<Icon className="h-4 w-4" /> <Icon className="h-4 w-4" />
</span> </span>
<span className="flex min-w-0 flex-1 items-baseline gap-2"> <span className="flex min-w-0 flex-1 flex-col gap-0.5 sm:flex-row sm:items-baseline sm:gap-2">
<span className="min-w-0 truncate text-[13.5px] font-semibold tracking-normal text-foreground"> <span className="min-w-0 truncate text-[13.5px] font-semibold tracking-normal text-foreground">
{title} {title}
</span> </span>
@ -2404,7 +2409,7 @@ function SlashCommandPalette({
{command.detail || description} {command.detail || description}
</span> </span>
</span> </span>
<span className="ml-2 flex shrink-0 items-center gap-1.5"> <span className="ml-2 flex max-w-[42%] shrink-0 items-center gap-1.5 sm:max-w-none">
{command.badge || command.recent ? ( {command.badge || command.recent ? (
<span className="hidden rounded-full bg-foreground/[0.055] px-2 py-1 text-[11px] font-medium text-muted-foreground sm:inline-flex"> <span className="hidden rounded-full bg-foreground/[0.055] px-2 py-1 text-[11px] font-medium text-muted-foreground sm:inline-flex">
{command.badge ?? t("thread.composer.slash.badges.recent")} {command.badge ?? t("thread.composer.slash.badges.recent")}
@ -2486,7 +2491,7 @@ function AttachmentChip({
) : null} ) : null}
</div> </div>
<div className="flex min-w-0 flex-col text-[11.5px] leading-4"> <div className="flex min-w-0 flex-col text-[11.5px] leading-4">
<span className="truncate max-w-[14rem] font-medium" title={image.file.name}> <span className="max-w-[min(14rem,calc(100vw-8rem))] truncate font-medium" title={image.file.name}>
{image.file.name} {image.file.name}
</span> </span>
<span className="truncate text-muted-foreground"> <span className="truncate text-muted-foreground">

View File

@ -725,7 +725,7 @@ export function ThreadShell({
</div> </div>
) : ( ) : (
<div className="flex w-full flex-col items-center text-center animate-in fade-in-0 slide-in-from-bottom-2 duration-500"> <div className="flex w-full flex-col items-center text-center animate-in fade-in-0 slide-in-from-bottom-2 duration-500">
<h1 className="text-balance text-[40px] font-normal leading-tight tracking-[-0.045em] text-foreground sm:text-[48px]"> <h1 className="max-w-[30rem] text-balance text-[34px] font-normal leading-[1.08] tracking-normal text-foreground sm:text-[48px] sm:leading-tight">
{t(heroGreetingKey)} {t(heroGreetingKey)}
</h1> </h1>
</div> </div>

View File

@ -335,7 +335,7 @@ export const ThreadViewport = forwardRef<ThreadViewportHandle, ThreadViewportPro
> >
{hasMessages ? ( {hasMessages ? (
<div ref={contentRef} className="mx-auto flex min-h-full w-full max-w-[64rem] flex-col"> <div ref={contentRef} className="mx-auto flex min-h-full w-full max-w-[64rem] flex-col">
<div className="flex-1 px-4 pb-20 pt-4"> <div className="flex-1 px-3 pb-[calc(5rem+env(safe-area-inset-bottom))] pt-4 sm:px-4">
<div className="mx-auto w-full max-w-[49.5rem]"> <div className="mx-auto w-full max-w-[49.5rem]">
<ThreadMessages <ThreadMessages
messages={visibleMessages} messages={visibleMessages}
@ -355,16 +355,16 @@ export const ThreadViewport = forwardRef<ThreadViewportHandle, ThreadViewportPro
data-testid="thread-composer-dock" data-testid="thread-composer-dock"
className="sticky bottom-0 z-10 mt-auto bg-background" className="sticky bottom-0 z-10 mt-auto bg-background"
> >
<div className="px-4 pb-3"> <div className="px-3 pb-[calc(0.75rem+env(safe-area-inset-bottom))] sm:px-4">
{composer} {composer}
</div> </div>
</div> </div>
</div> </div>
) : ( ) : (
<div ref={contentRef} className="mx-auto flex min-h-full w-full max-w-[72rem] flex-col px-4"> <div ref={contentRef} className="mx-auto flex min-h-full w-full max-w-[72rem] flex-col px-3 sm:px-4">
<div className="flex w-full flex-1 items-center justify-center py-10 sm:py-12"> <div className="flex w-full flex-1 items-center justify-center py-6 sm:py-12">
<div className="relative w-full max-w-[58rem]"> <div className="relative flex w-full max-w-[58rem] flex-col items-center gap-5 sm:block">
<div className="absolute inset-x-0 bottom-[calc(100%+1.5rem)] flex justify-center"> <div className="flex justify-center sm:absolute sm:inset-x-0 sm:bottom-[calc(100%+1.5rem)]">
{emptyState} {emptyState}
</div> </div>
<div className="w-full">{composer}</div> <div className="w-full">{composer}</div>

View File

@ -106,7 +106,7 @@ export function WorkspaceProjectPicker({
if (nativeProjectPicker) { if (nativeProjectPicker) {
return ( return (
<div className="flex items-center rounded-b-[28px] border-t border-border/25 bg-muted/60 px-4 py-1.5 dark:bg-white/[0.055]"> <div className="flex min-w-0 items-center rounded-b-[28px] border-t border-border/25 bg-muted/60 px-3 py-1.5 dark:bg-white/[0.055] sm:px-4">
<button <button
type="button" type="button"
disabled={disabled || pickingFolder} disabled={disabled || pickingFolder}
@ -114,7 +114,7 @@ export function WorkspaceProjectPicker({
title={currentProjectScope?.project_path} title={currentProjectScope?.project_path}
onClick={() => void pickNativeFolder()} onClick={() => void pickNativeFolder()}
className={cn( className={cn(
"inline-flex h-7 max-w-[18rem] items-center gap-2 rounded-full px-2.5", "inline-flex h-7 max-w-full items-center gap-2 rounded-full px-2.5 sm:max-w-[18rem]",
"text-[12px] font-medium text-muted-foreground/90 transition-colors", "text-[12px] font-medium text-muted-foreground/90 transition-colors",
"hover:bg-background/70 hover:text-foreground disabled:pointer-events-none disabled:opacity-55", "hover:bg-background/70 hover:text-foreground disabled:pointer-events-none disabled:opacity-55",
currentProjectScope && "text-foreground/82", currentProjectScope && "text-foreground/82",
@ -124,7 +124,7 @@ export function WorkspaceProjectPicker({
<span className="truncate">{projectLabel}</span> <span className="truncate">{projectLabel}</span>
</button> </button>
{pathError || error ? ( {pathError || error ? (
<span role="alert" className="ml-2 truncate text-[11.5px] font-medium text-destructive"> <span role="alert" className="ml-2 min-w-0 truncate text-[11.5px] font-medium text-destructive">
{pathError ?? error} {pathError ?? error}
</span> </span>
) : null} ) : null}
@ -133,7 +133,7 @@ export function WorkspaceProjectPicker({
} }
return ( return (
<div className="flex items-center rounded-b-[28px] border-t border-border/25 bg-muted/60 px-4 py-1.5 dark:bg-white/[0.055]"> <div className="flex min-w-0 items-center rounded-b-[28px] border-t border-border/25 bg-muted/60 px-3 py-1.5 dark:bg-white/[0.055] sm:px-4">
<DropdownMenu open={open} onOpenChange={setOpen}> <DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<button <button
@ -141,7 +141,7 @@ export function WorkspaceProjectPicker({
disabled={disabled} disabled={disabled}
aria-label={t("thread.composer.workspace.projectAria")} aria-label={t("thread.composer.workspace.projectAria")}
className={cn( className={cn(
"inline-flex h-7 max-w-[18rem] items-center gap-2 rounded-full px-2.5", "inline-flex h-7 max-w-full items-center gap-2 rounded-full px-2.5 sm:max-w-[18rem]",
"text-[12px] font-medium text-muted-foreground/90 transition-colors", "text-[12px] font-medium text-muted-foreground/90 transition-colors",
"hover:bg-background/70 hover:text-foreground disabled:pointer-events-none disabled:opacity-55", "hover:bg-background/70 hover:text-foreground disabled:pointer-events-none disabled:opacity-55",
currentProjectScope && "text-foreground/82", currentProjectScope && "text-foreground/82",
@ -254,7 +254,7 @@ export function WorkspaceAccessMenu({
variant="ghost" variant="ghost"
aria-label={t("thread.composer.workspace.accessAria")} aria-label={t("thread.composer.workspace.accessAria")}
className={cn( className={cn(
"max-w-[12.5rem] rounded-[10px] border border-transparent font-semibold shadow-none", "max-w-[min(12.5rem,42vw)] rounded-[10px] border border-transparent font-semibold shadow-none",
isHero ? "h-8 px-2.5 text-[12px]" : "h-9 px-3 text-[12.5px]", isHero ? "h-8 px-2.5 text-[12px]" : "h-9 px-3 text-[12.5px]",
isFull isFull
? "bg-transparent text-orange-600 hover:bg-orange-500/8 dark:text-orange-300 dark:hover:bg-orange-400/10" ? "bg-transparent text-orange-600 hover:bg-orange-500/8 dark:text-orange-300 dark:hover:bg-orange-400/10"