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