a tool for shared writing and social publishing
1import React, { forwardRef, type JSX } from "react";
2import * as RadixTooltip from "@radix-ui/react-tooltip";
3import { theme } from "tailwind.config";
4
5import {
6 CardThemeProvider,
7 NestedCardThemeProvider,
8} from "./ThemeManager/ThemeProvider";
9import { useReplicache } from "src/replicache";
10import { PopoverArrow } from "./Icons/PopoverArrow";
11
12type ButtonProps = Omit<JSX.IntrinsicElements["button"], "content">;
13
14export const ButtonPrimary = forwardRef<
15 HTMLButtonElement,
16 ButtonProps & {
17 fullWidth?: boolean;
18 fullWidthOnMobile?: boolean;
19 children: React.ReactNode;
20 compact?: boolean;
21 }
22>((props, ref) => {
23 let {
24 className,
25 fullWidth,
26 fullWidthOnMobile,
27 compact,
28 children,
29 ...buttonProps
30 } = props;
31 return (
32 <button
33 {...buttonProps}
34 ref={ref}
35 className={`
36 m-0 h-max
37 ${fullWidth ? "w-full" : fullWidthOnMobile ? "w-full sm:w-max" : "w-max"}
38 ${compact ? "py-0 px-1" : "px-2 py-0.5 "}
39 bg-accent-1 disabled:bg-border-light
40 border border-accent-1 rounded-md disabled:border-border-light
41 outline-2 outline-transparent outline-offset-1 focus:outline-accent-1 hover:outline-accent-1
42 text-base font-bold text-accent-2 disabled:text-border disabled:hover:text-border
43 flex gap-2 items-center justify-center shrink-0
44 ${className}
45 `}
46 >
47 {children}
48 </button>
49 );
50});
51ButtonPrimary.displayName = "ButtonPrimary";
52
53export const ButtonSecondary = forwardRef<
54 HTMLButtonElement,
55 ButtonProps & {
56 fullWidth?: boolean;
57 fullWidthOnMobile?: boolean;
58 children: React.ReactNode;
59 compact?: boolean;
60 }
61>((props, ref) => {
62 let {
63 className,
64 fullWidth,
65 fullWidthOnMobile,
66 compact,
67 children,
68 ...buttonProps
69 } = props;
70 return (
71 <button
72 {...buttonProps}
73 ref={ref}
74 className={`
75 m-0 h-max
76 ${fullWidth ? "w-full" : fullWidthOnMobile ? "w-full sm:w-max" : "w-max"}
77 ${compact ? "py-0 px-1" : "px-2 py-0.5 "}
78 bg-bg-page disabled:bg-border-light
79 border border-accent-contrast rounded-md
80 outline-2 outline-transparent focus:outline-accent-contrast hover:outline-accent-contrast outline-offset-1
81 text-base font-bold text-accent-contrast disabled:text-border disabled:hover:text-border
82 flex gap-2 items-center justify-center shrink-0
83 ${props.className}
84 `}
85 >
86 {props.children}
87 </button>
88 );
89});
90ButtonSecondary.displayName = "ButtonSecondary";
91
92export const ButtonTertiary = forwardRef<
93 HTMLButtonElement,
94 {
95 fullWidth?: boolean;
96 fullWidthOnMobile?: boolean;
97 children: React.ReactNode;
98 compact?: boolean;
99 } & ButtonProps
100>((props, ref) => {
101 let {
102 className,
103 fullWidth,
104 fullWidthOnMobile,
105 compact,
106 children,
107 ...buttonProps
108 } = props;
109 return (
110 <button
111 {...buttonProps}
112 ref={ref}
113 className={`
114 m-0 h-max
115 ${fullWidth ? "w-full" : fullWidthOnMobile ? "w-full sm:w-max" : "w-max"}
116 ${compact ? "py-0 px-1" : "px-2 py-0.5 "}
117 bg-transparent hover:bg-[var(--accent-light)]
118 border border-transparent rounded-md hover:border-[var(--accent-light)]
119 outline-2 outline-transparent focus:outline-[var(--accent-light)] hover:outline-[var(--accent-light)] outline-offset-1
120 text-base font-bold text-accent-contrast disabled:text-border
121 flex gap-2 items-center justify-center shrink-0
122 ${props.className}
123 `}
124 >
125 {children}
126 </button>
127 );
128});
129ButtonTertiary.displayName = "ButtonTertiary";
130
131export const TooltipButton = (props: {
132 onMouseDown?: (e: React.MouseEvent) => void | Promise<void>;
133 disabled?: boolean;
134 className?: string;
135 children: React.ReactNode;
136 tooltipContent: React.ReactNode;
137 side?: "top" | "right" | "bottom" | "left" | undefined;
138 open?: boolean;
139 delayDuration?: number;
140}) => {
141 let { undoManager } = useReplicache();
142 return (
143 // toolbar button does not control the highlight theme setter
144 // if toolbar button is updated, be sure to update there as well
145 <RadixTooltip.TooltipProvider
146 delayDuration={props.delayDuration ? props.delayDuration : 400}
147 >
148 <RadixTooltip.Root open={props.open}>
149 <RadixTooltip.Trigger
150 disabled={props.disabled}
151 className={props.className}
152 onMouseDown={async (e) => {
153 e.preventDefault();
154 undoManager.startGroup();
155 props.onMouseDown && (await props.onMouseDown(e));
156 undoManager.endGroup();
157 }}
158 >
159 {props.children}
160 </RadixTooltip.Trigger>
161
162 <RadixTooltip.Portal>
163 <NestedCardThemeProvider>
164 <RadixTooltip.Content
165 side={props.side ? props.side : undefined}
166 sideOffset={6}
167 alignOffset={12}
168 className="z-10 rounded-md py-1 px-[6px] font-bold text-secondary text-sm"
169 style={{
170 backgroundColor:
171 "color-mix(in oklab, rgb(var(--primary)), rgb(var(--bg-page)) 85%)",
172 }}
173 >
174 {props.tooltipContent}
175 <RadixTooltip.Arrow
176 asChild
177 width={16}
178 height={8}
179 viewBox="0 0 16 8"
180 >
181 <PopoverArrow
182 arrowFill={
183 "color-mix(in oklab, rgb(var(--primary)), rgb(var(--bg-page)) 85%)"
184 }
185 arrowStroke="transparent"
186 />
187 </RadixTooltip.Arrow>
188 </RadixTooltip.Content>
189 </NestedCardThemeProvider>
190 </RadixTooltip.Portal>
191 </RadixTooltip.Root>
192 </RadixTooltip.TooltipProvider>
193 );
194};