Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 19 additions & 22 deletions app/components/search-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ export function SearchBar({
<Form
method="GET"
action={action}
className="flex flex-wrap items-center justify-center gap-2"
className="flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-end sm:justify-between"
onChange={(e) => autoSubmit && handleFormChange(e.currentTarget)}
>
<div className="flex-1">
<div className="flex w-full items-center gap-2 sm:flex-1">
<div className="min-w-0 flex-1">
<Label htmlFor={id} className="sr-only">
Search
</Label>
Expand All @@ -54,14 +55,22 @@ export function SearchBar({
placeholder="Search"
className="w-full"
autoFocus={autoFocus}
/>
/>
</div>
<StatusButton
type="submit"
size="icon-lg"
status={isSubmitting ? 'pending' : status}
className="shrink-0"
>
<Icon name="magnifying-glass" size="md" />
<span className="sr-only">Search</span>
</StatusButton>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StatusButton icon-lg size may overflow during pending state

Medium Severity

The search button uses StatusButton with size="icon-lg" (48x48px, no padding) but doesn't include gap-0 to override the component's internal gap-4 spacing. During the pending state, when the spinner icon appears alongside the magnifying glass icon, the combined content with 16px gap may overflow the fixed button dimensions. The existing StatusButton with size="icon" elsewhere in the codebase includes gap-0 in its className to prevent this exact issue.

Fix in Cursor Fix in Web

</div>
{showDateFilter ? (
<div className="flex w-full flex-col gap-2 sm:w-auto sm:flex-row">
<div className="w-full sm:w-[160px]">
<Label htmlFor={startDateId} className="sr-only">
Start date
</Label>
<div className="grid w-full grid-cols-2 gap-2 sm:flex sm:w-auto sm:items-end">
<div className="min-w-0 space-y-1 sm:w-[160px]">
<Label htmlFor={startDateId}>Start date</Label>
<Input
type="date"
name="startDate"
Expand All @@ -70,10 +79,8 @@ export function SearchBar({
className="w-full"
/>
</div>
<div className="w-full sm:w-[160px]">
<Label htmlFor={endDateId} className="sr-only">
End date
</Label>
<div className="min-w-0 space-y-1 sm:w-[160px]">
<Label htmlFor={endDateId}>End date</Label>
<Input
type="date"
name="endDate"
Expand All @@ -84,16 +91,6 @@ export function SearchBar({
</div>
</div>
) : null}
<div>
<StatusButton
type="submit"
status={isSubmitting ? 'pending' : status}
className="flex w-full items-center justify-center"
>
<Icon name="magnifying-glass" size="md" />
<span className="sr-only">Search</span>
</StatusButton>
</div>
</Form>
)
}
9 changes: 9 additions & 0 deletions app/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,20 @@ const buttonVariants = cva(
variant: {
default:
'bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm',
brand:
'bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-green-700))] shadow-sm',
'brand-soft':
'bg-[hsl(var(--palette-green-300))] text-[hsl(var(--palette-dark-navy))] hover:bg-[hsl(var(--palette-green-500))] hover:text-[hsl(var(--palette-cream))] shadow-sm',
warm:
'bg-[hsl(var(--palette-chestnut))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-hot-fire-red))] shadow-sm',
destructive:
'bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm',
outline: 'border-border bg-card text-foreground hover:bg-muted border',
secondary:
'border-border text-foreground hover:bg-muted border bg-transparent',
ghost: 'text-foreground hover:bg-muted',
'ghost-inverse':
'text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-cream))/0.15]',
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
Expand All @@ -27,6 +35,7 @@ const buttonVariants = cva(
lg: 'h-14 px-8 text-base',
pill: 'h-10 px-8 text-sm',
icon: 'h-10 w-10 p-0',
'icon-lg': 'h-12 w-12 p-0',
},
icon: {
true: 'h-10 w-10 rounded-full p-2',
Expand Down
3 changes: 2 additions & 1 deletion app/routes/_app+/_auth+/forgot-password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ export default function ForgotPasswordRoute() {
</div>
<ErrorList errors={form.errors} id={form.errorId} />
<StatusButton
className="w-full bg-[hsl(var(--palette-hot-fire-red))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-fire-red))]"
variant="destructive"
className="w-full"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Destructive variant may not match original palette colors

Low Severity

The "Recover password" button originally used specific palette colors (--palette-hot-fire-red base, --palette-fire-red hover), but now uses variant="destructive" which relies on the --destructive CSS variable. Unless --destructive is mapped to the same hot-fire-red color, this changes the button's appearance from the intentionally chosen brand palette colors.

Fix in Cursor Fix in Web

status={
forgotPassword.state === 'submitting'
? 'pending'
Expand Down
3 changes: 2 additions & 1 deletion app/routes/_app+/_auth+/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ export default function LoginPage() {
<ErrorList errors={form.errors} id={form.errorId} />

<StatusButton
className="w-full bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-green-700))]"
variant="brand"
className="w-full"
status={isPending ? 'pending' : (form.status ?? 'idle')}
type="submit"
disabled={isPending}
Expand Down
3 changes: 2 additions & 1 deletion app/routes/_app+/_auth+/onboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ export default function SignupRoute() {
<input {...getInputProps(fields.redirectTo, { type: 'hidden' })} />
<ErrorList errors={form.errors} id={form.errorId} />
<StatusButton
className="w-full bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-green-700))]"
variant="brand"
className="w-full"
status={isPending ? 'pending' : (form.status ?? 'idle')}
type="submit"
disabled={isPending}
Expand Down
3 changes: 2 additions & 1 deletion app/routes/_app+/_auth+/reset-password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ export default function ResetPasswordPage() {
<ErrorList errors={form.errors} id={form.errorId} />

<StatusButton
className="w-full bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-green-700))]"
variant="brand"
className="w-full"
status={isPending ? 'pending' : (form.status ?? 'idle')}
type="submit"
disabled={isPending}
Expand Down
3 changes: 2 additions & 1 deletion app/routes/_app+/_auth+/signup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ export default function SignupRoute() {
</div>
<ErrorList errors={form.errors} id={form.errorId} />
<StatusButton
className="w-full bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-green-700))]"
variant="brand"
className="w-full"
status={isPending ? 'pending' : (form.status ?? 'idle')}
type="submit"
disabled={isPending}
Expand Down
3 changes: 2 additions & 1 deletion app/routes/_app+/_auth+/verify.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ export default function VerifyRoute() {
/>
<StatusButton
size="lg"
className="w-full bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-green-700))]"
variant="brand"
className="w-full"
status={isPending ? 'pending' : (form.status ?? 'idle')}
type="submit"
disabled={isPending}
Expand Down
3 changes: 2 additions & 1 deletion app/routes/_app+/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,8 @@ function MobileMenu() {
<Button
asChild
size="lg"
className="mt-6 w-full bg-[hsl(var(--palette-orange))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-chestnut))]"
variant="warm"
className="mt-6 w-full"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warm variant uses wrong base color for mobile menu

Medium Severity

The mobile menu "Start 14-day FREE Trial" button originally used --palette-orange as its base color with --palette-chestnut on hover. The new warm variant uses --palette-chestnut as the base with --palette-hot-fire-red on hover. This changes the button's appearance from orange to a darker brown/chestnut color, which is a visual regression from the intended design.

Additional Locations (1)

Fix in Cursor Fix in Web

>
<Link to="/login" onClick={() => setOpen(false)}>
<Icon name="star" size="sm" aria-hidden="true">
Expand Down
5 changes: 3 additions & 2 deletions app/routes/_app+/_marketing+/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ export default function Index() {
<Button
asChild
size="lg"
className="w-full max-w-[320px] bg-[hsl(var(--palette-chestnut))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-hot-fire-red))] sm:w-auto"
variant="warm"
className="w-full max-w-[320px] sm:w-auto"
>
{user ? (
<Link to="/recipients">Open dashboard</Link>
Expand Down Expand Up @@ -234,7 +235,7 @@ export default function Index() {
<div className="flex flex-col gap-3 sm:flex-row">
<Button
asChild
className="bg-[hsl(var(--palette-chestnut))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-hot-fire-red))]"
variant="warm"
>
<Link to="/login">Get started</Link>
</Button>
Expand Down
19 changes: 10 additions & 9 deletions app/routes/_app+/recipients+/$recipientId.index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -643,30 +643,31 @@ export default function RecipientRoute() {
</div>
)}
</section>
<div className="flex flex-col gap-2">
<div className="flex flex-col gap-2 pb-8 sm:pb-10">
<newMessageFetcher.Form
method="POST"
action="new"
className="border-border/60 rounded-full border bg-white p-2 shadow-sm transition focus-within:rounded-[28px] focus-within:p-3"
className="border-border/40 rounded-full border bg-white p-2 shadow-sm transition focus-within:rounded-[28px] focus-within:border-border/60 focus-within:shadow-md"
>
<label htmlFor="new-message" className="sr-only">
Add a new message
</label>
<div className="flex items-center gap-3">
<div className="flex items-center gap-2">
<textarea
id="new-message"
name="content"
ref={newMessageInputRef}
placeholder="Aa"
className="text-foreground placeholder:text-muted-foreground min-h-[44px] flex-1 resize-none rounded-full bg-transparent px-4 py-2 text-sm leading-relaxed focus-visible:outline-none"
className="text-foreground placeholder:text-muted-foreground min-h-[48px] flex-1 resize-none rounded-full bg-transparent px-4 py-2 text-sm leading-relaxed focus-visible:outline-none"
rows={1}
required
/>
<StatusButton
status={isCreating ? 'pending' : 'idle'}
type="submit"
size="pill"
className="shrink-0 bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-green-700))]"
variant="brand-soft"
className="shrink-0 px-6"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brand-soft variant uses wrong base color for Add button

Medium Severity

The message composer "Add" button originally used --palette-green-500 base with cream text and --palette-green-700 on hover. The brand-soft variant uses --palette-green-300 (lighter) with dark-navy text, changing to green-500 with cream text on hover. This makes the button noticeably lighter and changes the text color from light cream to dark navy.

Fix in Cursor Fix in Web

>
<Icon name="check">Add</Icon>
</StatusButton>
Expand Down Expand Up @@ -773,9 +774,9 @@ function MessageForms({ message }: { message: FutureMessage }) {
<StatusButton
form={updateContentForm.id}
status={updateIsPending ? 'pending' : 'idle'}
className="h-9 w-9 gap-0 text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-cream))/0.15]"
className="h-9 w-9 gap-0"
size="icon"
variant="ghost"
variant="ghost-inverse"
type="submit"
name="intent"
value={updateMessageContentActionIntent}
Expand All @@ -791,9 +792,9 @@ function MessageForms({ message }: { message: FutureMessage }) {
>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
variant="ghost-inverse"
size="icon"
className="h-9 w-9 text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-cream))/0.15]"
className="h-9 w-9"
aria-label="Message actions"
>
<Icon name="dots-horizontal" size="sm" />
Expand Down
2 changes: 1 addition & 1 deletion app/routes/_app+/recipients+/__editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ export function RecipientEditor({
status={isPending ? 'pending' : 'idle'}
name="intent"
value={upsertRecipientActionIntent}
className="bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-green-700))]"
variant="brand"
>
<Icon name="check">{submitLabel}</Icon>
</StatusButton>
Expand Down
5 changes: 3 additions & 2 deletions app/routes/_app+/recipients+/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default function RecipientsIndexRoute() {
variant="outline"
size="icon"
aria-label="Add recipient"
className="bg-muted hover:bg-card h-14 w-14 shadow-sm"
className="h-14 w-14 shadow-sm"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ButtonLink background states reversed after removing overrides

Low Severity

Removing bg-muted hover:bg-card from the "Add recipient" ButtonLink reverses its visual states. The button originally had a muted (darker) background that became card-colored (lighter) on hover. Now it uses the outline variant's default bg-card hover:bg-muted, making it lighter by default and darker on hover—the opposite interaction feedback.

Fix in Cursor Fix in Web

>
<Icon name="plus" size="xl" />
</ButtonLink>
Expand Down Expand Up @@ -148,7 +148,8 @@ export default function RecipientsIndexRoute() {
</div>
<ButtonLink
to="new"
className="flex w-full items-center justify-center gap-2 bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-green-700))] sm:w-auto"
variant="brand"
className="flex w-full items-center justify-center gap-2 sm:w-auto"
>
<Icon name="plus">Add Recipient</Icon>
</ButtonLink>
Expand Down
2 changes: 1 addition & 1 deletion app/routes/_app+/settings.profile+/change-number.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export default function ChangePhoneNumberIndex() {
<Link to="..">Cancel</Link>
</Button>
<StatusButton
className="bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-green-700))]"
variant="brand"
status={isPending ? 'pending' : (form.status ?? 'idle')}
>
Send Confirmation
Expand Down
2 changes: 1 addition & 1 deletion app/routes/_app+/settings.profile+/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ function UpdateProfile() {
status={
fetcher.state !== 'idle' ? 'pending' : (form.status ?? 'idle')
}
className="bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-green-700))]"
variant="brand"
>
Save Changes
</StatusButton>
Expand Down
2 changes: 1 addition & 1 deletion app/routes/_app+/settings.profile+/password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export default function ChangePasswordRoute() {
<StatusButton
type="submit"
status={isPending ? 'pending' : (form.status ?? 'idle')}
className="bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-green-700))]"
variant="brand"
>
Save
</StatusButton>
Expand Down
Loading