a tool for shared writing and social publishing
at main 5.8 kB view raw
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};