8f1b1fb5cd
* feat(ui): replace generic building icon with company monogram in user menu The company row and switcher flyout in the sidebar user menu showed lucide Building2 for every company. Render the company's initial in a small rounded square instead (square = company, circle = person), so each company gets a mark of its own. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(mobile): touch behavior polish for the mobile web experience - kill -webkit-tap-highlight-color flash; touch-action: manipulation on interactive elements (no double-tap-to-zoom wait); user-select: none on buttons (long-press no longer enters text selection) - overscroll-behavior-y: contain on html/body: pull-to-refresh no longer hijacks list scrolling, inner scrollers stop chaining to the document (contain, not none, so iOS rubber-banding survives) - 16px font-size floor for form fields on coarse pointers: iOS Safari stops zooming into focused inputs; desktop keeps text-sm - min-h-screen -> min-h-dvh everywhere: correct height under collapsing mobile browser chrome, identical on desktop - active: variants mirror hover: on Button: Tailwind 4 gates hover: behind (hover: hover), so touch devices previously got zero pointer feedback - theme-color now tracks the app: default was a leftover blue #304D83; SSR emits white and ThemeColorSync mirrors the computed --background into the meta tag across dark mode and palette switches Hover-stuck-after-tap and viewport-fit/safe-area were already covered (Tailwind 4 hover gating; existing viewportFit: cover + safe-area utilities). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: log monogram and overscroll decisions Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
67 lines
2.5 KiB
TypeScript
67 lines
2.5 KiB
TypeScript
import * as React from "react"
|
|
import { Slot } from "@radix-ui/react-slot"
|
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
// Buttons are pills (radius 99px): a deliberate app-wide divergence from the
|
|
// shadcn 8px default, locked in the UI-migration conventions. Change it here,
|
|
// never per call site.
|
|
const buttonVariants = cva(
|
|
"inline-flex items-center justify-center whitespace-nowrap rounded-full font-medium transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50",
|
|
{
|
|
variants: {
|
|
variant: {
|
|
// active: mirrors hover: on every variant. Tailwind 4 gates hover:
|
|
// behind (hover: hover), so on touch devices these are the only
|
|
// pointer-down feedback a button gives.
|
|
default:
|
|
"bg-primary text-primary-foreground hover:bg-primary/90 active:bg-primary/90",
|
|
destructive:
|
|
"bg-destructive text-destructive-foreground hover:bg-destructive/90 active:bg-destructive/90",
|
|
outline:
|
|
"border border-input bg-transparent hover:bg-secondary active:bg-secondary",
|
|
secondary:
|
|
"bg-secondary text-secondary-foreground hover:bg-secondary/70 active:bg-secondary/70",
|
|
ghost:
|
|
"hover:bg-secondary hover:text-secondary-foreground active:bg-secondary active:text-secondary-foreground",
|
|
link:
|
|
"text-primary underline-offset-4 hover:underline active:underline",
|
|
success:
|
|
"bg-success text-success-foreground hover:bg-success/90 active:bg-success/90",
|
|
},
|
|
size: {
|
|
default: "px-4 py-[7px] text-[13px]",
|
|
sm: "h-9 px-4 text-xs",
|
|
lg: "h-11 px-8 text-base",
|
|
icon: "h-10 w-10",
|
|
},
|
|
},
|
|
defaultVariants: {
|
|
variant: "default",
|
|
size: "default",
|
|
},
|
|
}
|
|
)
|
|
|
|
export interface ButtonProps
|
|
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
VariantProps<typeof buttonVariants> {
|
|
asChild?: boolean
|
|
}
|
|
|
|
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
const Comp = asChild ? Slot : "button"
|
|
return (
|
|
<Comp
|
|
className={cn(buttonVariants({ variant, size, className }))}
|
|
ref={ref}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
)
|
|
Button.displayName = "Button"
|
|
|
|
export { Button, buttonVariants }
|