refactor(ui): switch surfaces to shared shadow tokens
This commit is contained in:
@@ -25,7 +25,7 @@ function ErrorMessage() {
|
|||||||
export default function AuthErrorPage() {
|
export default function AuthErrorPage() {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center px-4 py-20">
|
<div className="flex items-center justify-center px-4 py-20">
|
||||||
<div className="w-full max-w-sm space-y-6 rounded-[10px] bg-card p-8 shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_12px_40px_rgba(0,0,0,0.12)]">
|
<div className="w-full max-w-sm space-y-6 rounded-[10px] bg-card p-8 shadow-xl">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<AlertTriangle className="h-8 w-8 text-destructive mx-auto mb-3" />
|
<AlertTriangle className="h-8 w-8 text-destructive mx-auto mb-3" />
|
||||||
<h1 className="text-lg font-semibold">Authentication Error</h1>
|
<h1 className="text-lg font-semibold">Authentication Error</h1>
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ export function SignInForm({ providers }: SignInFormProps) {
|
|||||||
initial={{ opacity: 0, y: 16 }}
|
initial={{ opacity: 0, y: 16 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.3 }}
|
transition={{ duration: 0.3 }}
|
||||||
className="w-full max-w-sm rounded-[10px] bg-card p-8 shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_12px_40px_rgba(0,0,0,0.12)]"
|
className="w-full max-w-sm rounded-[10px] bg-card p-8 shadow-xl"
|
||||||
>
|
>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-center gap-2 mb-2">
|
<div className="flex items-center justify-center gap-2 mb-2">
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export default function SignOutPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center px-4 py-20">
|
<div className="flex items-center justify-center px-4 py-20">
|
||||||
<div className="w-full max-w-sm space-y-6 rounded-[10px] bg-card p-8 shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_12px_40px_rgba(0,0,0,0.12)]">
|
<div className="w-full max-w-sm space-y-6 rounded-[10px] bg-card p-8 shadow-xl">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<LogOut className="h-8 w-8 text-muted-foreground mx-auto mb-3" />
|
<LogOut className="h-8 w-8 text-muted-foreground mx-auto mb-3" />
|
||||||
<h1 className="text-lg font-semibold">Sign Out</h1>
|
<h1 className="text-lg font-semibold">Sign Out</h1>
|
||||||
@@ -37,7 +37,7 @@ export default function SignOutPage() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="rounded-[8px] bg-muted px-4 py-3 text-center shadow-[inset_0_0_0_1px_rgba(0,0,0,0.05)]">
|
<div className="rounded-[8px] bg-secondary px-4 py-3 text-center shadow-[inset_0_0_0_1px_var(--color-border)]">
|
||||||
<div className="text-xs text-muted-foreground mb-0.5">
|
<div className="text-xs text-muted-foreground mb-0.5">
|
||||||
Signed in as
|
Signed in as
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -516,8 +516,8 @@ export default function HomePage() {
|
|||||||
Capture from text or files.
|
Capture from text or files.
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-sm leading-6 text-muted-foreground">
|
<p className="text-sm leading-6 text-muted-foreground">
|
||||||
Start with a prompt, screenshots, or both. Review happens in the
|
Start with a prompt, screenshots, or both. Review happens
|
||||||
timeline rather than a separate flow.
|
in the timeline rather than a separate flow.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ export const AIToolbar = ({
|
|||||||
) : isAuthenticated ? (
|
) : isAuthenticated ? (
|
||||||
<div className="grid gap-3 lg:grid-cols-[minmax(0,1fr)_minmax(0,1fr)]">
|
<div className="grid gap-3 lg:grid-cols-[minmax(0,1fr)_minmax(0,1fr)]">
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="rounded-[10px] bg-card shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_2px_2px_rgba(0,0,0,0.04),0_0_0_1px_#fafafa] focus-within:ring-[3px] focus-within:ring-ring/20">
|
<div className="rounded-[10px] bg-card shadow focus-within:ring-[3px] focus-within:ring-ring/20">
|
||||||
<Textarea
|
<Textarea
|
||||||
id="ai-event-prompt"
|
id="ai-event-prompt"
|
||||||
className="wrap-anywhere field-sizing-content min-h-48 w-full resize-none rounded-none border-0 bg-transparent px-4 py-3 text-sm shadow-none placeholder:text-muted-foreground/50 focus-visible:ring-0 focus-visible:ring-offset-0"
|
className="wrap-anywhere field-sizing-content min-h-48 w-full resize-none rounded-none border-0 bg-transparent px-4 py-3 text-sm shadow-none placeholder:text-muted-foreground/50 focus-visible:ring-0 focus-visible:ring-offset-0"
|
||||||
@@ -416,18 +416,20 @@ export const AIToolbar = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="rounded-[10px] bg-card p-3 shadow-[0_0_0_1px_rgba(0,0,0,0.08)]">
|
<div className="rounded-[10px] bg-card p-3 shadow-sm">
|
||||||
<div className="mb-3 flex items-start justify-between gap-3">
|
<div className="mb-3 flex items-start justify-between gap-3">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">
|
<p className="text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">
|
||||||
Attachments
|
Attachments
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-1 text-sm leading-6 text-muted-foreground">
|
<p className="mt-1 text-sm leading-6 text-muted-foreground">
|
||||||
Add screenshots, flyers, or pasted images alongside the prompt.
|
Add screenshots, flyers, or pasted images alongside the
|
||||||
|
prompt.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<span className="rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground">
|
<span className="rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground">
|
||||||
{imagePreviews.length} file{imagePreviews.length === 1 ? "" : "s"}
|
{imagePreviews.length} file
|
||||||
|
{imagePreviews.length === 1 ? "" : "s"}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ interface EventCardProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const EVENT_CARD_SURFACE_CLASSES =
|
export const EVENT_CARD_SURFACE_CLASSES =
|
||||||
"group cursor-pointer rounded-[10px] bg-card p-4 shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_2px_2px_rgba(0,0,0,0.04),0_0_0_1px_#fafafa] transition-[background-color,transform,box-shadow] duration-150 hover:-translate-y-0.5 hover:bg-accent/20";
|
"group cursor-pointer rounded-[10px] bg-card p-4 shadow transition-[background-color,transform,box-shadow] duration-150 hover:-translate-y-0.5 hover:bg-accent/20";
|
||||||
|
|
||||||
export const EventCard = ({ event, onEdit, onDelete }: EventCardProps) => {
|
export const EventCard = ({ event, onEdit, onDelete }: EventCardProps) => {
|
||||||
const validationIssues = getEventValidationIssues(event);
|
const validationIssues = getEventValidationIssues(event);
|
||||||
|
|||||||
@@ -147,8 +147,8 @@ export const EventDialog = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={handleOpenChange}>
|
<Dialog open={open} onOpenChange={handleOpenChange}>
|
||||||
<DialogContent className="max-w-2xl rounded-[10px] bg-card p-0 shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_12px_40px_rgba(0,0,0,0.12)]">
|
<DialogContent className="max-w-2xl rounded-[10px] bg-card p-0 shadow-xl">
|
||||||
<DialogHeader className="border-b border-foreground/10 px-6 py-5">
|
<DialogHeader className="px-6 py-5 shadow-[inset_0_-1px_0_0_var(--color-border)]">
|
||||||
<DialogTitle className="text-[28px] tracking-[-0.06em]">
|
<DialogTitle className="text-[28px] tracking-[-0.06em]">
|
||||||
{titleText}
|
{titleText}
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
@@ -176,7 +176,9 @@ export const EventDialog = ({
|
|||||||
{...register("title")}
|
{...register("title")}
|
||||||
/>
|
/>
|
||||||
{errors.title && (
|
{errors.title && (
|
||||||
<p className="text-xs text-destructive">{errors.title.message}</p>
|
<p className="text-xs text-destructive">
|
||||||
|
{errors.title.message}
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -209,7 +211,9 @@ export const EventDialog = ({
|
|||||||
<Label htmlFor="event-url">URL</Label>
|
<Label htmlFor="event-url">URL</Label>
|
||||||
<Input id="event-url" placeholder="URL" {...register("url")} />
|
<Input id="event-url" placeholder="URL" {...register("url")} />
|
||||||
{errors.url && (
|
{errors.url && (
|
||||||
<p className="text-xs text-destructive">{errors.url.message}</p>
|
<p className="text-xs text-destructive">
|
||||||
|
{errors.url.message}
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -293,7 +297,9 @@ export const EventDialog = ({
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{errors.start && (
|
{errors.start && (
|
||||||
<p className="text-xs text-destructive">{errors.start.message}</p>
|
<p className="text-xs text-destructive">
|
||||||
|
{errors.start.message}
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
{errors.end && (
|
{errors.end && (
|
||||||
<p className="text-xs text-destructive">{errors.end.message}</p>
|
<p className="text-xs text-destructive">{errors.end.message}</p>
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ const ServerLocationInput = ({
|
|||||||
value={value}
|
value={value}
|
||||||
/>
|
/>
|
||||||
{showSuggestions ? (
|
{showSuggestions ? (
|
||||||
<div className="absolute left-0 right-0 top-[calc(100%+0.375rem)] z-20 rounded-[10px] bg-popover p-1.5 shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_8px_24px_rgba(0,0,0,0.08)]">
|
<div className="absolute left-0 right-0 top-[calc(100%+0.375rem)] z-20 rounded-[10px] bg-popover p-1.5 shadow-lg">
|
||||||
<div className="space-y-1" role="listbox">
|
<div className="space-y-1" role="listbox">
|
||||||
{suggestions.map((suggestion) => {
|
{suggestions.map((suggestion) => {
|
||||||
const suggestionKey =
|
const suggestionKey =
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ interface SettingsPanelProps {
|
|||||||
settings: UserSettings;
|
settings: UserSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const settingRowClasses =
|
const settingRowClasses = "rounded-[10px] bg-card p-4 shadow-sm";
|
||||||
"rounded-[10px] bg-card p-4 shadow-[0_0_0_1px_rgba(0,0,0,0.08)]";
|
|
||||||
|
|
||||||
export function SettingsPanel({
|
export function SettingsPanel({
|
||||||
adminAiEnabled,
|
adminAiEnabled,
|
||||||
@@ -74,7 +73,7 @@ export function SettingsPanel({
|
|||||||
</div>
|
</div>
|
||||||
<Label
|
<Label
|
||||||
htmlFor="settings-skip-ai-review"
|
htmlFor="settings-skip-ai-review"
|
||||||
className="min-h-11 cursor-pointer justify-between rounded-[8px] bg-muted px-3 py-2 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.05)]"
|
className="min-h-11 cursor-pointer justify-between rounded-[8px] bg-secondary px-3 py-2 shadow-[inset_0_0_0_1px_var(--color-border)]"
|
||||||
>
|
>
|
||||||
<span className="text-sm font-medium text-foreground">
|
<span className="text-sm font-medium text-foreground">
|
||||||
{settings.skipAiReview
|
{settings.skipAiReview
|
||||||
@@ -115,7 +114,7 @@ export function SettingsPanel({
|
|||||||
</div>
|
</div>
|
||||||
<Label
|
<Label
|
||||||
htmlFor="settings-ai-enabled"
|
htmlFor="settings-ai-enabled"
|
||||||
className="min-h-11 cursor-pointer justify-between rounded-[8px] bg-muted px-3 py-2 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.05)]"
|
className="min-h-11 cursor-pointer justify-between rounded-[8px] bg-secondary px-3 py-2 shadow-[inset_0_0_0_1px_var(--color-border)]"
|
||||||
>
|
>
|
||||||
<span className="text-sm font-medium text-foreground">
|
<span className="text-sm font-medium text-foreground">
|
||||||
{settings.aiEnabled
|
{settings.aiEnabled
|
||||||
@@ -151,7 +150,7 @@ export function SettingsPanel({
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<dl className="grid gap-3 sm:grid-cols-2 lg:grid-cols-1">
|
<dl className="grid gap-3 sm:grid-cols-2 lg:grid-cols-1">
|
||||||
<div className="rounded-[8px] bg-muted p-3 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.05)]">
|
<div className="rounded-[8px] bg-secondary p-3 shadow-[inset_0_0_0_1px_var(--color-border)]">
|
||||||
<dt className="text-xs font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
<dt className="text-xs font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
||||||
Direct create preference
|
Direct create preference
|
||||||
</dt>
|
</dt>
|
||||||
@@ -161,7 +160,7 @@ export function SettingsPanel({
|
|||||||
: `${valuePrefix}: off`}
|
: `${valuePrefix}: off`}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div className="rounded-[8px] bg-muted p-3 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.05)]">
|
<div className="rounded-[8px] bg-secondary p-3 shadow-[inset_0_0_0_1px_var(--color-border)]">
|
||||||
<dt className="text-xs font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
<dt className="text-xs font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
||||||
AI integrations
|
AI integrations
|
||||||
</dt>
|
</dt>
|
||||||
|
|||||||
@@ -10,13 +10,12 @@ const badgeVariants = cva(
|
|||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default:
|
default:
|
||||||
"bg-secondary text-secondary-foreground shadow-[0_0_0_1px_rgba(0,0,0,0.08)] [a&]:hover:bg-accent",
|
"bg-secondary text-secondary-foreground shadow-sm [a&]:hover:bg-accent",
|
||||||
secondary:
|
secondary:
|
||||||
"bg-[#ebf5ff] text-[#0068d6] shadow-[0_0_0_1px_rgba(0,0,0,0.08)] [a&]:hover:opacity-90",
|
"bg-[#ebf5ff] text-[#0068d6] shadow-sm [a&]:hover:opacity-90",
|
||||||
destructive:
|
destructive:
|
||||||
"bg-destructive/12 text-destructive shadow-[0_0_0_1px_rgba(255,91,79,0.2)] [a&]:hover:bg-destructive/18 focus-visible:ring-destructive/25",
|
"bg-destructive/12 text-destructive shadow-[0_0_0_1px_rgba(255,91,79,0.2)] [a&]:hover:bg-destructive/18 focus-visible:ring-destructive/25",
|
||||||
outline:
|
outline: "bg-background text-foreground shadow-sm [a&]:hover:bg-accent",
|
||||||
"bg-background text-foreground shadow-[0_0_0_1px_rgba(0,0,0,0.08)] [a&]:hover:bg-accent",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
|
|||||||
@@ -12,10 +12,9 @@ const buttonVariants = cva(
|
|||||||
default: "bg-primary text-primary-foreground hover:opacity-92",
|
default: "bg-primary text-primary-foreground hover:opacity-92",
|
||||||
destructive:
|
destructive:
|
||||||
"bg-destructive text-destructive-foreground hover:opacity-92 focus-visible:ring-destructive/25 dark:focus-visible:ring-destructive/35",
|
"bg-destructive text-destructive-foreground hover:opacity-92 focus-visible:ring-destructive/25 dark:focus-visible:ring-destructive/35",
|
||||||
outline:
|
outline: "bg-background text-foreground shadow-xs hover:bg-accent",
|
||||||
"bg-background text-foreground shadow-[0_0_0_1px_rgba(0,0,0,0.08)] hover:bg-accent",
|
|
||||||
secondary:
|
secondary:
|
||||||
"bg-secondary text-secondary-foreground shadow-[0_0_0_1px_rgba(0,0,0,0.05)] hover:bg-accent",
|
"bg-secondary text-secondary-foreground shadow-sm hover:bg-accent",
|
||||||
ghost: "text-muted-foreground hover:bg-accent hover:text-foreground",
|
ghost: "text-muted-foreground hover:bg-accent hover:text-foreground",
|
||||||
link: "text-[#0072f5] underline-offset-4 hover:underline",
|
link: "text-[#0072f5] underline-offset-4 hover:underline",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ function Card({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
<div
|
<div
|
||||||
data-slot="card"
|
data-slot="card"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-card text-card-foreground flex flex-col gap-6 rounded-[10px] py-6 shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_2px_2px_rgba(0,0,0,0.04),0_0_0_1px_#fafafa]",
|
"bg-card text-card-foreground flex flex-col gap-6 rounded-[10px] py-6 shadow",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ function DialogContent({
|
|||||||
<DialogPrimitive.Content
|
<DialogPrimitive.Content
|
||||||
data-slot="dialog-content"
|
data-slot="dialog-content"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-card text-card-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-5 rounded-[10px] p-6 shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_2px_2px_rgba(0,0,0,0.04),0_0_0_1px_#fafafa] duration-200 sm:max-w-lg",
|
"bg-card text-card-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-5 rounded-[10px] p-6 shadow-xl duration-200 sm:max-w-lg",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -110,7 +110,10 @@ function DialogTitle({
|
|||||||
return (
|
return (
|
||||||
<DialogPrimitive.Title
|
<DialogPrimitive.Title
|
||||||
data-slot="dialog-title"
|
data-slot="dialog-title"
|
||||||
className={cn("text-[24px] leading-none font-semibold tracking-[-0.04em]", className)}
|
className={cn(
|
||||||
|
"text-[24px] leading-none font-semibold tracking-[-0.04em]",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ function DropdownMenuContent({
|
|||||||
data-slot="dropdown-menu-content"
|
data-slot="dropdown-menu-content"
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[11rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-[10px] p-1.5 shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_8px_24px_rgba(0,0,0,0.08)]",
|
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[11rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-[10px] p-1.5 shadow-lg",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -230,7 +230,7 @@ function DropdownMenuSubContent({
|
|||||||
<DropdownMenuPrimitive.SubContent
|
<DropdownMenuPrimitive.SubContent
|
||||||
data-slot="dropdown-menu-sub-content"
|
data-slot="dropdown-menu-sub-content"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[11rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-[10px] p-1.5 shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_8px_24px_rgba(0,0,0,0.08)]",
|
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[11rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-[10px] p-1.5 shadow-lg",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
|||||||
type={type}
|
type={type}
|
||||||
data-slot="input"
|
data-slot="input"
|
||||||
className={cn(
|
className={cn(
|
||||||
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground flex h-10 w-full min-w-0 rounded-[8px] bg-background px-3 py-2 text-sm shadow-[0_0_0_1px_rgba(0,0,0,0.08)] transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground flex h-10 w-full min-w-0 rounded-[8px] bg-secondary px-3 py-2 text-sm shadow-sm transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
"focus-visible:ring-[3px] focus-visible:ring-ring/25",
|
"focus-visible:ring-[3px] focus-visible:ring-ring/25",
|
||||||
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
|
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
|
||||||
className,
|
className,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
|||||||
<textarea
|
<textarea
|
||||||
data-slot="textarea"
|
data-slot="textarea"
|
||||||
className={cn(
|
className={cn(
|
||||||
"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
"placeholder:text-muted-foreground aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex field-sizing-content min-h-16 w-full rounded-[8px] bg-secondary px-3 py-2 text-base shadow-sm transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/25 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,24 +1,22 @@
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
export const APP_HEADER_SURFACE_CLASSES =
|
export const APP_HEADER_SURFACE_CLASSES =
|
||||||
"mb-6 flex min-h-14 items-center justify-between gap-3 border-b border-foreground/10 bg-background/95 px-4 py-3 sm:px-6";
|
"mb-6 flex min-h-14 items-center justify-between gap-3 bg-background/95 px-4 py-3 shadow-[inset_0_-1px_0_0_var(--color-border)] sm:px-6";
|
||||||
|
|
||||||
export const APP_SECTION_SURFACE_CLASSES =
|
export const APP_SECTION_SURFACE_CLASSES =
|
||||||
"rounded-[10px] bg-card px-4 py-4 shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_2px_2px_rgba(0,0,0,0.04),0_0_0_1px_#fafafa] sm:px-5";
|
"rounded-[10px] bg-card px-4 py-4 shadow sm:px-5";
|
||||||
|
|
||||||
export const APP_ACTION_BAR_CLASSES =
|
export const APP_ACTION_BAR_CLASSES =
|
||||||
"rounded-[10px] bg-card px-3 py-3 shadow-[0_0_0_1px_rgba(0,0,0,0.08)]";
|
"rounded-[10px] bg-secondary px-3 py-3 shadow-sm";
|
||||||
|
|
||||||
export const APP_NAV_SURFACE_CLASSES =
|
export const APP_NAV_SURFACE_CLASSES =
|
||||||
"fixed inset-x-4 bottom-4 mx-auto flex max-w-3xl items-center justify-between rounded-[10px] bg-background/95 px-3 py-2 shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_8px_24px_rgba(0,0,0,0.08)] sm:inset-x-6 lg:hidden";
|
"fixed inset-x-4 bottom-4 mx-auto flex max-w-3xl items-center justify-between rounded-[10px] bg-card/95 px-3 py-2 shadow-lg sm:inset-x-6 lg:hidden";
|
||||||
|
|
||||||
const CONNECTION_BADGE_BASE_CLASSES =
|
const CONNECTION_BADGE_BASE_CLASSES =
|
||||||
"gap-1.5 rounded-full px-2.5 py-1 text-xs font-medium shadow-[0_0_0_1px_rgba(0,0,0,0.08)]";
|
"gap-1.5 rounded-full px-2.5 py-1 text-xs font-medium shadow-sm";
|
||||||
|
|
||||||
export const getConnectionBadgeClasses = (isOnline: boolean) =>
|
export const getConnectionBadgeClasses = (isOnline: boolean) =>
|
||||||
cn(
|
cn(
|
||||||
CONNECTION_BADGE_BASE_CLASSES,
|
CONNECTION_BADGE_BASE_CLASSES,
|
||||||
isOnline
|
isOnline ? "bg-[#ebf5ff] text-[#0068d6]" : "bg-muted text-muted-foreground",
|
||||||
? "bg-[#ebf5ff] text-[#0068d6]"
|
|
||||||
: "bg-muted text-muted-foreground",
|
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ describe("AI capture redesign", () => {
|
|||||||
test("attachments panel is a first-class surfaced region, not an inline footer affordance", () => {
|
test("attachments panel is a first-class surfaced region, not an inline footer affordance", () => {
|
||||||
const source = readToolbarSource();
|
const source = readToolbarSource();
|
||||||
|
|
||||||
expect(source).toContain("rounded-[10px] bg-card p-3 shadow-[0_0_0_1px_rgba(0,0,0,0.08)]");
|
expect(source).toContain("rounded-[10px] bg-card p-3 shadow-sm");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ describe("EventDialog public modes", () => {
|
|||||||
const source = readFileSync("src/components/ui/dialog.tsx", "utf8");
|
const source = readFileSync("src/components/ui/dialog.tsx", "utf8");
|
||||||
|
|
||||||
expect(source).toContain("rounded-[10px]");
|
expect(source).toContain("rounded-[10px]");
|
||||||
expect(source).toContain("shadow-[0_0_0_1px_rgba(0,0,0,0.08)");
|
expect(source).toContain("shadow-xl");
|
||||||
expect(source).not.toContain("rounded-lg border p-6 shadow-lg");
|
expect(source).not.toContain("rounded-lg border p-6 shadow-lg");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,23 +11,28 @@ import { EVENT_CARD_SURFACE_CLASSES } from "@/components/event-card";
|
|||||||
describe("app shell surfaces", () => {
|
describe("app shell surfaces", () => {
|
||||||
test("header surface is a thin structural bar instead of a glass panel", () => {
|
test("header surface is a thin structural bar instead of a glass panel", () => {
|
||||||
expect(APP_HEADER_SURFACE_CLASSES).toContain("min-h-14");
|
expect(APP_HEADER_SURFACE_CLASSES).toContain("min-h-14");
|
||||||
expect(APP_HEADER_SURFACE_CLASSES).toContain("border-b");
|
expect(APP_HEADER_SURFACE_CLASSES).toContain("shadow-[inset_0_-1px_0_0_var(--color-border)]");
|
||||||
expect(APP_HEADER_SURFACE_CLASSES).not.toContain("glass-surface");
|
expect(APP_HEADER_SURFACE_CLASSES).not.toContain("glass-surface");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("section and action surfaces use tokenized shell classes instead of glass helpers", () => {
|
test("section and action surfaces use tokenized shell classes instead of frozen light-mode shadows", () => {
|
||||||
expect(APP_SECTION_SURFACE_CLASSES).not.toContain("glass-panel");
|
expect(APP_SECTION_SURFACE_CLASSES).not.toContain("glass-panel");
|
||||||
expect(APP_ACTION_BAR_CLASSES).not.toContain("glass-subtle");
|
expect(APP_ACTION_BAR_CLASSES).not.toContain("glass-subtle");
|
||||||
expect(APP_NAV_SURFACE_CLASSES).not.toContain("glass-surface");
|
expect(APP_NAV_SURFACE_CLASSES).not.toContain("glass-surface");
|
||||||
|
expect(APP_SECTION_SURFACE_CLASSES).toContain("shadow");
|
||||||
|
expect(APP_SECTION_SURFACE_CLASSES).not.toContain("rgba(0,0,0,0.08)");
|
||||||
|
expect(APP_ACTION_BAR_CLASSES).toContain("shadow-sm");
|
||||||
|
expect(APP_ACTION_BAR_CLASSES).not.toContain("rgba(0,0,0,0.08)");
|
||||||
|
expect(APP_NAV_SURFACE_CLASSES).toContain("shadow-lg");
|
||||||
|
expect(APP_NAV_SURFACE_CLASSES).not.toContain("rgba(0,0,0,0.08)");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("event cards", () => {
|
describe("event cards", () => {
|
||||||
test("event cards use the redesigned console card treatment", () => {
|
test("event cards use the redesigned console card treatment", () => {
|
||||||
expect(EVENT_CARD_SURFACE_CLASSES).toContain("rounded-[10px]");
|
expect(EVENT_CARD_SURFACE_CLASSES).toContain("rounded-[10px]");
|
||||||
expect(EVENT_CARD_SURFACE_CLASSES).toContain(
|
expect(EVENT_CARD_SURFACE_CLASSES).toContain("shadow");
|
||||||
"shadow-[0_0_0_1px_rgba(0,0,0,0.08)",
|
expect(EVENT_CARD_SURFACE_CLASSES).not.toContain("rgba(0,0,0,0.08)");
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user