Skip to content
Source
Sign inSign up
Open History to see the last commit

ContextChip.tsx

101 lines4.7 KB

1import { mergeProps } from "@base-ui/react/merge-props";
2import { useRender } from "@base-ui/react/use-render";
3import { cva, type VariantProps } from "class-variance-authority";
4import type * as React from "react";
5​
6import { cn } from "~/lib/utils";
7​
8const contextChipVariants = cva(
9 "inline-flex max-w-full items-center gap-[0.2em] font-medium leading-[normal] text-(--context-chip-ink) [--context-chip-ink:var(--context-chip-accent)] [--document-icon-stroke:var(--context-chip-ink)] [&_svg]:block [&_svg]:size-[1em] [&_svg]:shrink-0 [&_svg]:self-center [button&,a&,[data-popup-open]&]:cursor-pointer focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-current rounded-sm disabled:cursor-default",
10 {
11 defaultVariants: { kind: "neutral" },
12 variants: {
13 kind: {
14 neutral: "[--context-chip-accent:currentColor]",
15 image: "[--context-chip-accent:var(--info-foreground)]",
16 video: "[--context-chip-accent:var(--warning-foreground)]",
17 file: "[--context-chip-accent:var(--info-foreground)]",
18 mention: "[--context-chip-accent:var(--info-foreground)]",
19 terminal: "[--context-chip-accent:var(--success-foreground)]",
20 element: "[--context-chip-accent:var(--warning-foreground)]",
21 "preview-annotation": "[--context-chip-accent:var(--warning-foreground)]",
22 "review-comment": "[--context-chip-accent:var(--merged-foreground)]",
23 "pull-request": "[--context-chip-accent:var(--merged-foreground)]",
24 "pr-open": "[--context-chip-accent:var(--success-foreground)]",
25 "pr-draft": "[--context-chip-accent:var(--muted-foreground)]",
26 "pr-merged": "[--context-chip-accent:var(--merged-foreground)]",
27 "pr-closed": "[--context-chip-accent:var(--error-foreground)]",
28 skill: "[--context-chip-accent:var(--merged-foreground)]",
29 model: "[--context-chip-accent:var(--warning-foreground)]",
30 thread: "[--context-chip-accent:var(--info-foreground)]",
31 environment: "[--context-chip-accent:var(--success-foreground)]",
32 citation: "[--context-chip-accent:var(--info-foreground)]",
33 "doc-pdf": "[--context-chip-accent:var(--error-foreground)]",
34 "doc-word": "[--context-chip-accent:var(--info-foreground)]",
35 "doc-spreadsheet": "[--context-chip-accent:var(--success-foreground)]",
36 "doc-slides": "[--context-chip-accent:var(--warning-foreground)]",
37 "doc-epub": "[--context-chip-accent:var(--merged-foreground)]",
38 },
39 shape: {
40 inline: "",
41 bubble: "w-64 gap-2 rounded-2xl surface-bubble px-3 py-2 text-label text-foreground",
42 },
43 state: {
44 unresolved: "data-[state=unresolved]:[--context-chip-accent:currentColor]",
45 invalid: "data-[state=invalid]:[--context-chip-accent:var(--error-foreground)]",
46 },
47 },
48 },
49);
50​
51type ContextChipKind = NonNullable<VariantProps<typeof contextChipVariants>["kind"]>;
52​
53interface ContextChipProps extends useRender.ComponentProps<"span"> {
54 kind?: ContextChipKind;
55 state?: "unresolved" | "invalid";
56 shape?: "inline" | "bubble";
58​
59function ContextChip({ className, kind, state, shape, render, ...props }: ContextChipProps) {
60 const defaultProps = {
61 className: cn(contextChipVariants({ kind, state, shape }), className),
62 "data-slot": "context-chip",
63 "data-state": state,
64 };
65 return useRender({
66 defaultTagName: "span",
67 props: mergeProps<"span">(defaultProps, props),
68 render,
69 });
71​
72function ContextChipLabel({ className, ...props }: React.ComponentProps<"span">) {
73 return (
74 <span
75 className={cn(
76 "block min-w-0 self-baseline overflow-x-clip text-ellipsis whitespace-nowrap underline decoration-transparent decoration-1 underline-offset-[0.2em] transition-colors motion-reduce:transition-none [:is(button:enabled,a):hover>&]:decoration-current",
77 className,
78 )}
79 data-slot="context-chip-label"
80 {...props}
81 />
82 );
84​
85function ContextChipAction({ className, render, ...props }: useRender.ComponentProps<"button">) {
86 const defaultProps = {
87 className: cn(
88 "ml-[0.17em] inline-flex size-[1em] shrink-0 cursor-pointer items-center justify-center rounded-sm text-current transition-colors hover:bg-(--context-chip-accent,var(--color-foreground))/17 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring motion-reduce:transition-none [&_svg]:size-[0.85em]",
89 className,
90 ),
91 "data-slot": "context-chip-action",
92 type: render ? undefined : ("button" as const),
93 };
94 return useRender({
95 defaultTagName: "button",
96 props: mergeProps<"button">(defaultProps, props),
97 render,
98 });
100​
101export { ContextChip, ContextChipAction, ContextChipLabel, type ContextChipKind };