From cf958cb4b520eea4225cc1c530ffe71d4966a4af Mon Sep 17 00:00:00 2001 From: celine Date: Tue, 6 Jan 2026 19:58:10 -0500 Subject: [PATCH] added a slider to adjust page-wdith to leaflets --- app/globals.css | 25 +++- .../ThemeManager/Pickers/ImagePicker.tsx | 4 +- .../ThemeManager/Pickers/PageThemePickers.tsx | 4 +- .../ThemeManager/Pickers/PageWidthSetter.tsx | 120 ++++++++++++++++++ .../PubPickers/PubTextPickers.tsx | 4 +- components/ThemeManager/ThemeProvider.tsx | 13 ++ components/ThemeManager/ThemeSetter.tsx | 13 +- src/replicache/attributes.ts | 4 + 8 files changed, 173 insertions(+), 14 deletions(-) create mode 100644 components/ThemeManager/Pickers/PageWidthSetter.tsx diff --git a/app/globals.css b/app/globals.css index ae584c7a..46a82ac9 100644 --- a/app/globals.css +++ b/app/globals.css @@ -107,8 +107,15 @@ --highlight-3: 255, 205, 195; --list-marker-width: 36px; - --page-width-unitless: min(624, calc(var(--leaflet-width-unitless) - 12)); - --page-width-units: min(624px, calc(100vw - 12px)); + --page-max-width-unitless: 624; + --page-width-unitless: min( + var(--page-max-width-unitless), + calc(var(--leaflet-width-unitless) - 12) + ); + --page-width-units: min( + calc(var(--page-max-width-unitless) * 1px), + calc(100vw - 12px) + ); --gripperSVG: url("/gripperPattern.svg"); --gripperSVG2: url("/gripperPattern2.svg"); @@ -126,20 +133,26 @@ @media (min-width: 640px) { :root { --page-width-unitless: min( - 624, + var(--page-max-width-unitless), calc(var(--leaflet-width-unitless) - 128) ); - --page-width-units: min(624px, calc(100vw - 128px)); + --page-width-units: min( + calc(var(--page-max-width-unitless) * 1px), + calc(100vw - 128px) + ); } } @media (min-width: 1280px) { :root { --page-width-unitless: min( - 624, + var(--page-max-width-unitless), calc((var(--leaflet-width-unitless) / 2) - 32) ); - --page-width-units: min(624px, calc((100vw / 2) - 32px)); + --page-width-units: min( + calc(var(--page-max-width-unitless) * 1px), + calc((100vw / 2) - 32px) + ); } } diff --git a/components/ThemeManager/Pickers/ImagePicker.tsx b/components/ThemeManager/Pickers/ImagePicker.tsx index b5203df2..3b0a3b79 100644 --- a/components/ThemeManager/Pickers/ImagePicker.tsx +++ b/components/ThemeManager/Pickers/ImagePicker.tsx @@ -127,8 +127,8 @@ export const ImageSettings = (props: { diff --git a/components/ThemeManager/Pickers/PageThemePickers.tsx b/components/ThemeManager/Pickers/PageThemePickers.tsx index 8aaf4a61..5238caa8 100644 --- a/components/ThemeManager/Pickers/PageThemePickers.tsx +++ b/components/ThemeManager/Pickers/PageThemePickers.tsx @@ -51,7 +51,7 @@ export const PageThemePickers = (props: {
)} - void; value: Color; diff --git a/components/ThemeManager/Pickers/PageWidthSetter.tsx b/components/ThemeManager/Pickers/PageWidthSetter.tsx new file mode 100644 index 00000000..d69457dd --- /dev/null +++ b/components/ThemeManager/Pickers/PageWidthSetter.tsx @@ -0,0 +1,120 @@ +import * as Slider from "@radix-ui/react-slider"; +import { Input } from "components/Input"; +import { useEntity, useReplicache } from "src/replicache"; +import { pickers } from "../ThemeSetter"; +import { useState } from "react"; + +export const PageWidthSetter = (props: { + entityID: string; + openPicker: pickers; + thisPicker: pickers; + setOpenPicker: (thisPicker: pickers) => void; + closePicker: () => void; +}) => { + let { rep } = useReplicache(); + let pageWidth = useEntity(props.entityID, "theme/page-width"); + let currentValue = pageWidth?.data.value || 624; + let [interimValue, setInterimValue] = useState(currentValue); + let min = 324; + let max = 1200; + + let open = props.openPicker == props.thisPicker; + + return ( +
+
+
+ +
+ { + e.preventDefault(); + props.setOpenPicker(props.thisPicker); + }} + onChange={(e) => { + setInterimValue(parseInt(e.currentTarget.value)); + }} + onKeyDown={(e) => { + if (e.key === "Enter" || e.key === "Escape") { + e.preventDefault(); + let clampedValue = interimValue; + if (!isNaN(interimValue)) { + clampedValue = Math.max(min, Math.min(max, interimValue)); + setInterimValue(clampedValue); + } + rep?.mutate.assertFact({ + entity: props.entityID, + attribute: "theme/page-width", + data: { + type: "number", + value: clampedValue, + }, + }); + } + }} + onBlur={() => { + let clampedValue = interimValue; + if (!isNaN(interimValue)) { + clampedValue = Math.max(min, Math.min(max, interimValue)); + setInterimValue(clampedValue); + } + rep?.mutate.assertFact({ + entity: props.entityID, + attribute: "theme/page-width", + data: { + type: "number", + value: clampedValue, + }, + }); + }} + /> + px +
+
+ {open && ( + { + setInterimValue(value[0]); + }} + onPointerUp={() => { + rep?.mutate.assertFact({ + entity: props.entityID, + attribute: "theme/page-width", + data: { type: "number", value: interimValue }, + }); + }} + > + + + + )} +
+
+ ); +}; diff --git a/components/ThemeManager/PubPickers/PubTextPickers.tsx b/components/ThemeManager/PubPickers/PubTextPickers.tsx index 8ea5413e..9902afe9 100644 --- a/components/ThemeManager/PubPickers/PubTextPickers.tsx +++ b/components/ThemeManager/PubPickers/PubTextPickers.tsx @@ -1,5 +1,5 @@ import { pickers } from "../ThemeSetter"; -import { PageTextPicker } from "../Pickers/PageThemePickers"; +import { TextPickers } from "../Pickers/PageThemePickers"; import { Color } from "react-aria-components"; export const PagePickers = (props: { @@ -20,7 +20,7 @@ export const PagePickers = (props: { : "transparent", }} > - {props.children} @@ -106,6 +109,7 @@ export const BaseThemeProvider = ({ highlight2, highlight3, showPageBackground, + pageWidth, children, }: { local?: boolean; @@ -118,6 +122,7 @@ export const BaseThemeProvider = ({ highlight1?: string; highlight2: AriaColor; highlight3: AriaColor; + pageWidth?: number; children: React.ReactNode; }) => { // set accent contrast to the accent color that has the highest contrast with the page background @@ -196,6 +201,12 @@ export const BaseThemeProvider = ({ "--accent-1-is-contrast", accentContrast === accent1 ? "1" : "0", ); + + // Set page width CSS variable + el?.style.setProperty( + "--page-max-width-unitless", + (pageWidth || 624).toString(), + ); }, [ local, bgLeaflet, @@ -207,6 +218,7 @@ export const BaseThemeProvider = ({ accent1, accent2, accentContrast, + pageWidth, ]); return (
diff --git a/components/ThemeManager/ThemeSetter.tsx b/components/ThemeManager/ThemeSetter.tsx index 4afc5917..c55654e6 100644 --- a/components/ThemeManager/ThemeSetter.tsx +++ b/components/ThemeManager/ThemeSetter.tsx @@ -10,6 +10,7 @@ import { PageBorderHider, PageThemePickers, } from "./Pickers/PageThemePickers"; +import { PageWidthSetter } from "./Pickers/PageWidthSetter"; import { useMemo, useState } from "react"; import { ReplicacheMutators, useEntity, useReplicache } from "src/replicache"; import { Replicache } from "replicache"; @@ -35,7 +36,8 @@ export type pickers = | "highlight-1" | "highlight-2" | "highlight-3" - | "page-background-image"; + | "page-background-image" + | "page-width"; export function setColorAttribute( rep: Replicache | null, @@ -75,7 +77,7 @@ export const ThemePopover = (props: { entityID: string; home?: boolean }) => { return ( <> + setOpenPicker("null")} + />
diff --git a/src/replicache/attributes.ts b/src/replicache/attributes.ts index a902d078..c2d71974 100644 --- a/src/replicache/attributes.ts +++ b/src/replicache/attributes.ts @@ -191,6 +191,10 @@ export const ThemeAttributes = { type: "boolean", cardinality: "one", }, + "theme/page-width": { + type: "number", + cardinality: "one", + }, "theme/page-background": { type: "color", cardinality: "one", -- 2.51.2