a tool for shared writing and social publishing
0

Configure Feed

Select the types of activity you want to include in your feed.

add underlines to link if the text is similar to the accent color

celine (Mar 31, 2026, 8:02 PM EDT) bfa4c363 4312b444

+88 -20
+32 -10
app/globals.css
··· 96 96 --accent-2: 255, 255, 255; 97 97 --accent-contrast: 0, 0, 225; 98 98 --accent-1-is-contrast: "true"; 99 + --accent-contrast-similar-to-text: 0; 100 + --link-underline: none; 99 101 --accent-light: color-mix( 100 102 in oklab, 101 103 rgb(var(--accent-contrast)), ··· 189 191 a { 190 192 @apply text-accent-contrast; 191 193 @apply hover:cursor-pointer; 192 - @apply no-underline; 193 194 @apply hover:underline; 195 + text-decoration-line: var(--link-underline, none); 194 196 } 195 197 196 198 p { ··· 215 217 .pageScrollWrapper h2, 216 218 .pageScrollWrapper h3, 217 219 .pageScrollWrapper h4 { 218 - font-family: var(--theme-heading-font, var(--theme-font, var(--font-quattro))); 220 + font-family: var( 221 + --theme-heading-font, 222 + var(--theme-font, var(--font-quattro)) 223 + ); 219 224 } 220 225 221 226 /* Scale heading sizes relative to the custom base font size */ 222 - .pageScrollWrapper h1 { font-size: 2em; } 223 - .pageScrollWrapper h2 { font-size: 1.625em; } 224 - .pageScrollWrapper h3 { font-size: 1.125em; } 225 - .pageScrollWrapper h4 { font-size: 1em; } 227 + .pageScrollWrapper h1 { 228 + font-size: 2em; 229 + } 230 + .pageScrollWrapper h2 { 231 + font-size: 1.625em; 232 + } 233 + .pageScrollWrapper h3 { 234 + font-size: 1.125em; 235 + } 236 + .pageScrollWrapper h4 { 237 + font-size: 1em; 238 + } 226 239 227 240 /* Scale text size classes relative to the custom base font size. 228 241 Tailwind's text-sm/text-base/text-lg compile to fixed rem values 229 242 which ignore the custom base size set on .pageScrollWrapper. */ 230 - .pageScrollWrapper .textSizeSmall { font-size: 0.875em; } 231 - .pageScrollWrapper .textSizeLarge { font-size: 1.125em; } 243 + .pageScrollWrapper .textSizeSmall { 244 + font-size: 0.875em; 245 + } 246 + .pageScrollWrapper .textSizeLarge { 247 + font-size: 1.125em; 248 + } 232 249 233 250 .pageScrollWrapper pre { 234 251 font-family: var(--theme-font, var(--font-quattro)); ··· 243 260 .pubWrapper h2, 244 261 .pubWrapper h3, 245 262 .pubWrapper h4 { 246 - font-family: var(--theme-heading-font, var(--theme-font, var(--font-quattro))); 263 + font-family: var( 264 + --theme-heading-font, 265 + var(--theme-font, var(--font-quattro)) 266 + ); 247 267 } 248 268 /*END FONT STYLING*/ 249 269 ··· 571 591 .footnote-side-item { 572 592 max-height: 4.5em; 573 593 overflow: hidden; 574 - transition: max-height 200ms ease, mask-image 200ms ease; 594 + transition: 595 + max-height 200ms ease, 596 + mask-image 200ms ease; 575 597 } 576 598 .footnote-side-item.has-overflow { 577 599 mask-image: linear-gradient(to bottom, white 50%, transparent 100%);
+56 -10
components/ThemeManager/ThemeProvider.tsx
··· 29 29 PublicationThemeProvider, 30 30 } from "./PublicationThemeProvider"; 31 31 import { getColorDifference } from "./themeUtils"; 32 - import { getFontConfig, getGoogleFontsUrl, getFontFamilyValue, getFontBaseSize, defaultFontId } from "src/fonts"; 32 + import { 33 + getFontConfig, 34 + getGoogleFontsUrl, 35 + getFontFamilyValue, 36 + getFontBaseSize, 37 + defaultFontId, 38 + } from "src/fonts"; 33 39 34 40 // define a function to set an Aria Color to a CSS Variable in RGB 35 41 function setCSSVariableToColor( ··· 89 95 90 96 let pageWidth = useEntity(props.entityID, "theme/page-width"); 91 97 // Use initial font IDs as fallback until Replicache syncs 92 - let headingFontId = useEntity(props.entityID, "theme/heading-font")?.data.value ?? props.initialHeadingFontId; 93 - let bodyFontId = useEntity(props.entityID, "theme/body-font")?.data.value ?? props.initialBodyFontId; 98 + let headingFontId = 99 + useEntity(props.entityID, "theme/heading-font")?.data.value ?? 100 + props.initialHeadingFontId; 101 + let bodyFontId = 102 + useEntity(props.entityID, "theme/body-font")?.data.value ?? 103 + props.initialBodyFontId; 94 104 95 105 return ( 96 106 <CardBorderHiddenContext.Provider value={!!cardBorderHiddenValue}> ··· 192 202 accentContrast = sortedAccents[0]; 193 203 } 194 204 205 + // Check if the final accent contrast color is very similar to the text color 206 + let accentContrastSimilarToText = 207 + getColorDifference( 208 + colorToString(accentContrast, "rgb"), 209 + colorToString(primary, "rgb"), 210 + ) < 0.2; 211 + 195 212 // Get font configs for CSS variables. 196 213 // When using the default font (Quattro), use var(--font-quattro) which is 197 214 // always available via next/font/local in layout.tsx, rather than the raw ··· 203 220 const headingFontConfig = getFontConfig(headingFontId); 204 221 const bodyFontConfig = getFontConfig(bodyFontId); 205 222 const headingFontValue = isDefaultHeading 206 - ? (isDefaultBody ? undefined : "var(--font-quattro)") 223 + ? isDefaultBody 224 + ? undefined 225 + : "var(--font-quattro)" 207 226 : getFontFamilyValue(headingFontConfig); 208 227 const bodyFontValue = isDefaultBody 209 - ? (isDefaultHeading ? undefined : "var(--font-quattro)") 228 + ? isDefaultHeading 229 + ? undefined 230 + : "var(--font-quattro)" 210 231 : getFontFamilyValue(bodyFontConfig); 211 - const bodyFontBaseSize = isDefaultBody ? undefined : getFontBaseSize(bodyFontConfig); 232 + const bodyFontBaseSize = isDefaultBody 233 + ? undefined 234 + : getFontBaseSize(bodyFontConfig); 212 235 const headingGoogleFontsUrl = getGoogleFontsUrl(headingFontConfig); 213 236 const bodyGoogleFontsUrl = getGoogleFontsUrl(bodyFontConfig); 214 237 ··· 222 245 if (existingLink) return; 223 246 224 247 // Add preconnect hints if not present 225 - if (!document.querySelector('link[href="https://fonts.googleapis.com"]')) { 248 + if ( 249 + !document.querySelector('link[href="https://fonts.googleapis.com"]') 250 + ) { 226 251 const preconnect1 = document.createElement("link"); 227 252 preconnect1.rel = "preconnect"; 228 253 preconnect1.href = "https://fonts.googleapis.com"; ··· 249 274 250 275 loadGoogleFont(headingGoogleFontsUrl, headingFontConfig.fontFamily); 251 276 loadGoogleFont(bodyGoogleFontsUrl, bodyFontConfig.fontFamily); 252 - }, [headingGoogleFontsUrl, bodyGoogleFontsUrl, headingFontConfig.fontFamily, bodyFontConfig.fontFamily]); 277 + }, [ 278 + headingGoogleFontsUrl, 279 + bodyGoogleFontsUrl, 280 + headingFontConfig.fontFamily, 281 + bodyFontConfig.fontFamily, 282 + ]); 253 283 254 284 useEffect(() => { 255 285 if (local) return; ··· 293 323 "--accent-1-is-contrast", 294 324 accentContrast === accent1 ? "1" : "0", 295 325 ); 326 + el?.style.setProperty( 327 + "--accent-contrast-similar-to-text", 328 + accentContrastSimilarToText ? "1" : "0", 329 + ); 330 + el?.style.setProperty( 331 + "--link-underline", 332 + accentContrastSimilarToText ? "underline" : "none", 333 + ); 296 334 297 335 // Set page width CSS variable 298 336 el?.style.setProperty( 299 337 "--page-width-setting", 300 338 (pageWidth || 624).toString(), 301 339 ); 302 - 303 340 }, [ 304 341 local, 305 342 bgLeaflet, ··· 311 348 accent1, 312 349 accent2, 313 350 accentContrast, 351 + accentContrastSimilarToText, 314 352 pageWidth, 315 353 ]); 316 354 return ( ··· 326 364 "--accent-2": colorToString(accent2, "rgb"), 327 365 "--accent-contrast": colorToString(accentContrast, "rgb"), 328 366 "--accent-1-is-contrast": accentContrast === accent1 ? 1 : 0, 367 + "--accent-contrast-similar-to-text": accentContrastSimilarToText 368 + ? 1 369 + : 0, 370 + "--link-underline": accentContrastSimilarToText 371 + ? "underline" 372 + : "none", 329 373 "--highlight-1": highlight1 330 374 ? `rgb(${colorToString(parseColor(`hsba(${highlight1})`), "rgb")})` 331 375 : "color-mix(in oklab, rgb(var(--accent-contrast)), rgb(var(--bg-page)) 75%)", ··· 336 380 "--page-width-units": `min(${pageWidth || 624}px, calc(100vw - 12px))`, 337 381 "--theme-heading-font": headingFontValue, 338 382 "--theme-font": bodyFontValue, 339 - "--theme-font-base-size": bodyFontBaseSize ? `${bodyFontBaseSize}px` : undefined, 383 + "--theme-font-base-size": bodyFontBaseSize 384 + ? `${bodyFontBaseSize}px` 385 + : undefined, 340 386 } as CSSProperties 341 387 } 342 388 >