style/pdf viewer: restyle UI

This commit is contained in:
Adorian Doran 2026-02-27 19:34:26 +02:00
parent f4d91e48ba
commit 7c89c66526
2 changed files with 242 additions and 21 deletions

View File

@ -1,14 +1,37 @@
import type { HTMLAttributes, RefObject } from "preact";
import { useCallback, useEffect, useRef } from "preact/hooks";
import Inter from "./../../../fonts/Inter/Inter-VariableFont_opsz,wght.ttf";
import { useSyncedRef, useTriliumOption, useTriliumOptionBool } from "../../react/hooks";
interface FontDefinition {
name: string;
url: string;
}
const FONTS: FontDefinition[] = [
{name: "Inter", url: Inter},
]
const VARIABLE_WHITELIST = new Set([
"root-background",
"main-background-color",
"main-border-color",
"main-text-color",
"theme-style"
"theme-style",
"menu-background-color",
"dropdown-backdrop-filter",
"dropdown-border-radius",
"dropdown-border-color",
"dropdown-shadow-opacity",
"menu-padding-size",
"dropdown-backdrop-filter",
"menu-text-color",
"hover-item-background-color",
"hover-item-text-color",
"menu-item-icon-color",
"input-focus-outline-color",
"input-background-color",
"input-text-color"
]);
interface PdfViewerProps extends Pick<HTMLAttributes<HTMLIFrameElement>, "tabIndex"> {
@ -54,10 +77,14 @@ function useStyleInjection(iframeRef: RefObject<HTMLIFrameElement>) {
const style = doc.createElement('style');
style.id = 'client-root-vars';
style.textContent = cssVarsToString(getRootCssVariables());
style.textContent = cssVarsToString(getRootCssVariables());;
styleRef.current = style;
doc.head.appendChild(style);
const fontStyles = doc.createElement("style");
fontStyles.textContent = FONTS.map(injectFont).join("\n");
doc.head.appendChild(fontStyles);
}, [ iframeRef ]);
// React to changes.
@ -93,3 +120,12 @@ function cssVarsToString(vars: Record<string, string>) {
.map(([k, v]) => ` ${k}: ${v};`)
.join('\n')}\n}`;
}
function injectFont(font: FontDefinition) {
return `
@font-face {
font-family: '${font.name}';
src: url('${font.url}');
}
`;
};

View File

@ -1,31 +1,175 @@
:root {
color-scheme: var(--tn-theme-style);
/* #region General */
--body-bg-color: transparent;
--toolbar-bg-color: transparent;
:root {
--main-color: var(--tn-main-text-color);
--body-bg-color: transparent;
--toolbar-border-color: var(--tn-main-border-color);
--toolbar-bg-color: transparent;
--toolbar-icon-opacity: 1;
--toggled-btn-bg-color: var(--tn-hover-item-background-color);
--doorhanger-bg-color: var(--tn-menu-background-color);
--doorhanger-separator-color: var(--tn-main-border-color);
--page-margin: 12px auto;
--spreadHorizontalWrapped-margin-LR: 4px;
color-scheme: var(--tn-theme-style);
}
.pdfViewer {
.page,
.page > .canvasWrapper,
.page > .canvasWrapper > canvas {
border-radius: 6px;
}
:root button,
:root dialog,
:root #toolbarContainer,
:root .toolbarButton,
:root #scaleSelect,
:root .toolbarButtonWithContainer .editorParamsToolbar .editorParamsLabel,
:root #toolbarContainer #toolbarViewer input,
:root #editorUndoBar,
:root .dialogButton {
font-family: "Inter";
font-size: 11;
}
.page {
border: 1px solid var(--tn-main-border-color);
box-shadow: 7px 7px 15px #00000010;
#secondaryToolbar,
#documentPropertiesDialog,
#findbar.doorHanger,
.doorHangerRight,
#printServiceDialog {
border: 1px solid var(--tn-dropdown-border-color);
border-radius: var(--tn-dropdown-border-radius);
background-color: var(--tn-menu-background-color);
padding: var(--tn-menu-padding-size);
box-shadow: 0px 10px 20px rgba(0, 0, 0, var(--tn-dropdown-shadow-opacity));
backdrop-filter: var(--tn-dropdown-backdrop-filter);
}
.doorHangerRight,
.doorHangerLeft,
.doorHanger {
&::after, &::before {
display: none;
}
}
:root .toggle-button {
--toggle-border-color: transparent;
--toggle-background-color: var(--tn-input-background-color);
--toggle-background-color-hover: var(--toggle-background-color);
--toggle-dot-background-color: var(--tn-input-text-color);
--toggle-background-color-pressed: var(--tn-input-text-color);
--toggle-background-color-pressed-hover: var(--toggle-background-color-pressed);
cursor: pointer;
}
:root .colorPicker {
--hover-outline-color: var(--tn-input-focus-outline-color);
--selected-outline-color: var(--tn-main-text-color);
}
/* #endregion */
/* #region Toolbar */
.toolbarButton {
color: var(--menu-text-color);
&:not(.labeled):active::before {
transform: scale(.85) !important;
}
&:hover {
background: var(--tn-hover-item-background-color);
border-radius: 6px;
color: var(--tn-hover-item-text-color);
}
}
#findbar {
padding: unset;
}
#scaleSelectContainer {
--dropdown-btn-bg-color: transparent;
--button-hover-color: var(--tn-hover-item-background-color);
border-radius: 6px;
select:focus {
background: var(--tn-main-background-color);
}
}
/* Toolbar editor dropdowns */
:root .editorParamsToolbar:not(.menu),
:root #highlightParamsToolbarContainer {
padding: 10px 16px;
}
/* Toolbar dropdowns */
:root .editorParamsToolbar {
.menu {
padding: 8px;
}
.editorParamsToolbarContainer {
padding: 0;
}
}
/* Overflow menu */
#secondaryToolbar {
--toolbar-icon-bg-color: var(--tn-menu-item-icon-color);
--toolbar-icon-hover-bg-color: var(--tn-menu-item-icon-color);
--toggled-btn-bg-color: transparent;
--toggled-btn-color: currentColor;
--doorhanger-icon-opacity: 1;
padding: var(--tn-menu-padding-size);
}
/* Horizontal menu dividers */
:root #highlightParamsToolbarContainer #editorHighlightVisibility .divider,
:root .horizontalToolbarSeparator {
position: relative;
overflow: visible;
background: unset;
border: none;
&:before {
content: "";
position: absolute;
left: 0;
right: 0;
border-top: 1px solid var(--tn-main-border-color);
}
}
/* Radio menu items */
#cursorToolButtons .toolbarButton,
#scrollModeButtons .toolbarButton,
#spreadModeButtons .toolbarButton {
--toggled-hover-active-btn-color: var(--tn-hover-item-background-color);
--toggled-btn-color: var(--tn-menu-item-icon-color);
position: relative;
&::after {
display: block;
content: "";
position: absolute;
right: 0;
width: 2em;
height: 100%;
/* https://pictogrammers.com/library/mdi/icon/radiobox-blank/ */
mask-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3e%3ctitle%3eradiobox-blank%3c/title%3e%3cpath d='M12%2c20A8%2c8 0 0%2c1 4%2c12A8%2c8 0 0%2c1 12%2c4A8%2c8 0 0%2c1 20%2c12A8%2c8 0 0%2c1 12%2c20M12%2c2A10%2c10 0 0%2c0 2%2c12A10%2c10 0 0%2c0 12%2c22A10%2c10 0 0%2c0 22%2c12A10%2c10 0 0%2c0 12%2c2Z' /%3e%3c/svg%3e");
mask-size: 16px;
mask-repeat: no-repeat;
mask-position: center center;
background-color: var(--tn-main-text-color);
}
&.toggled::after {
/* https://pictogrammers.com/library/mdi/icon/radiobox-marked/ */
mask-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3e%3ctitle%3eradiobox-marked%3c/title%3e%3cpath d='M12%2c20A8%2c8 0 0%2c1 4%2c12A8%2c8 0 0%2c1 12%2c4A8%2c8 0 0%2c1 20%2c12A8%2c8 0 0%2c1 12%2c20M12%2c2A10%2c10 0 0%2c0 2%2c12A10%2c10 0 0%2c0 12%2c22A10%2c10 0 0%2c0 22%2c12A10%2c10 0 0%2c0 12%2c2M12%2c7A5%2c5 0 0%2c0 7%2c12A5%2c5 0 0%2c0 12%2c17A5%2c5 0 0%2c0 17%2c12A5%2c5 0 0%2c0 12%2c7Z' /%3e%3c/svg%3e");
}
}
/* Permanently removed buttons */
#viewsManagerToggleButton,
#downloadButton,
@ -43,10 +187,51 @@
/* #region Properties Dialog */
/* Hide irrelevant properties */
#documentPropertiesDialog > .row:has(#fileNameField),
#documentPropertiesDialog > .row:has(#linearizedField) {
display: none;
#documentPropertiesDialog {
--separator-color: transparent;
user-select: none;
padding: 1em;
.row {
line-height: 1.5;
> span {
font-weight: bold;
opacity: .5;
}
> p {
user-select: all;
}
}
/* Hide irrelevant properties */
> .row:has(#fileNameField),
> .row:has(#linearizedField) {
display: none;
}
}
/* #endregion */
/* #region Viewer Area */
.pdfViewer {
.page,
.page > .canvasWrapper,
.page > .canvasWrapper > canvas {
border-radius: 6px;
}
.page {
border: 1px solid var(--tn-main-border-color);
box-shadow: 7px 7px 15px #00000010;
}
}
#viewsManager {
display: none;
}
/* #endregion */