Repository navigation
Expand file tree
/
Copy pathTopbarButton.tsx
More file actions
60 lines (56 loc) · 2.73 KB
/
Copy pathTopbarButton.tsx
File metadata and controls
60 lines (56 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
import { Pressable } from "./ui/pressable";
import { NAV_ROW_HIGHLIGHT_HOST_CLASS, NavRowHighlight } from "./NavRowHighlight";
// Utility controls rest muted and brighten on hover or while their menu or toggle is on.
const topbarActionClass = "border-0 bg-transparent text-muted-foreground hover:text-foreground aria-expanded:text-foreground aria-pressed:text-foreground";
const topbarButtonVariants = cva(
"topbar-control topbar-control--disabled-affordance inline-flex items-center transition-[filter,background-color,color,border-color] duration-fast ease-out",
{
variants: {
variant: {
action:
`topbar-control--action h-control-lg gap-1.5 rounded-md px-3.5 text-sm font-semibold leading-none ${topbarActionClass}`,
secondary:
"topbar-control--secondary h-control-lg gap-1.5 rounded-md bg-transparent px-3.5 text-sm font-semibold leading-none text-muted-foreground hover:text-foreground",
primary:
"topbar-control--primary h-control-lg gap-1.5 rounded-md bg-accent-strong px-3.5 text-sm leading-none text-accent-foreground hover:brightness-110 active:brightness-95",
accent:
"topbar-control--accent h-control-lg gap-1.5 rounded-md border border-border px-3.5 text-sm font-semibold leading-none bg-raised text-muted-foreground hover:bg-surface hover:text-foreground",
icon:
`topbar-control--icon grid size-control-md place-items-center rounded-md ${topbarActionClass}`,
},
},
defaultVariants: { variant: "action" },
},
);
export function TopbarButton({
children,
className,
highlight = true,
variant = "action",
type = "button",
...props
}: React.ComponentProps<"button"> & VariantProps<typeof topbarButtonVariants> & {
/** Joined controls can let their surrounding group own the highlight. */
highlight?: boolean;
}) {
// Accent keeps its bordered raised surface; every other utility control
// shares the sidebar's hover highlight.
const useHighlight = highlight && (variant === "action" || variant === "icon" || variant === "secondary");
const active = props["aria-pressed"] === true || props["aria-pressed"] === "true" ||
props["aria-expanded"] === true || props["aria-expanded"] === "true";
return (
<Pressable
className={cn(topbarButtonVariants({ variant }), useHighlight && NAV_ROW_HIGHLIGHT_HOST_CLASS, useHighlight && "isolate", className)}
type={type}
{...props}
>
{useHighlight ? <NavRowHighlight active={active} disabled={props.disabled} /> : null}
{children}
</Pressable>
);
}
export function TopbarActionError({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) {
return <span className={cn("text-caption text-destructive", className)} role="alert" {...props} />;
}