Compare commits

...

22 Commits

Author SHA1 Message Date
Elian Doran
1170cfd4a7 fix(website): stargrazers count still not updating due to hydration 2026-02-07 13:47:25 +02:00
Elian Doran
2eddaa954e chore: address requested changes 2026-02-07 12:38:41 +02:00
Elian Doran
2c472fd03f docs(user): improve docuemntation slightly on icon packs 2026-02-07 12:37:10 +02:00
Elian Doran
16019a787e fix(website): stargazers count not updating 2026-02-07 12:27:16 +02:00
Elian Doran
717d0a75f4 chore(website): improve fit for full-height section 2026-02-07 12:20:24 +02:00
Elian Doran
cc9487bae8 chore(website): fix warnings & type issue 2026-02-07 12:17:14 +02:00
Elian Doran
5ed9ec8f46 fix(website): unnecessary horizontal scroll on md screen 2026-02-07 12:11:41 +02:00
Elian Doran
6ca37ca7f4 feat(header): improve header fit on smaller screens 2026-02-07 11:56:51 +02:00
Elian Doran
1007b8b15d fix(website): subpixel scaling causing issues at 719px 2026-02-07 11:47:30 +02:00
Elian Doran
be3a95fd54 chore(website): add resources to header 2026-02-07 11:19:46 +02:00
Elian Doran
109cb6cc3f chore(website/resources): add descriptions to fonts 2026-02-07 11:18:05 +02:00
Elian Doran
fe1509dcfc chore(website/resources): display version slightly smaller 2026-02-07 11:09:09 +02:00
Elian Doran
1797e33989 feat(website/resources): add intro blurb for icon packs 2026-02-07 11:08:03 +02:00
Elian Doran
6c504eeb3e feat(website/resources): make downloadable 2026-02-07 10:52:23 +02:00
Elian Doran
d4b16fcdd1 feat(website/resources): display icon packs 2026-02-07 10:36:00 +02:00
Elian Doran
9a08c079b5 chore(icon-pack-builder): build directly in website resource path 2026-02-07 10:24:32 +02:00
Elian Doran
98e75a7d6c chore(icon-pack-builder): generate meta alongside files 2026-02-07 10:17:58 +02:00
Elian Doran
675fd13391 chore(icon-pack-builder): add website and version meta 2026-02-07 10:15:55 +02:00
Elian Doran
e4f042aba4 fix(content_renderer): prevent iconPacks from rendering in preview 2026-02-07 09:59:53 +02:00
Elian Doran
19527845d1 fix(tree): wrong icon on multi selection with custom icons 2026-02-07 09:54:50 +02:00
Elian Doran
3aa981649c fix(icon-pack-builder): wrong icon for boxicons3-brands 2026-02-07 09:51:21 +02:00
Elian Doran
330d48f70d chore(website): create empty resources page 2026-02-07 09:42:42 +02:00
40 changed files with 668 additions and 463 deletions

View File

@@ -285,10 +285,11 @@ function getRenderingType(entity: FNote | FAttachment) {
}
const mime = "mime" in entity && entity.mime;
const isIconPack = entity instanceof FNote && entity.hasLabel("iconPack");
if (type === "file" && mime === "application/pdf") {
type = "pdf";
} else if ((type === "file" || type === "viewConfig") && mime && CODE_MIME_TYPES.has(mime)) {
} else if ((type === "file" || type === "viewConfig") && mime && CODE_MIME_TYPES.has(mime) && !isIconPack) {
type = "code";
} else if (type === "file" && mime && mime.startsWith("audio/")) {
type = "audio";

View File

@@ -206,6 +206,7 @@ span.fancytree-selected .fancytree-title {
}
span.fancytree-selected .fancytree-custom-icon::before {
font-family: "boxicons";
content: "\eb43";
border: 1px solid var(--main-border-color);
border-radius: 3px;

View File

@@ -1 +0,0 @@
*.zip

View File

@@ -1,5 +1,5 @@
import { createWriteStream, mkdirSync } from "node:fs";
import { join } from "node:path";
import { createWriteStream, mkdirSync, writeFileSync } from "node:fs";
import { join, resolve } from "node:path";
import cls from "@triliumnext/server/src/services/cls.js";
@@ -13,7 +13,8 @@ process.env.TRILIUM_RESOURCE_DIR = "../server/src";
process.env.NODE_ENV = "development";
async function main() {
const outputDir = join(__dirname, "output");
const outputDir = join(__dirname, "../../website/public/resources/icon-packs");
const outputMetaDir = join(__dirname, "../../website/src/resources/icon-packs");
mkdirSync(outputDir, { recursive: true });
const i18n = await import("@triliumnext/server/src/services/i18n.js");
@@ -49,7 +50,8 @@ async function main() {
});
// Export to zip.
const zipFilePath = join(outputDir, `${iconPack.name}.zip`);
const zipFileName = `${iconPack.name}.zip`;
const zipFilePath = join(outputDir, zipFileName);
const fileOutputStream = createWriteStream(zipFilePath);
const { exportToZip } = (await import("@triliumnext/server/src/services/export/zip.js")).default;
const taskContext = new (await import("@triliumnext/server/src/services/task_context.js")).default(
@@ -58,7 +60,15 @@ async function main() {
await exportToZip(taskContext, branch, "html", fileOutputStream, false, { skipExtraFiles: true });
await new Promise<void>((resolve) => { fileOutputStream.on("finish", resolve); });
console.log(`Built icon pack: ${iconPack.name} (${zipFilePath})`);
// Save meta.
const metaFilePath = join(outputMetaDir, `${iconPack.name}.json`);
writeFileSync(metaFilePath, JSON.stringify({
name: iconPack.name,
file: zipFileName,
...iconPack.meta
}, null, 2));
console.log(`Built icon pack ${iconPack.name}.`);
}
const builtIconPacks = [
@@ -69,6 +79,8 @@ async function main() {
phosphor("fill")
];
await Promise.all(builtIconPacks.map(buildIconPack));
console.log(`\n✅ Built icon packs are available at ${resolve(outputDir)}.`);
}
cls.init(() => {

View File

@@ -9,5 +9,10 @@ export interface IconPackData {
name: string;
mime: string;
content: Buffer;
},
meta: {
version: string;
website: string;
description: string;
}
}

View File

@@ -29,7 +29,7 @@ export default function buildIcons(pack: "basic" | "brands"): IconPackData {
return {
name: pack === "basic" ? "Boxicons 3 (Basic)" : "Boxicons 3 (Brands)",
prefix: pack === "basic" ? "bx3" : "bxl3",
icon: pack === "basic" ? "bx3 bx-cube" : "bxl3 bxl-boxicons",
icon: pack === "basic" ? "bx3 bx-cube" : "bxl3 bx-boxicons",
fontFile: {
name: `${fileName}.woff2`,
mime: "font/woff2",
@@ -37,6 +37,13 @@ export default function buildIcons(pack: "basic" | "brands"): IconPackData {
},
manifest: {
icons
},
meta: {
version: "3.0.0",
website: "https://boxicons.com/",
description: pack === "basic"
? "The Basic set of icons from Boxicons v3. This is an upgrade from Trilium's built-in icon pack (Boxicons v2)."
: "The brand set of icons from Boxicons v3."
}
};
}

View File

@@ -7,6 +7,7 @@ import { extractClassNamesFromCss, getModulePath } from "../utils";
export default function buildIcons(): IconPackData {
const baseDir = getModulePath("@mdi/font");
const packageJson = JSON.parse(readFileSync(join(baseDir, "package.json"), "utf-8"));
const cssFilePath = join(baseDir, "css", "materialdesignicons.min.css");
const cssFileContent = readFileSync(cssFilePath, "utf-8");
@@ -21,6 +22,11 @@ export default function buildIcons(): IconPackData {
name: "materialdesignicons-webfont.woff2",
mime: "font/woff2",
content: readFileSync(join(baseDir, "fonts", "materialdesignicons-webfont.woff2"))
},
meta: {
version: packageJson.version,
website: "https://pictogrammers.com/library/mdi/",
description: "The community Material Design Icons pack (@mdi/font). Not to be confused with Google's own Material Design Icons."
}
};
}

View File

@@ -5,7 +5,9 @@ import { IconPackData } from "../provider";
import { getModulePath } from "../utils";
export default function buildIcons(packName: "regular" | "fill"): IconPackData {
const baseDir = join(getModulePath("@phosphor-icons/web"), "src", packName);
const moduleDir = getModulePath("@phosphor-icons/web");
const baseDir = join(moduleDir, "src", packName);
const packageJson = JSON.parse(readFileSync(join(moduleDir, "package.json"), "utf-8"));
const iconIndex = JSON.parse(readFileSync(join(baseDir, "selection.json"), "utf-8"));
const icons: IconPackData["manifest"]["icons"] = {};
@@ -41,6 +43,13 @@ export default function buildIcons(packName: "regular" | "fill"): IconPackData {
name: fontFile!,
mime: "font/woff2",
content: readFileSync(join(baseDir, fontFile!))
},
meta: {
version: packageJson.version,
website: "https://phosphoricons.com/",
description: packName === "regular"
? "The regular weight version of Phosphor Icons."
: "The filled version of Phosphor Icons."
}
};
}

View File

@@ -1,10 +1,10 @@
<p>Frequently used notes can be bookmarked, which will make them appear in
the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_xYmIYSP6wE3F">Launch Bar</a>&nbsp;for
the&nbsp;<a class="reference-link" href="#root/_help_xYmIYSP6wE3F">Launch Bar</a>&nbsp;for
easy access.</p>
<h2>Configuring the launch bar</h2>
<p>If bookmarks don't appear in the launch bar, then most likely the bookmark
section has been hidden. Go to the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_xYmIYSP6wE3F">Launch Bar</a>&nbsp;configuration
from the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_x3i7MxGccDuM">Global menu</a>&nbsp;and
section has been hidden. Go to the&nbsp;<a class="reference-link" href="#root/_help_xYmIYSP6wE3F">Launch Bar</a>&nbsp;configuration
from the&nbsp;<a class="reference-link" href="#root/_help_x3i7MxGccDuM">Global menu</a>&nbsp;and
ensure <em>Bookmarks</em> is in the <em>Visible Launchers</em> section.</p>
<h2>Bookmark folder</h2>
<p>Space in the left panel is limited, and you might want to bookmark many

View File

@@ -1,73 +1,85 @@
<h2>Importing an existing icon pack</h2>
<figure class="image image-style-align-right image_resized" style="width:45.14%;">
<img style="aspect-ratio:854/649;" src="Icon Packs_image.png"
width="854" height="649">
</figure>
<p>By default, Trilium comes with a set of icons called Boxicons v2. Since
v0.102.0, custom icon packs allow a wider selection of icons for notes.</p>
<p>Icon packs are specific to Trilium, so they must either be created from
scratch (see below) or imported from a ZIP file from a third-party developer.</p>
<aside
class="admonition note">
<h2>Sample icon packs</h2>
<p>The Trilium team maintains a few icon packs that are not shipped with
Trilium. These icon packs can be found on the official website on the
<a
href="https://triliumnotes.org/resources">Resources page</a>.</p>
<h2>Importing an existing icon pack</h2>
<aside class="admonition note">
<p><strong>Icon packs are third-party content</strong>
</p>
<p>The Trilium maintainers are not responsible for keeping these icon packs
up to date. If you have an issue with a specific icon pack, then the issue
must be reported to the third-party developer responsible for it, not the
Trilium team.</p>
</aside>
<p>To import an icon pack:</p>
<ol>
<li>Ideally, create a dedicated spot in your note tree where to place the
icon packs.</li>
<li>Right click the note where to put it and select <em>Import into note</em>.</li>
<li>Uncheck <em>Safe import</em>.</li>
<p>Apart from the <a href="https://triliumnotes.org/resources">sample icon packs</a>,
the Trilium maintainers are not responsible for keeping icon packs up to
date. If you have an issue with a specific icon pack, then the issue must
be reported to the third-party developer responsible for it, not the Trilium
team.</p>
</aside>
<p>To import an icon pack:</p>
<ol>
<li>Ideally, create a dedicated spot in your note tree where to place the
icon packs.</li>
<li>Right click the note where to put it and select <em>Import into note</em>.</li>
<li
>Uncheck <em>Safe import</em>.</li>
<li>Select <em>Import</em>.</li>
<li><a href="#root/_help_s8alTXmpFR61">Refresh the application</a>.</li>
</ol>
<aside class="admonition warning">
<p>Since <em>Safe import</em> is disabled, make sure you trust the source as
it could contain dangerous third-party scripts. One good way to check if
the icon pack is safe is to manually extract the .zip and inspect the file
contents. Icon packs should only contain a font file and a JSON file. Other
files (especially scripts) are to be considered harmful.</p>
</aside>
<h2>Creating an icon pack</h2>
<p>Creating an icon pack requires some scripting knowledge outside Trilium
in order to generate the list of icons. For information, see&nbsp;<a class="reference-link"
href="#root/_help_g1mlRoU8CsqC">Creating an icon pack</a>.</p>
<h2>Using an icon from an icon pack</h2>
<p>After <a href="#root/_help_s8alTXmpFR61">refreshing the application</a>, the
icon pack should be enabled by default. To test this, simply select an
existing note or create a new one and try to change the note icon.</p>
<p>There should be a <em>Filter</em> button to the right of the search bar
in the icon list. Clicking it allows filtering by icon pack and the newly
imported icon pack should be displayed there.</p>
<aside class="admonition note">
<p>If the icon pack is missing from that list, then most likely there's something
wrong with it.</p>
<ul>
<li>Try checking the&nbsp;<a class="reference-link" href="#root/_help_bnyigUA2UK7s">Backend (server) logs</a>&nbsp;for
clues and make sure that the icon pack has the <code spellcheck="false">#iconPack</code>
<a
href="#root/_help_HI6GBBIduIgv">label</a>with a value assigned to it (a prefix).</li>
<li>Icon packs that are <a href="#root/_help_bwg0e8ewQMak">protected</a> are ignored.</li>
</ul>
</aside>
<h2>Integration with the share and export functionality</h2>
<p>Custom icon packs are also supported by the&nbsp;<a class="reference-link"
href="#root/_help_R9pX4DGra2Vt">Sharing</a>&nbsp;feature, where they will be
shown in the note tree. However, in order for an icon pack to be visible
to the share function, the icon pack note must also be shared.</p>
<p>If you are using a custom share theme, make sure it supports the
<code
spellcheck="false">iconPackCss</code>, otherwise icons will not show up. Check the original
share template source code for reference.</p>
<p>Custom icon packs will also be preserved when&nbsp;<a class="reference-link"
href="#root/_help_ycBFjKrrwE9p">Exporting static HTML for web publishing</a>.
In this case, there's no requirement to make the icon pack shared.</p>
<h2>What happens if I remove an icon pack</h2>
<p>If an icon pack is removed or disabled (by removing or altering its
<code
spellcheck="false">#iconPack</code>label), all the notes that use this icon pack will show
in the&nbsp;<a class="reference-link" href="#root/_help_oPVyFC7WL2Lp">Note Tree</a>&nbsp;with
no icon. This won't cause any issues apart from looking strange.</p>
<p>The solution is to replace the icons with some else, try using&nbsp;
<a
class="reference-link" href="#root/_help_eIg8jdvaoNNd">Search</a>&nbsp;which supports bulk actions, to identify the notes with
the now deleted icon pack (by looking for the prefix) and changing or removing
their <code spellcheck="false">iconClass</code>.</p>
</ol>
<aside class="admonition warning">
<p>Since <em>Safe import</em> is disabled, make sure you trust the source as
it could contain dangerous third-party scripts. One good way to check if
the icon pack is safe is to manually extract the .zip and inspect the file
contents. Icon packs should only contain a font file and a JSON file. Other
files (especially scripts) are to be considered harmful.</p>
</aside>
<h2>Creating an icon pack</h2>
<p>Creating an icon pack requires some scripting knowledge outside Trilium
in order to generate the list of icons. For information, see&nbsp;<a class="reference-link"
href="#root/_help_g1mlRoU8CsqC">Creating an icon pack</a>.</p>
<h2>Using an icon from an icon pack</h2>
<p>After <a href="#root/_help_s8alTXmpFR61">refreshing the application</a>, the
icon pack should be enabled by default. To test this, simply select an
existing note or create a new one and try to change the note icon.</p>
<p>There should be a <em>Filter</em> button to the right of the search bar
in the icon list. Clicking it allows filtering by icon pack and the newly
imported icon pack should be displayed there.</p>
<aside class="admonition note">
<p>If the icon pack is missing from that list, then most likely there's something
wrong with it.</p>
<ul>
<li>Try checking the&nbsp;<a class="reference-link" href="#root/_help_bnyigUA2UK7s">Backend (server) logs</a>&nbsp;for
clues and make sure that the icon pack has the <code spellcheck="false">#iconPack</code>
<a
href="#root/_help_HI6GBBIduIgv">label</a>with a value assigned to it (a prefix).</li>
<li>Icon packs that are <a href="#root/_help_bwg0e8ewQMak">protected</a> are ignored.</li>
</ul>
</aside>
<h2>Integration with the share and export functionality</h2>
<p>Custom icon packs are also supported by the&nbsp;<a class="reference-link"
href="#root/_help_R9pX4DGra2Vt">Sharing</a>&nbsp;feature, where they will be
shown in the note tree. However, in order for an icon pack to be visible
to the share function, the icon pack note must also be shared.</p>
<p>If you are using a custom share theme, make sure it supports the
<code
spellcheck="false">iconPackCss</code>, otherwise icons will not show up. Check the original
share template source code for reference.</p>
<p>Custom icon packs will also be preserved when&nbsp;<a class="reference-link"
href="#root/_help_ycBFjKrrwE9p">Exporting static HTML for web publishing</a>.
In this case, there's no requirement to make the icon pack shared.</p>
<h2>What happens if I remove an icon pack</h2>
<p>If an icon pack is removed or disabled (by removing or altering its
<code
spellcheck="false">#iconPack</code>label), all the notes that use this icon pack will show
in the&nbsp;<a class="reference-link" href="#root/_help_oPVyFC7WL2Lp">Note Tree</a>&nbsp;with
no icon. This won't cause any issues apart from looking strange.</p>
<p>The solution is to replace the icons with some else, try using&nbsp;
<a
class="reference-link" href="#root/_help_eIg8jdvaoNNd">Search</a>&nbsp;which supports bulk actions, to identify the notes with
the now deleted icon pack (by looking for the prefix) and changing or removing
their <code spellcheck="false">iconClass</code>.</p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

View File

@@ -1,7 +1,7 @@
<h2>Position of the Launch bar</h2>
<p>On desktop, depending on the layout selected, the launcher bar will either
be on the left side of the screen with buttons displayed vertically or
at the top of the screen. See&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_x0JgW8UqGXvq">Vertical and horizontal layout</a>&nbsp;for
at the top of the screen. See&nbsp;<a class="reference-link" href="#root/_help_x0JgW8UqGXvq">Vertical and horizontal layout</a>&nbsp;for
more information.</p>
<p>On mobile, the launch bar will always be at the bottom.</p>
<p>If there are too many items in the launch bar to fit the screen, it will
@@ -21,10 +21,10 @@
<li>Right click in the empty space between launchers on the launch bar and
select <em>Configure Launchbar.</em>
</li>
<li>Click on the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_x3i7MxGccDuM">Global menu</a>&nbsp;and
<li>Click on the&nbsp;<a class="reference-link" href="#root/_help_x3i7MxGccDuM">Global menu</a>&nbsp;and
select <em>Configure Launchbar</em>.</li>
</ul>
<p>This will open a new tab with the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_oPVyFC7WL2Lp">Note Tree</a>&nbsp;listing
<p>This will open a new tab with the&nbsp;<a class="reference-link" href="#root/_help_oPVyFC7WL2Lp">Note Tree</a>&nbsp;listing
the launchers.</p>
<p>
<img src="Launch Bar_image.png">
@@ -37,11 +37,10 @@
one. The reasoning is that not all desktop icons are available on mobile,
and fewer icons fit on a mobile screen.</p>
<p>To configure the launch bar on mobile, go to&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_x3i7MxGccDuM">Global menu</a>&nbsp;and
select <em>Configure Launchbar</em>.</p>
href="#root/_help_x3i7MxGccDuM">Global menu</a>&nbsp;and select <em>Configure Launchbar</em>.</p>
<p>The configure the mobile launch bar while on the desktop (especially useful
to configure more complicated launchers such as scripts or custom widgets),
go to&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_x3i7MxGccDuM">Global menu</a>&nbsp;
go to&nbsp;<a class="reference-link" href="#root/_help_x3i7MxGccDuM">Global menu</a>&nbsp;
Advanced → Show Hidden Subtree and look for the <em>Mobile Launch Bar</em> section.
While in the hidden subtree, it's also possible to drag launchers between
the <em>Mobile Launch Bar</em> and (Desktop) <em>Launch Bar</em> sections.</p>
@@ -52,13 +51,13 @@
<p>Similarly, to remove it from the launch bar, simply look for it in <em>Visible Launchers</em> then
right click it and select <em>Move to available launchers</em> or use drag-and-drop.</p>
<p>Drag-and-drop the items in the&nbsp;tree&nbsp;in order to change their
order. See&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_oPVyFC7WL2Lp">Note Tree</a>&nbsp;for
order. See&nbsp;<a class="reference-link" href="#root/_help_oPVyFC7WL2Lp">Note Tree</a>&nbsp;for
more interaction options, including using keyboard shortcuts.</p>
<h2>Customizing the launcher</h2>
<ul>
<li>The icon of a launcher can be changed just like a normal note. See&nbsp;
<a
class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/BFs8mudNFgCS/_help_p9kXRFAkwN4o">Note Icons</a>&nbsp;for more information.</li>
class="reference-link" href="#root/_help_p9kXRFAkwN4o">Note Icons</a>&nbsp;for more information.</li>
<li>The title of the launcher can also be changed.</li>
</ul>
<h3>Resetting</h3>
@@ -70,39 +69,43 @@
<p>Right click either the <em>Available launchers</em> or <em>Visible launchers</em> sections
and select one of the options:</p>
<ol>
<li><strong>Note Launcher</strong>
<br>A note launcher will simply navigate to a specified note.
<li>
<p><strong>Note Launcher</strong>
<br>A note launcher will simply navigate to a specified note.</p>
<ol>
<li>Set the <code spellcheck="false">target</code> promoted attribute to the
note to navigate to.</li>
<li>Optionally, set <code spellcheck="false">hoistedNote</code> to hoist a particular
note. See&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/wArbEsdSae6g/_help_OR8WJ7Iz9K4U">Note Hoisting</a>&nbsp;for
note. See&nbsp;<a class="reference-link" href="#root/_help_OR8WJ7Iz9K4U">Note Hoisting</a>&nbsp;for
more information.</li>
<li>Optionally, set a <code spellcheck="false">keyboardShortcut</code> to trigger
the launcher.</li>
</ol>
</li>
<li><strong>Script Launcher</strong>
<br>An advanced launcher which will run a script upon pressing. See&nbsp;
<a
class="reference-link" href="#root/pOsGYCXsbNQG/_help_CdNpE2pqjmI6">Scripting</a>&nbsp;for more information.
<ol>
<li>Set <code spellcheck="false">script</code> to point to the desired script
to run.</li>
<li>Optionally, set a <code spellcheck="false">keyboardShortcut</code> to trigger
the launcher.</li>
</ol>
<li>
<p><strong>Script Launcher</strong>
<br>An advanced launcher which will run a script upon pressing. See&nbsp;
<a
class="reference-link" href="#root/_help_CdNpE2pqjmI6">Scripting</a>&nbsp;for more information.</p>
<ol>
<li>Set <code spellcheck="false">script</code> to point to the desired script
to run.</li>
<li>Optionally, set a <code spellcheck="false">keyboardShortcut</code> to trigger
the launcher.</li>
</ol>
</li>
<li class="ck-list-marker-bold">
<li>
<p><strong>Custom Widget</strong>
</p>
<p>Allows defining a custom widget to be rendered inside the launcher. See&nbsp;
<a
class="reference-link" href="#root/pOsGYCXsbNQG/CdNpE2pqjmI6/yIhgI5H7A2Sm/MgibgPcfeuGz/_help_SynTBQiBsdYJ">Widget Basics</a>&nbsp;for more information.</p>
class="reference-link" href="#root/_help_SynTBQiBsdYJ">Widget Basics</a>&nbsp;for more information.</p>
</li>
<li>
<p><strong>Spacers</strong>
<br>Launchers that create some distance between other launchers for better
visual distinction.</p>
</li>
<li><strong>Spacers</strong>
<br>Launchers that create some distance between other launchers for better
visual distinction.</li>
</ol>
<p>Launchers are configured via predefined&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/tC7s2alapj8V/zEY4DaJG4YT5/_help_OFXdgB2nNk1F">Promoted Attributes</a>.</p>
href="#root/_help_OFXdgB2nNk1F">Promoted Attributes</a>.</p>

View File

@@ -4,7 +4,8 @@ class="image image-style-align-center">
<img style="aspect-ratio:1398/1015;" src="Split View_2_Split View_im.png"
width="1398" height="1015">
</figure>
<h2><strong>Interactions</strong></h2>
<h2><strong>Interactions</strong></h2>
<ul>
<li>Press the
<img src="Split View_Split View_imag.png">button to the right of a note's title to open a new split to the right
@@ -50,12 +51,11 @@ class="image image-style-align-center">
<ul>
<li>On smartphones, the split views are laid out vertically (one on the top
and one on the bottom), instead of horizontally as on the desktop.</li>
<li
>There can be only one split open per tab.</li>
<li>It's not possible to resize the two split panes.</li>
<li>When the keyboard is opened, the active note will be “maximized”, thus
allowing for more space even when a split is open. When the keyboard is
closed, the splits become equal in size again.</li>
<li>There can be only one split open per tab.</li>
<li>It's not possible to resize the two split panes.</li>
<li>When the keyboard is opened, the active note will be “maximized”, thus
allowing for more space even when a split is open. When the keyboard is
closed, the splits become equal in size again.</li>
</ul>
<p>Interaction:</p>
<ul>

View File

@@ -8,8 +8,7 @@
<ul>
<li>For the vertical layout, the tabs will be placed at the top but to the
right of the&nbsp;<a class="reference-link" href="#root/_help_oPVyFC7WL2Lp">Note Tree</a>.</li>
<li
>For the horizontal layout, the tabs will be placed at the top in full-width,
<li>For the horizontal layout, the tabs will be placed at the top in full-width,
above the&nbsp;<a href="#root/_help_oPVyFC7WL2Lp">note tree</a>, allowing for
more tabs to be comfortably displayed.</li>
</ul>
@@ -23,8 +22,7 @@
href="#root/_help_luNhaphA37EO">Split View</a>. Each tab can have one or more
notes, displayed horizontally.</li>
<li>Tabs can be reordered by drag-and-dropping it into a new position.</li>
<li
>An existing tab can be displayed in a new window by dragging the tab upwards
<li>An existing tab can be displayed in a new window by dragging the tab upwards
or downwards. It is not possible to combine tabs back into another window.</li>
</ul>
<h2>Keyboard interaction</h2>
@@ -47,20 +45,20 @@
<img style="aspect-ratio:1242/2688;" src="Tabs_IMG_1767.PNG"
width="1242" height="2688">
</figure>
<p>Tabs are also supported on the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/Otzi9La2YAUX/_help_RDslemsQ6gCp">Mobile Frontend</a>.</p>
<p>Tabs are also supported on the&nbsp;<a class="reference-link" href="#root/_help_RDslemsQ6gCp">Mobile Frontend</a>.</p>
<p>Since v0.102.0, the tabs are displayed by pressing the dedicated tab switcher
button in the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_xYmIYSP6wE3F">Launch Bar</a>.
button in the&nbsp;<a class="reference-link" href="#root/_help_xYmIYSP6wE3F">Launch Bar</a>.
In this view the tabs are laid out on a grid with a preview of the note
content.</p>
<p>The context menu button at the top-right of the popup allows creating
a new tab, reopening the last closed tab and closing all the tabs.</p>
<p><a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_luNhaphA37EO">Split View</a>s
are also indicated in the tab switcher, with two titles displayed in a
tab.</p>
<aside class="admonition note">
<p><a class="reference-link" href="#root/_help_luNhaphA37EO">Split View</a>s are
also indicated in the tab switcher, with two titles displayed in a tab.</p>
<aside
class="admonition note">
<p>Versions prior to v0.102.0 also supported tabs, but they were displayed
directly above the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_xYmIYSP6wE3F">Launch Bar</a>.
directly above the&nbsp;<a class="reference-link" href="#root/_help_xYmIYSP6wE3F">Launch Bar</a>.
The decision to use a more mobile-like tab switcher was taken because the
original tab bar could not support many tabs at once and the new design
better aligns with how mobile applications handle tabs.</p>
</aside>
</aside>

View File

@@ -14,36 +14,33 @@
and the mobile one:</p>
<ul>
<li>
<p>The&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_oPVyFC7WL2Lp">Note Tree</a>&nbsp;is
<p>The&nbsp;<a class="reference-link" href="#root/_help_oPVyFC7WL2Lp">Note Tree</a>&nbsp;is
displayed as a sidebar. To display the sidebar, press the button in the
top-left of the screen.</p>
<ul>
<li>
<p>There is also a swipe gesture that can be done from the left of the screen,
but the browser's navigation gesture interferes with it most of the time
(depending on the platform).</p>
</li>
<li>
<p>Press and hold a note to display the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/oPVyFC7WL2Lp/_help_YtSN43OrfzaA">Note tree contextual menu</a>.</p>
</li>
<li>There is also a swipe gesture that can be done from the left of the screen,
but the browser's navigation gesture interferes with it most of the time
(depending on the platform).</li>
<li>Press and hold a note to display the&nbsp;<a class="reference-link" href="#root/_help_YtSN43OrfzaA">Note tree contextual menu</a>.</li>
</ul>
</li>
<li>The&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/wArbEsdSae6g/_help_Ms1nauBra7gq">Quick search</a>&nbsp;bar
is also displayed at the top of the note tree.</li>
<li>The full&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/wArbEsdSae6g/_help_eIg8jdvaoNNd">Search</a>&nbsp;function
can be triggered either from either the&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_x3i7MxGccDuM">Global menu</a>&nbsp;or
from the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_xYmIYSP6wE3F">Launch Bar</a>,
if configured.</li>
<li>
<p>The&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_xYmIYSP6wE3F">Launch Bar</a>&nbsp;is
<p>The&nbsp;<a class="reference-link" href="#root/_help_Ms1nauBra7gq">Quick search</a>&nbsp;bar
is also displayed at the top of the note tree.</p>
</li>
<li>
<p>The full&nbsp;<a class="reference-link" href="#root/_help_eIg8jdvaoNNd">Search</a>&nbsp;function
can be triggered either from either the&nbsp;<a class="reference-link"
href="#root/_help_x3i7MxGccDuM">Global menu</a>&nbsp;or from the&nbsp;<a class="reference-link"
href="#root/_help_xYmIYSP6wE3F">Launch Bar</a>, if configured.</p>
</li>
<li>
<p>The&nbsp;<a class="reference-link" href="#root/_help_xYmIYSP6wE3F">Launch Bar</a>&nbsp;is
displayed at the bottom of the screen.</p>
<ul>
<li>
<p>The launch bar uses a different configuration for icons than the desktop
version. See the dedicated page for more information on how to configure
it.</p>
</li>
<li>The launch bar uses a different configuration for icons than the desktop
version. See the dedicated page for more information on how to configure
it.</li>
</ul>
</li>
<li>
@@ -51,18 +48,18 @@
on the top-right of the note.</p>
</li>
<li>
<p>The&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_3seOhtN8uLIY">Tabs</a>&nbsp;are
grouped under a tab switcher in the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_xYmIYSP6wE3F">Launch Bar</a>,
<p>The&nbsp;<a class="reference-link" href="#root/_help_3seOhtN8uLIY">Tabs</a>&nbsp;are
grouped under a tab switcher in the&nbsp;<a class="reference-link" href="#root/_help_xYmIYSP6wE3F">Launch Bar</a>,
where the tabs are displayed in a full-screen grid with preview for easy
switching, as well as additional options such as reopening closed tabs.</p>
</li>
<li>
<p>Since v0.100.0,&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_luNhaphA37EO">Split View</a>&nbsp;can
<p>Since v0.100.0,&nbsp;<a class="reference-link" href="#root/_help_luNhaphA37EO">Split View</a>&nbsp;can
also be used in mobile view, but with a maximum of two panes at once. The
splits are displayed vertically instead of horizontally.</p>
</li>
<li>
<p>Starting with v0.102.0, the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_IjZS7iK5EXtb">New Layout</a>&nbsp;is
<p>Starting with v0.102.0, the&nbsp;<a class="reference-link" href="#root/_help_IjZS7iK5EXtb">New Layout</a>&nbsp;is
enforced on mobile. This brings features such as the note badges, note
type switcher or collection properties which would otherwise not be available.</p>
</li>
@@ -74,17 +71,10 @@
<h3>On iOS with Safari</h3>
<ol>
<li>Open your default web browser and access your Trilium instance.</li>
<li
>Login.</li>
<li>
<p>Press the […] button in the bottom-right of the screen and select Share.</p>
</li>
<li>
<p>Scroll down to reveal the full list of items and choose “Add to Home Screen”.</p>
</li>
<li>
<p>Press “Add” and the web app will be available.</p>
</li>
<li>Login.</li>
<li>Press the […] button in the bottom-right of the screen and select Share.</li>
<li>Scroll down to reveal the full list of items and choose “Add to Home Screen”.</li>
<li>Press “Add” and the web app will be available.</li>
</ol>
<h3>On Android with Google Chrome</h3>
<aside class="admonition important">
@@ -94,22 +84,13 @@
</aside>
<ol>
<li>Open your default web browser and access your Trilium instance.</li>
<li
>Login.</li>
<li>
<p>Press the three vertical dots icon in the top-right of the screen and
select <em>Add to Home screen.</em>
</p>
</li>
<li>
<p>Select the <em>Install</em> option.</p>
</li>
<li>
<p>Select an appropriate name.</p>
</li>
<li>
<p>The web app will appear as an application, not on the home screen.</p>
</li>
<li>Login.</li>
<li>Press the three vertical dots icon in the top-right of the screen and
select <em>Add to Home screen.</em>
</li>
<li>Select the <em>Install</em> option.</li>
<li>Select an appropriate name.</li>
<li>The web app will appear as an application, not on the home screen.</li>
</ol>
<h3>On Android with Brave</h3>
<aside class="admonition important">
@@ -119,33 +100,19 @@
</aside>
<ol>
<li>Open your default web browser and access your Trilium instance.</li>
<li
>Login.</li>
<li>
<p>Press the three vertical dots icon in the bottom-right of the screen and
select <em>Add to Home screen</em>.</p>
</li>
<li>
<p>Press the <em>Install</em> option.</p>
</li>
<li>
<p>The web app will appear as an application, not on the home screen.</p>
</li>
<li>Login.</li>
<li>Press the three vertical dots icon in the bottom-right of the screen and
select <em>Add to Home screen</em>.</li>
<li>Press the <em>Install</em> option.</li>
<li>The web app will appear as an application, not on the home screen.</li>
</ol>
<h3>On Samsung Browser</h3>
<ol>
<li>Open your default web browser and access your Trilium instance.</li>
<li
>Login.</li>
<li>
<p>Press the hamburger menu in the bottom-right of the screen.</p>
</li>
<li>
<p>Select <em>Add to</em>, followed by <em>Home screen</em>.</p>
</li>
<li>
<p>Press <em>Add</em> and the web app will appear on the home page.</p>
</li>
<li>Login.</li>
<li>Press the hamburger menu in the bottom-right of the screen.</li>
<li>Select <em>Add to</em>, followed by <em>Home screen</em>.</li>
<li>Press <em>Add</em> and the web app will appear on the home page.</li>
</ol>
<h2>Testing via the desktop application</h2>
<p>If you are running Trilium without a dedicated <a href="#root/_help_WOcw2SLH6tbX">server installation</a>,
@@ -159,10 +126,10 @@
spellcheck="false">?desktop</code>query param on <strong>login</strong> page (Note: you might
need to log out).</p>
<p>Alternatively, simply select <em>Switch to Mobile/Desktop Version</em> in
the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_x3i7MxGccDuM">Global menu</a>.</p>
the&nbsp;<a class="reference-link" href="#root/_help_x3i7MxGccDuM">Global menu</a>.</p>
<h2>Scripting</h2>
<p>You can alter the behavior with&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/_help_CdNpE2pqjmI6">Scripting</a>,
<p>You can alter the behavior with&nbsp;<a class="reference-link" href="#root/_help_CdNpE2pqjmI6">Scripting</a>,
just like for normal frontend. For script notes to be executed, they need
to have labeled <code spellcheck="false">#run=mobileStartup</code>.</p>
<p>Custom&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_xYmIYSP6wE3F">Launch Bar</a>&nbsp;widgets
<p>Custom&nbsp;<a class="reference-link" href="#root/_help_xYmIYSP6wE3F">Launch Bar</a>&nbsp;widgets
are also supported.</p>

View File

@@ -1,7 +1,9 @@
import { ComponentChildren } from "preact";
import Icon from "./Icon.js";
import "./Button.css";
import { ComponentChildren } from "preact";
import Icon from "./Icon.js";
interface LinkProps {
className?: string;
href?: string;
@@ -9,6 +11,7 @@ interface LinkProps {
children?: ComponentChildren;
title?: string;
onClick?: (e: MouseEvent) => void;
download?: boolean;
}
interface ButtonProps extends Omit<LinkProps, "children"> {
@@ -16,6 +19,7 @@ interface ButtonProps extends Omit<LinkProps, "children"> {
iconSvg?: string;
text: ComponentChildren;
openExternally?: boolean;
download?: boolean;
outline?: boolean;
}
@@ -28,17 +32,18 @@ export default function Button({ iconSvg, text, className, outline, ...restProps
{iconSvg && <><Icon svg={iconSvg} />{" "}</>}
<span class="text">{text}</span>
</Link>
)
);
}
export function Link({ openExternally, children, ...restProps }: LinkProps) {
export function Link({ openExternally, children, download, ...restProps }: LinkProps) {
return (
<a
{...restProps}
target={openExternally ? "_blank" : undefined}
rel={openExternally ? "noopener noreferrer" : undefined}
target={openExternally || download ? "_blank" : undefined}
download={download}
rel={openExternally || download ? "noopener noreferrer" : undefined}
>
{children}
</a>
)
);
}

View File

@@ -4,7 +4,7 @@ header {
top: 0;
background: var(--header-background-color);
box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
backdrop-filter: blur(20px);
backdrop-filter: blur(20px);
z-index: 1000;
--gap: 1.25em;
font-size: 0.8em;
@@ -23,7 +23,7 @@ header {
justify-items: center;
text-decoration: none;
color: inherit;
&:hover { text-decoration: none;}
}
@@ -67,7 +67,7 @@ header {
}
}
@media (max-width: 719px) {
@media (max-width: 719.99px) {
:root {
--header-height: 60px;
}
@@ -100,7 +100,7 @@ header {
flex-direction: column;
max-height: 0;
overflow: hidden;
transition: max-height 200ms ease-in;
transition: max-height 200ms ease-in;
&.mobile-shown {
display: flex;
@@ -113,7 +113,7 @@ header {
header + main {
margin-top: var(--header-height);
}
header nav a {
font-size: 1.25em;
padding: 0.5em 0;
@@ -144,4 +144,31 @@ header {
height: 48px;
}
}
}
}
@media ((min-width: 720px) and (max-width: 1115px)) {
header {
.banner span {
display: none;
}
.repository-button {
display: none;
}
nav {
font-size: 0.9em;
justify-content: center;
}
.download-button {
font-size: 0.8em;
padding: 0.5em;
.text {
display: flex;
flex-direction: column;
}
}
}
}

View File

@@ -1,16 +1,18 @@
import "./Header.css";
import { Link } from "./Button.js";
import { SocialButtons, SocialButton } from "./Footer.js";
import { useContext, useEffect, useMemo, useState } from "preact/hooks";
import { useLocation } from 'preact-iso';
import DownloadButton from './DownloadButton.js';
import githubIcon from "../assets/boxicons/bx-github.svg?raw";
import Icon from "./Icon.js";
import logoPath from "../assets/icon-color.svg";
import menuIcon from "../assets/boxicons/bx-menu.svg?raw";
import { LocaleContext } from "..";
import { useTranslation } from "react-i18next";
import { LocaleContext } from "..";
import githubIcon from "../assets/boxicons/bx-github.svg?raw";
import menuIcon from "../assets/boxicons/bx-menu.svg?raw";
import logoPath from "../assets/icon-color.svg";
import { swapLocaleInUrl } from "../i18n";
import { Link } from "./Button.js";
import DownloadButton from './DownloadButton.js';
import { SocialButton,SocialButtons } from "./Footer.js";
import Icon from "./Icon.js";
interface HeaderLink {
url: string;
@@ -19,7 +21,7 @@ interface HeaderLink {
}
export function Header(props: {repoStargazersCount: number}) {
const { url } = useLocation();
const { url } = useLocation();
const { t } = useTranslation();
const locale = useContext(LocaleContext);
const [ mobileMenuShown, setMobileMenuShown ] = useState(false);
@@ -28,13 +30,14 @@ export function Header(props: {repoStargazersCount: number}) {
useEffect(() => {
setHeaderLinks([
{ url: "/get-started", text: t("header.get-started") },
{ url: "/resources", text: t("header.resources") },
{ url: "https://docs.triliumnotes.org/", text: t("header.documentation"), external: true },
{ url: "/support-us", text: t("header.support-us") }
]);
}, [ locale, t ]);
return (
<header>
return (
<header>
<div class="content-wrapper">
<div class="first-row">
<a class="banner" href={`/${locale}/`}>
@@ -46,7 +49,7 @@ export function Header(props: {repoStargazersCount: number}) {
className="mobile-only menu-toggle"
onClick={(e) => {
e.preventDefault();
setMobileMenuShown(!mobileMenuShown)
setMobileMenuShown(!mobileMenuShown);
}}
>
<Icon svg={menuIcon} />
@@ -63,7 +66,7 @@ export function Header(props: {repoStargazersCount: number}) {
onClick={() => {
setMobileMenuShown(false);
}}
>{link.text}</Link>)
>{link.text}</Link>);
})}
<SocialButtons className="mobile-only" withText />
@@ -73,7 +76,7 @@ export function Header(props: {repoStargazersCount: number}) {
<SocialButton
name="GitHub"
iconSvg={githubIcon}
counter={(props.repoStargazersCount / 1000).toFixed(1) + "K+"}
counter={`${(props.repoStargazersCount / 1000).toFixed(1) }K+`}
url="https://github.com/TriliumNext/Trilium"
/>
</div>
@@ -81,6 +84,6 @@ export function Header(props: {repoStargazersCount: number}) {
<DownloadButton />
</div>
</header>
);
</header>
);
}

View File

@@ -6,23 +6,26 @@ let repoStargazersCount: number | null = null;
/** Returns the number of stargazers of the Trilium's GitHub repository. */
export async function getRepoStargazersCount() {
if (repoStargazersCount === null) {
repoStargazersCount = await fetchRepoStargazersCount() && FALLBACK_STARGAZERS_COUNT;
}
return repoStargazersCount;
if (repoStargazersCount === null) {
repoStargazersCount = await fetchRepoStargazersCount();
}
return repoStargazersCount;
}
async function fetchRepoStargazersCount(): Promise<number | null> {
console.log("\nFetching stargazers count from GitHub API... ");
const response = await fetch(API_URL);
async function fetchRepoStargazersCount(): Promise<number> {
console.log("\nFetching stargazers count from GitHub API... ");
const response = await fetch(API_URL);
if (response.ok) {
const details = await response.json();
if ("stargazers_count" in details) {
return details["stargazers_count"];
}
}
if (response.ok) {
const details = await response.json();
const count = details["stargazers_count"];
console.error("Failed to fetch stargazers count from GitHub API:", response.status, response.statusText);
return null;
}
if (count) {
console.log(`Got number of stargazers: ${count}`);
return count;
}
}
console.error("Failed to fetch stargazers count from GitHub API:", response.status, response.statusText);
return FALLBACK_STARGAZERS_COUNT;
}

View File

@@ -1,71 +1,78 @@
import './style.css';
import { FALLBACK_STARGAZERS_COUNT, getRepoStargazersCount } from './github-utils.js';
import { Header } from './components/Header.jsx';
import { Home } from './pages/Home/index.jsx';
import { LocationProvider, Router, Route, hydrate, prerender as ssr, useLocation } from 'preact-iso';
import { NotFound } from './pages/_404.jsx';
import Footer from './components/Footer.js';
import GetStarted from './pages/GetStarted/get-started.js';
import SupportUs from './pages/SupportUs/SupportUs.js';
import { changeLanguage } from 'i18next';
import { createContext } from 'preact';
import { useLayoutEffect, useRef } from 'preact/hooks';
import { changeLanguage } from 'i18next';
import { hydrate, LocationProvider, prerender as ssr, Route, Router, useLocation } from 'preact-iso';
import Footer from './components/Footer.js';
import { Header } from './components/Header.jsx';
import { getRepoStargazersCount } from './github-utils';
import { extractLocaleFromUrl, initTranslations, LOCALES, mapLocale } from './i18n';
import { NotFound } from './pages/_404.jsx';
import GetStarted from './pages/GetStarted/get-started.js';
import { Home } from './pages/Home/index.jsx';
import Resources from './pages/Resources/Resources';
import SupportUs from './pages/SupportUs/SupportUs.js';
export const LocaleContext = createContext('en');
export function App(props: {repoStargazersCount: number}) {
return (
<LocationProvider>
export function App({ repoStargazersCount }) {
return (
<LocationProvider>
<LocaleProvider>
<Header repoStargazersCount={props.repoStargazersCount} />
<Header repoStargazersCount={repoStargazersCount} />
<main>
<Router>
<Route path="/" component={Home} />
<Route path="/get-started" component={GetStarted} />
<Route path="/support-us" component={SupportUs} />
<Route path="/resources" component={Resources} />
<Route path="/:locale:/" component={Home} />
<Route path="/:locale:/get-started" component={GetStarted} />
<Route path="/:locale:/support-us" component={SupportUs} />
<Route path="/:locale:/resources" component={Resources} />
<Route default component={NotFound} />
</Router>
</main>
<Footer />
</LocaleProvider>
</LocationProvider>
);
</LocationProvider>
);
}
export function LocaleProvider({ children }) {
const { path } = useLocation();
const localeId = getLocaleId(path);
const loadedRef = useRef(false);
const { path } = useLocation();
const localeId = getLocaleId(path);
const loadedRef = useRef(false);
if (!loadedRef.current) {
initTranslations(localeId);
loadedRef.current = true;
} else {
changeLanguage(localeId);
}
if (!loadedRef.current) {
initTranslations(localeId);
loadedRef.current = true;
} else {
changeLanguage(localeId);
}
// Update html lang and dir attributes
useLayoutEffect(() => {
const correspondingLocale = LOCALES.find(l => l.id === localeId);
document.documentElement.lang = localeId;
document.documentElement.dir = correspondingLocale?.rtl ? "rtl" : "ltr";
}, [localeId]);
// Update html lang and dir attributes
useLayoutEffect(() => {
const correspondingLocale = LOCALES.find(l => l.id === localeId);
document.documentElement.lang = localeId;
document.documentElement.dir = correspondingLocale?.rtl ? "rtl" : "ltr";
}, [localeId]);
return (
<LocaleContext.Provider value={localeId}>
{children}
</LocaleContext.Provider>
);
return (
<LocaleContext.Provider value={localeId}>
{children}
</LocaleContext.Provider>
);
}
if (typeof window !== 'undefined') {
hydrate(<App repoStargazersCount={FALLBACK_STARGAZERS_COUNT} />, document.getElementById('app')!);
const el = document.getElementById("prerender-data");
const data = JSON.parse(el?.innerText ?? "{}");
hydrate(<App {...data} />, document.getElementById('app')!);
}
function getLocaleId(path: string) {
@@ -76,18 +83,18 @@ function getLocaleId(path: string) {
}
export async function prerender(data) {
// Fetch the stargazer count of the Trilium's GitHub repo on prerender to pass
// it to the App component for SSR.
// This ensures the GitHub API is not called on every page load in the client.
const stargazersCount = await getRepoStargazersCount();
const { html, links } = await ssr(<App repoStargazersCount={stargazersCount} {...data} />);
// Fetch the stargazer count of the Trilium's GitHub repo on prerender to pass
// it to the App component for SSR.
// This ensures the GitHub API is not called on every page load in the client.
data.repoStargazersCount = await getRepoStargazersCount();
const { html, links } = await ssr(<App {...data} />);
return {
html,
links,
data,
head: {
lang: extractLocaleFromUrl(data.url) ?? "en"
}
}
};
}

View File

@@ -37,13 +37,13 @@ section.hero-section {
pointer-events: none;
}
}
&>.content-wrapper {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
min-width: 80vw;
min-width: 80vw;
}
.title-section {
@@ -73,7 +73,7 @@ section.hero-section {
margin-bottom: 0;
}
.download-wrapper {
.download-wrapper {
display: flex;
flex-direction: column;
align-content: center;
@@ -104,17 +104,17 @@ section.hero-section {
}
}
@media (max-width: 719px) {
@media (max-width: 719.99px) {
section.hero-section {
padding-bottom: 0;
padding-bottom: 0;
.content-wrapper {
width: 100%;
}
.title-section {
max-width: 90%;
}
}
.screenshot {
margin-top: 2em;
@@ -193,18 +193,18 @@ section.faq {
padding: 0;
gap: 1em;
display: grid;
@media (min-width: 720px) {
grid-template-columns: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
}
li {
margin: 0;
margin: 0;
.card {
border: 1px solid transparent;
height: 100%;
}
}
}
}
@@ -214,7 +214,7 @@ section.faq {
display: flex;
flex-direction: column;
@media (max-width: 719px) {
@media (max-width: 719.99px) {
margin-top: 1em;
}
}

View File

@@ -0,0 +1,24 @@
.icon-packs .card-content {
.card-content-inner {
display: flex;
flex-direction: column;
flex-grow: 1;
}
.description {
font-size: 0.8em;
margin: 0;
flex-grow: 1;
height: 100%;
}
footer {
padding: 0;
border: 0;
display: flex;
align-items: center;
margin-top: 1em;
justify-content: space-between;
flex-grow: 1;
}
}

View File

@@ -0,0 +1,55 @@
import "./Resources.css";
import { Trans, useTranslation } from "react-i18next";
import Button, { Link } from "../../components/Button";
import Card from "../../components/Card";
import Section from "../../components/Section";
import { usePageTitle } from "../../hooks";
interface IconPackMeta {
name: string;
file: string;
version: string;
website: string;
description: string;
}
const iconPacksMeta = Object.values(import.meta.glob("../../../src/resources/icon-packs/*.json", {
eager: true
})) as IconPackMeta[];
export default function Resources() {
const { t } = useTranslation();
usePageTitle(t("resources.title"));
return (
<Section className="icon-packs fill">
<h2>{t("resources.icon_packs")}</h2>
<p>
<Trans
i18nKey="resources.icon_packs_intro"
components={{
DocumentationLink: <Link href="https://docs.triliumnotes.org/user-guide/concepts/themes/icon-packs" />
}}
/>
</p>
<div className="grid-3-cols">
{iconPacksMeta.map(meta => (
<Card
key={meta.name}
title={<>{meta.name} <small>{meta.version}</small></>}
>
<p className="description">{meta.description}</p>
<footer>
<Button href={`/resources/icon-packs/${meta.file}`} download text="Download" />
<Link href={meta.website} openExternally>Website</Link>
</footer>
</Card>
))}
</div>
</Section>
);
}

View File

@@ -0,0 +1,7 @@
{
"name": "Boxicons 3 (Basic)",
"file": "Boxicons 3 (Basic).zip",
"version": "3.0.0",
"website": "https://boxicons.com/",
"description": "The Basic set of icons from Boxicons v3. This is an upgrade from Trilium's built-in icon pack (Boxicons v2)."
}

View File

@@ -0,0 +1,7 @@
{
"name": "Boxicons 3 (Brands)",
"file": "Boxicons 3 (Brands).zip",
"version": "3.0.0",
"website": "https://boxicons.com/",
"description": "The brand set of icons from Boxicons v3."
}

View File

@@ -0,0 +1,7 @@
{
"name": "Material Design Icons",
"file": "Material Design Icons.zip",
"version": "7.4.47",
"website": "https://pictogrammers.com/library/mdi/",
"description": "The community Material Design Icons pack (@mdi/font). Not to be confused with Google's own Material Design Icons."
}

View File

@@ -0,0 +1,7 @@
{
"name": "Phosphor Icons (Fill)",
"file": "Phosphor Icons (Fill).zip",
"version": "2.1.2",
"website": "https://phosphoricons.com/",
"description": "The filled version of Phosphor Icons."
}

View File

@@ -0,0 +1,7 @@
{
"name": "Phosphor Icons (Regular)",
"file": "Phosphor Icons (Regular).zip",
"version": "2.1.2",
"website": "https://phosphoricons.com/",
"description": "The regular weight version of Phosphor Icons."
}

View File

@@ -42,7 +42,7 @@ body {
}
main {
min-height: calc(100vh - 80px - 90px);
min-height: calc(100vh - 80px - 136px);
display: flex;
flex-direction: column;
}
@@ -65,6 +65,7 @@ a {
max-width: 1200px;
width: 90%;
margin: auto;
box-sizing: border-box;
}
section {
@@ -123,14 +124,14 @@ img {
display: flex;
flex-direction: column;
flex-grow: 1;
.more-info-container {
margin-top: 0.5em;
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: flex-end;
.more-info {
font-size: 0.9em;
}
@@ -149,7 +150,7 @@ img {
}
}
@media (max-width: 719px) {
@media (max-width: 719.99px) {
.grid-4-cols > *,
.grid-3-cols > *,
.grid-2-cols > * {
@@ -168,7 +169,7 @@ img {
h2 {
margin-bottom: 2em;
}
}
}
.grid-4-cols {
display: grid;
@@ -191,4 +192,4 @@ img {
.mobile-only {
display: none !important;
}
}
}

View File

@@ -112,6 +112,7 @@
"header": {
"get-started": "Get started",
"documentation": "Documentation",
"resources": "Resources",
"support-us": "Support us"
},
"footer": {
@@ -196,5 +197,10 @@
"description": "Trilium Notes hosted on PikaPods, a paid service for easy access and management. Not directly affiliated with the Trilium team.",
"download_pikapod": "Set up on PikaPods",
"download_triliumcc": "Alternatively see trilium.cc"
},
"resources": {
"title": "Resources",
"icon_packs": "Icon packs",
"icon_packs_intro": "Expand the selection of available icons for your notes by using an icon pack. For more information about icon packs, see the <DocumentationLink>official documentation</DocumentationLink>."
}
}

View File

@@ -1,5 +1,5 @@
# Documentation
There are multiple types of documentation for Trilium:<img class="image-style-align-right" src="api/images/qIpo9UiTZNdm/Documentation_image.png" width="205" height="162">
There are multiple types of documentation for Trilium:<img class="image-style-align-right" src="api/images/vAGCdo7kgoVD/Documentation_image.png" width="205" height="162">
* The _User Guide_ represents the user-facing documentation. This documentation can be browsed by users directly from within Trilium, by pressing <kbd>F1</kbd>.
* The _Developer's Guide_ represents a set of Markdown documents that present the internals of Trilium, for developers.

View File

@@ -1480,17 +1480,87 @@
{
"type": "relation",
"name": "internalLink",
"value": "WOcw2SLH6tbX",
"value": "oPVyFC7WL2Lp",
"isInheritable": false,
"position": 10
},
{
"type": "relation",
"name": "internalLink",
"value": "nRqcgfTb97uV",
"value": "YtSN43OrfzaA",
"isInheritable": false,
"position": 20
},
{
"type": "relation",
"name": "internalLink",
"value": "Ms1nauBra7gq",
"isInheritable": false,
"position": 30
},
{
"type": "relation",
"name": "internalLink",
"value": "eIg8jdvaoNNd",
"isInheritable": false,
"position": 40
},
{
"type": "relation",
"name": "internalLink",
"value": "x3i7MxGccDuM",
"isInheritable": false,
"position": 50
},
{
"type": "relation",
"name": "internalLink",
"value": "xYmIYSP6wE3F",
"isInheritable": false,
"position": 60
},
{
"type": "relation",
"name": "internalLink",
"value": "3seOhtN8uLIY",
"isInheritable": false,
"position": 70
},
{
"type": "relation",
"name": "internalLink",
"value": "luNhaphA37EO",
"isInheritable": false,
"position": 80
},
{
"type": "relation",
"name": "internalLink",
"value": "IjZS7iK5EXtb",
"isInheritable": false,
"position": 90
},
{
"type": "relation",
"name": "internalLink",
"value": "WOcw2SLH6tbX",
"isInheritable": false,
"position": 100
},
{
"type": "relation",
"name": "internalLink",
"value": "nRqcgfTb97uV",
"isInheritable": false,
"position": 110
},
{
"type": "relation",
"name": "internalLink",
"value": "CdNpE2pqjmI6",
"isInheritable": false,
"position": 120
},
{
"type": "label",
"name": "shareAlias",
@@ -1504,76 +1574,6 @@
"value": "bx bx-mobile-alt",
"isInheritable": false,
"position": 60
},
{
"type": "relation",
"name": "internalLink",
"value": "x3i7MxGccDuM",
"isInheritable": false,
"position": 70
},
{
"type": "relation",
"name": "internalLink",
"value": "IjZS7iK5EXtb",
"isInheritable": false,
"position": 80
},
{
"type": "relation",
"name": "internalLink",
"value": "oPVyFC7WL2Lp",
"isInheritable": false,
"position": 90
},
{
"type": "relation",
"name": "internalLink",
"value": "YtSN43OrfzaA",
"isInheritable": false,
"position": 110
},
{
"type": "relation",
"name": "internalLink",
"value": "xYmIYSP6wE3F",
"isInheritable": false,
"position": 120
},
{
"type": "relation",
"name": "internalLink",
"value": "Ms1nauBra7gq",
"isInheritable": false,
"position": 130
},
{
"type": "relation",
"name": "internalLink",
"value": "eIg8jdvaoNNd",
"isInheritable": false,
"position": 140
},
{
"type": "relation",
"name": "internalLink",
"value": "3seOhtN8uLIY",
"isInheritable": false,
"position": 150
},
{
"type": "relation",
"name": "internalLink",
"value": "CdNpE2pqjmI6",
"isInheritable": false,
"position": 160
},
{
"type": "relation",
"name": "internalLink",
"value": "luNhaphA37EO",
"isInheritable": false,
"position": 170
}
],
"format": "markdown",
@@ -2845,6 +2845,20 @@
"isInheritable": false,
"position": 30
},
{
"type": "relation",
"name": "internalLink",
"value": "RDslemsQ6gCp",
"isInheritable": false,
"position": 40
},
{
"type": "relation",
"name": "internalLink",
"value": "xYmIYSP6wE3F",
"isInheritable": false,
"position": 50
},
{
"type": "label",
"name": "iconClass",
@@ -2858,20 +2872,6 @@
"value": "tabs",
"isInheritable": false,
"position": 40
},
{
"type": "relation",
"name": "internalLink",
"value": "RDslemsQ6gCp",
"isInheritable": false,
"position": 50
},
{
"type": "relation",
"name": "internalLink",
"value": "xYmIYSP6wE3F",
"isInheritable": false,
"position": 60
}
],
"format": "markdown",
@@ -2927,6 +2927,20 @@
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "relation",
"name": "internalLink",
"value": "x0JgW8UqGXvq",
"isInheritable": false,
"position": 10
},
{
"type": "relation",
"name": "internalLink",
"value": "x3i7MxGccDuM",
"isInheritable": false,
"position": 20
},
{
"type": "relation",
"name": "internalLink",
@@ -2934,6 +2948,41 @@
"isInheritable": false,
"position": 30
},
{
"type": "relation",
"name": "internalLink",
"value": "p9kXRFAkwN4o",
"isInheritable": false,
"position": 40
},
{
"type": "relation",
"name": "internalLink",
"value": "OR8WJ7Iz9K4U",
"isInheritable": false,
"position": 50
},
{
"type": "relation",
"name": "internalLink",
"value": "CdNpE2pqjmI6",
"isInheritable": false,
"position": 60
},
{
"type": "relation",
"name": "internalLink",
"value": "SynTBQiBsdYJ",
"isInheritable": false,
"position": 70
},
{
"type": "relation",
"name": "internalLink",
"value": "OFXdgB2nNk1F",
"isInheritable": false,
"position": 80
},
{
"type": "label",
"name": "iconClass",
@@ -2947,55 +2996,6 @@
"value": "launch-bar",
"isInheritable": false,
"position": 90
},
{
"type": "relation",
"name": "internalLink",
"value": "OFXdgB2nNk1F",
"isInheritable": false,
"position": 100
},
{
"type": "relation",
"name": "internalLink",
"value": "SynTBQiBsdYJ",
"isInheritable": false,
"position": 110
},
{
"type": "relation",
"name": "internalLink",
"value": "CdNpE2pqjmI6",
"isInheritable": false,
"position": 120
},
{
"type": "relation",
"name": "internalLink",
"value": "OR8WJ7Iz9K4U",
"isInheritable": false,
"position": 130
},
{
"type": "relation",
"name": "internalLink",
"value": "p9kXRFAkwN4o",
"isInheritable": false,
"position": 140
},
{
"type": "relation",
"name": "internalLink",
"value": "x3i7MxGccDuM",
"isInheritable": false,
"position": 150
},
{
"type": "relation",
"name": "internalLink",
"value": "x0JgW8UqGXvq",
"isInheritable": false,
"position": 160
}
],
"format": "markdown",
@@ -5330,6 +5330,20 @@
"type": "text",
"mime": "text/markdown",
"attributes": [
{
"type": "relation",
"name": "internalLink",
"value": "xYmIYSP6wE3F",
"isInheritable": false,
"position": 10
},
{
"type": "relation",
"name": "internalLink",
"value": "x3i7MxGccDuM",
"isInheritable": false,
"position": 20
},
{
"type": "label",
"name": "shareAlias",
@@ -5343,20 +5357,6 @@
"value": "bx bx-bookmarks",
"isInheritable": false,
"position": 30
},
{
"type": "relation",
"name": "internalLink",
"value": "xYmIYSP6wE3F",
"isInheritable": false,
"position": 40
},
{
"type": "relation",
"name": "internalLink",
"value": "x3i7MxGccDuM",
"isInheritable": false,
"position": 50
}
],
"format": "markdown",
@@ -6049,7 +6049,16 @@
],
"format": "markdown",
"dataFileName": "Icon Packs.md",
"attachments": []
"attachments": [
{
"attachmentId": "CPieIjN3b77m",
"title": "image.png",
"role": "image",
"mime": "image/png",
"position": 10,
"dataFileName": "Icon Packs_image.png"
}
]
}
]
},

View File

@@ -1,12 +1,20 @@
# Icon Packs
## Importing an existing icon pack
<figure class="image image-style-align-right image_resized" style="width:45.14%;"><img style="aspect-ratio:854/649;" src="Icon Packs_image.png" width="854" height="649"></figure>
By default, Trilium comes with a set of icons called Boxicons v2. Since v0.102.0, custom icon packs allow a wider selection of icons for notes.
Icon packs are specific to Trilium, so they must either be created from scratch (see below) or imported from a ZIP file from a third-party developer.
## Sample icon packs
The Trilium team maintains a few icon packs that are not shipped with Trilium. These icon packs can be found on the official website on the [Resources page](https://triliumnotes.org/resources).
## Importing an existing icon pack
> [!NOTE]
> **Icon packs are third-party content**
>
> The Trilium maintainers are not responsible for keeping these icon packs up to date. If you have an issue with a specific icon pack, then the issue must be reported to the third-party developer responsible for it, not the Trilium team.
> Apart from the [sample icon packs](https://triliumnotes.org/resources), the Trilium maintainers are not responsible for keeping icon packs up to date. If you have an issue with a specific icon pack, then the issue must be reported to the third-party developer responsible for it, not the Trilium team.
To import an icon pack:

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

View File

@@ -57,11 +57,13 @@ Right click either the _Available launchers_ or _Visible launchers_ sections and
1. **Note Launcher**
A note launcher will simply navigate to a specified note.
1. Set the `target` promoted attribute to the note to navigate to.
2. Optionally, set `hoistedNote` to hoist a particular note. See <a class="reference-link" href="../Navigation/Note%20Hoisting.md">Note Hoisting</a> for more information.
3. Optionally, set a `keyboardShortcut` to trigger the launcher.
2. **Script Launcher**
An advanced launcher which will run a script upon pressing. See <a class="reference-link" href="../../Scripting.md">Scripting</a> for more information.
1. Set `script` to point to the desired script to run.
2. Optionally, set a `keyboardShortcut` to trigger the launcher.
3. **Custom Widget**