Fix icon sizing, menu colors, and prompt box toggle alignment

- Safelist the lucide class so the icon sizing rule is no longer purged
  and icons scale with their text instead of rendering at 24px
- Use the webapp home colors for the apps page and apps menu tiles, and
  the webapp badge style on the apps page
- Match the top menu active and hover states to the webapp nav, and
  shrink its tooltips to plain 12px text
- Align toggle buttons (Instrumental, sound, etc.) and @Characters with
  the popover triggers beside them
This commit is contained in:
BFlat 2026-09-28 12:14:41 +07:00
parent ba4be8aa6b
commit f41a2b2564
7 changed files with 87 additions and 80 deletions

View File

@ -38,9 +38,9 @@ const AppsQuickMenuSection = ({
onClick={() => goToApp(app.action)}
disabled={!app.action}
className={twMerge(
"group flex w-full items-center gap-3 px-2 py-2 text-left transition-colors",
"group flex w-full items-center gap-3 rounded-[3px] px-2 py-2 text-left transition-colors",
app.action
? "cursor-pointer hover:bg-white/10"
? "cursor-pointer hover:bg-white/[0.08]"
: "cursor-default opacity-60",
)}
>

View File

@ -105,10 +105,10 @@ const APP_CARD_PALETTES: Record<string, AppCardPalette> = {
hoverStyle: "hover:border-blue-400/60 hover:bg-blue-500/10",
},
"image-to-video": {
accent: "from-amber-500/20 to-amber-500/0",
iconBg: "bg-amber-500/20 border-amber-400/40",
iconColor: "text-amber-300",
hoverStyle: "hover:border-amber-400/60 hover:bg-amber-500/10",
accent: "from-purple-500/20 to-purple-500/0",
iconBg: "bg-purple-500/20 border-purple-400/40",
iconColor: "text-purple-300",
hoverStyle: "hover:border-purple-400/60 hover:bg-purple-500/10",
},
"create-audio": {
accent: "from-pink-500/20 to-pink-500/0",
@ -117,17 +117,65 @@ const APP_CARD_PALETTES: Record<string, AppCardPalette> = {
hoverStyle: "hover:border-pink-400/60 hover:bg-pink-500/10",
},
"image-to-3d-object": {
accent: "from-cyan-500/20 to-cyan-500/0",
iconBg: "bg-cyan-500/20 border-cyan-400/40",
iconColor: "text-cyan-300",
hoverStyle: "hover:border-cyan-400/60 hover:bg-cyan-500/10",
},
"image-to-3d-world": {
accent: "from-teal-500/20 to-teal-500/0",
iconBg: "bg-teal-500/20 border-teal-400/40",
iconColor: "text-teal-300",
hoverStyle: "hover:border-teal-400/60 hover:bg-teal-500/10",
},
"3d-editor": {
accent: "from-amber-500/20 to-amber-500/0",
iconBg: "bg-amber-500/20 border-amber-400/40",
iconColor: "text-amber-300",
hoverStyle: "hover:border-amber-400/60 hover:bg-amber-500/10",
},
"background-change": {
accent: "from-emerald-500/20 to-emerald-500/0",
iconBg: "bg-emerald-500/20 border-emerald-400/40",
iconColor: "text-emerald-300",
hoverStyle: "hover:border-emerald-400/60 hover:bg-emerald-500/10",
},
"image-to-3d-world": {
"video-editor": {
accent: "from-rose-500/20 to-rose-500/0",
iconBg: "bg-rose-500/20 border-rose-400/40",
iconColor: "text-rose-300",
hoverStyle: "hover:border-rose-400/60 hover:bg-rose-500/10",
},
moodboard: {
accent: "from-indigo-500/20 to-indigo-500/0",
iconBg: "bg-indigo-500/20 border-indigo-400/40",
iconColor: "text-indigo-300",
hoverStyle: "hover:border-indigo-400/60 hover:bg-indigo-500/10",
},
"video-frame-extractor": {
accent: "from-orange-500/20 to-orange-500/0",
iconBg: "bg-orange-500/20 border-orange-400/40",
iconColor: "text-orange-300",
hoverStyle: "hover:border-orange-400/60 hover:bg-orange-500/10",
},
"edit-image": {
accent: "from-sky-500/20 to-sky-500/0",
iconBg: "bg-sky-500/20 border-sky-400/40",
iconColor: "text-sky-300",
hoverStyle: "hover:border-sky-400/60 hover:bg-sky-500/10",
},
"2d-canvas": {
accent: "from-sky-500/20 to-sky-500/0",
iconBg: "bg-sky-500/20 border-sky-400/40",
iconColor: "text-sky-300",
hoverStyle: "hover:border-sky-400/60 hover:bg-sky-500/10",
},
"remove-background": {
accent: "from-violet-500/20 to-violet-500/0",
iconBg: "bg-violet-500/20 border-violet-400/40",
iconColor: "text-violet-300",
hoverStyle: "hover:border-violet-400/60 hover:bg-violet-500/10",
},
angles: {
accent: "from-lime-500/20 to-lime-500/0",
iconBg: "bg-lime-500/20 border-lime-400/40",
@ -140,59 +188,17 @@ const APP_CARD_PALETTES: Record<string, AppCardPalette> = {
iconColor: "text-fuchsia-300",
hoverStyle: "hover:border-fuchsia-400/60 hover:bg-fuchsia-500/10",
},
"2d-canvas": {
accent: "from-sky-500/20 to-sky-500/0",
iconBg: "bg-sky-500/20 border-sky-400/40",
iconColor: "text-sky-300",
hoverStyle: "hover:border-sky-400/60 hover:bg-sky-500/10",
},
"3d-editor": {
accent: "from-emerald-500/20 to-emerald-500/0",
iconBg: "bg-emerald-500/20 border-emerald-400/40",
iconColor: "text-emerald-300",
hoverStyle: "hover:border-emerald-400/60 hover:bg-emerald-500/10",
},
"edit-image": {
accent: "from-purple-500/20 to-purple-500/0",
iconBg: "bg-purple-500/20 border-purple-400/40",
iconColor: "text-purple-300",
hoverStyle: "hover:border-purple-400/60 hover:bg-purple-500/10",
},
"remove-background": {
accent: "from-violet-500/20 to-violet-500/0",
iconBg: "bg-violet-500/20 border-violet-400/40",
iconColor: "text-violet-300",
hoverStyle: "hover:border-violet-400/60 hover:bg-violet-500/10",
},
"video-frame-extractor": {
accent: "from-rose-500/20 to-rose-500/0",
iconBg: "bg-rose-500/20 border-rose-400/40",
iconColor: "text-rose-300",
hoverStyle: "hover:border-rose-400/60 hover:bg-rose-500/10",
},
"background-change": {
accent: "from-orange-500/20 to-orange-500/0",
iconBg: "bg-orange-500/20 border-orange-400/40",
iconColor: "text-orange-300",
hoverStyle: "hover:border-orange-400/60 hover:bg-orange-500/10",
},
"video-editor": {
accent: "from-teal-500/20 to-teal-500/0",
iconBg: "bg-teal-500/20 border-teal-400/40",
iconColor: "text-teal-300",
hoverStyle: "hover:border-teal-400/60 hover:bg-teal-500/10",
},
"video-watermark-removal": {
accent: "from-cyan-500/20 to-cyan-500/0",
iconBg: "bg-cyan-500/20 border-cyan-400/40",
iconColor: "text-cyan-300",
hoverStyle: "hover:border-cyan-400/60 hover:bg-cyan-500/10",
accent: "from-yellow-500/20 to-yellow-500/0",
iconBg: "bg-yellow-500/20 border-yellow-400/40",
iconColor: "text-yellow-300",
hoverStyle: "hover:border-yellow-400/60 hover:bg-yellow-500/10",
},
"image-watermark-removal": {
accent: "from-indigo-500/20 to-indigo-500/0",
iconBg: "bg-indigo-500/20 border-indigo-400/40",
iconColor: "text-indigo-300",
hoverStyle: "hover:border-indigo-400/60 hover:bg-indigo-500/10",
accent: "from-red-500/20 to-red-500/0",
iconBg: "bg-red-500/20 border-red-400/40",
iconColor: "text-red-300",
hoverStyle: "hover:border-red-400/60 hover:bg-red-500/10",
},
};

View File

@ -90,7 +90,9 @@ function AppCard({ app }: { app: FullAppItem }) {
<span
className={twMerge(
"shrink-0 border px-1.5 py-1 font-mono text-[9px] font-medium leading-none tracking-wider",
getBadgeStyles(app.badge),
app.badge === "SOON"
? getBadgeStyles(app.badge)
: "border-primary/30 text-ui-accent-ink",
)}
>
{app.badge}

View File

@ -326,6 +326,9 @@ export default {
},
plugins: [],
safelist: [
// lucide-react adds this class at runtime; keep the base-layer sizing rule
// in styles/tailwind.css from being purged.
"lucide",
"bg-character-selected",
"bg-character-unselected",
"bg-character-clip",

View File

@ -1,6 +1,6 @@
import type { LucideIcon } from "lucide-react";
import { DynamicIcon } from "@storyteller/icons";
import { Button } from "./button";
import { Button, NEUTRAL_BUTTON_HOVER_CLASSES } from "./button";
import { twMerge } from "tailwind-merge";
interface ToggleButtonProps {
@ -26,14 +26,14 @@ export const ToggleButton = ({
return (
<Button
className={twMerge(
// 34px matches the sibling toolbar controls (GenerateButton, the
// PopoverMenu triggers). Flat control surface + hairline border,
// same idiom as the PopoverMenu triggers beside it.
"flex h-[34px] items-center justify-center rounded-[3px] border border-ui-controls-border bg-ui-controls text-white transition-colors",
// Same box and type as the PopoverMenu triggers beside it (34px,
// text-sm sans, flat control surface + hairline border), overriding
// the Button base's mono uppercase label.
"flex h-[34px] items-center justify-center rounded-[3px] border border-ui-controls-border bg-ui-controls py-0 font-sans text-sm font-medium normal-case tracking-normal text-base-fg transition-colors",
hasLabel ? "px-3" : "w-[34px] p-0",
isActive
? "border-white/30 bg-brand-primary/40 hover:border-white/30 hover:bg-brand-primary/40"
: "hover:bg-ui-controls hover:bg-[linear-gradient(rgba(255,255,255,0.07),rgba(255,255,255,0.07))]",
? "border-white/40 bg-white/10 hover:border-white/40 hover:bg-white/15"
: NEUTRAL_BUTTON_HOVER_CLASSES,
className,
)}
variant="secondary"
@ -47,7 +47,7 @@ export const ToggleButton = ({
/>
)}
{label && (
<span className="whitespace-nowrap text-white/90">{label}</span>
<span className="whitespace-nowrap">{label}</span>
)}
</span>
</Button>

View File

@ -94,7 +94,7 @@ export const MenuIconSelector: React.FC<MenuIconSelectorProps> = ({
{/* Active tab background */}
{selectedIndex >= 0 && (
<div
className="absolute z-10 rounded-[2px] bg-base-fg transition-all duration-150 ease-in-out"
className="absolute z-10 rounded-[2px] bg-base-fg/[0.08] transition-all duration-150 ease-in-out after:absolute after:inset-x-1.5 after:-bottom-1 after:h-0.5 after:bg-base-fg"
style={{
left: activeStyle.left,
width: activeStyle.width,
@ -106,7 +106,7 @@ export const MenuIconSelector: React.FC<MenuIconSelectorProps> = ({
{/* Hover background (only if hovering a different tab) */}
{hoveredIndex !== -1 && hoveredIndex !== selectedIndex && (
<div
className="absolute z-20 rounded-[2px] bg-base-fg/10 transition-all duration-150 ease-in-out pointer-events-none"
className="absolute z-20 rounded-[2px] bg-base-fg/[0.08] transition-all duration-150 ease-in-out pointer-events-none"
style={{
left: hoverStyle.left,
width: hoverStyle.width,
@ -136,10 +136,7 @@ export const MenuIconSelector: React.FC<MenuIconSelectorProps> = ({
closeOnClick={true}
interactive={interactive}
disabled={disabled}
className={twMerge(
"text-sm font-semibold",
item.large && "text-md",
)}
className="font-sans text-xs font-medium normal-case tracking-normal"
imageSrc={imageSrc || undefined}
description={description || undefined}
>
@ -153,7 +150,7 @@ export const MenuIconSelector: React.FC<MenuIconSelectorProps> = ({
className={twMerge(
"relative z-30 flex flex-col items-center justify-center px-3 py-2 rounded-[2px] transition-colors duration-150",
idx === selectedIndex
? "text-ui-panel"
? "text-base-fg"
: "text-base-fg/70 hover:text-base-fg",
disabled ? "cursor-not-allowed opacity-60" : "",
)}

View File

@ -4,7 +4,11 @@ import { JobContextType } from "@storyteller/common";
import { PopoverMenu, PopoverItem } from "@storyteller/ui-popover";
import { SliderV2 } from "@storyteller/ui-sliderv2";
import { Tooltip } from "@storyteller/ui-tooltip";
import { ToggleButton, GenerateIconButton } from "@storyteller/ui-button";
import {
ToggleButton,
GenerateIconButton,
NEUTRAL_BUTTON_HOVER_CLASSES,
} from "@storyteller/ui-button";
import { GenerateVideo, GenerateVideoRequest, commandErrorMessage } from "@storyteller/tauri-api";
import { AudioLinesIcon, ChevronDownIcon, ChevronUpIcon, ClockIcon, InfoIcon } from "lucide-react";
import { DynamicIcon } from "@storyteller/icons";
@ -1317,7 +1321,7 @@ export const PromptBoxVideo = ({
<button
type="button"
onClick={() => setIsCharactersModalOpen(true)}
className="flex h-9 items-center justify-center gap-1 rounded-[3px] border border-ui-controls-border bg-ui-controls px-3 font-mono text-[11px] font-semibold uppercase tracking-[0.12em] text-base-fg transition-colors duration-150 hover:bg-ui-controls/80"
className={`flex h-[34px] items-center justify-center gap-2 rounded-[3px] border border-ui-controls-border bg-ui-controls px-3 text-sm font-medium text-base-fg transition-colors duration-150 ${NEUTRAL_BUTTON_HOVER_CLASSES}`}
>
@Characters
</button>
@ -1531,11 +1535,6 @@ export const PromptBoxVideo = ({
icon={AudioLinesIcon}
activeIcon={AudioLinesIcon}
onClick={() => setGenerateWithSound(!generateWithSound)}
className={
generateWithSound
? "bg-white/10 hover:bg-white/15 border-white/40"
: undefined
}
/>
</Tooltip>
)}