Compare commits

...
4 changed files with 27 additions and 19 deletions

No files matched your search

+6 -4
View File
@@ -15,10 +15,12 @@ import { bookmarksWidget } from ".";
The Bookmarks widget keeps direct URLs and Homarr Apps in one ordered list. URLs do not require an App record; Homarr
uses the site's favicon when available. Choose adaptive, compact-grid, or other layouts from the widget configuration.
Adaptive, vertical, and grid layouts keep larger cards when the configured bookmarks fit, then reduce card height and
spacing to show as many bookmarks as possible before scrolling. Horizontal uses a compact, centered scrolling row with
narrower cards in one-row widgets. Horizontal, compact-grid, and icon-only layouts keep their gaps tight. Compact grid
also preserves its configured columns when the dashboard is scaled.
Vertical uses consistent compact rows and keeps bookmark names visible whenever the widget is wide enough, regardless
of how many bookmarks are configured. Adaptive and grid layouts reduce card height and spacing to show as many
bookmarks as possible before scrolling. Horizontal uses a compact, centered scrolling row with narrower cards in
one-row widgets. Horizontal, vertical, compact-grid, and icon-only layouts keep their gaps tight. Compact grid also
preserves its configured columns when the dashboard is scaled. Bookmark cards, icons, text, and gaps keep the same
visual density when a low-column dashboard is enlarged to fill the screen.
### Screenshots
+1 -1
View File
@@ -17,7 +17,7 @@ export const bookmarksWidget: WidgetDefinition = {
{
name: "Layout",
description:
"How bookmarks use the available widget space. Layouts stay compact and reduce card size when needed.",
"How bookmarks use the available widget space. Vertical keeps compact rows and stable title visibility.",
values: { type: "select", options: ["Adaptive", "Vertical", "Horizontal", "Grid", "Compact grid", "Icons"] },
defaultValue: "Adaptive",
},
@@ -1,5 +1,6 @@
"use client";
import type { CSSProperties } from "react";
import { useMemo, useState } from "react";
import {
Avatar,
@@ -144,9 +145,21 @@ export default function BookmarksWidget({
if (appIds.length > 0 && isInitialWidgetQueryPending(appsQuery)) return <WidgetQueryLoadingState />;
const isTight = responsiveHeight < 120;
let compactStyle: CSSProperties | undefined;
if (!advanced && Number.isFinite(displayScale) && displayScale > 1) {
// Low-column boards zoom the canvas above 100%. Keep bookmark controls at their intended physical size.
// The spacing and font tokens are rebound here because their inherited values resolve at the canvas level.
compactStyle = {
"--board-canvas-ui-scale": 1 / displayScale,
"--mantine-scale": 1 / displayScale,
"--mantine-font-size-xxs": "calc(0.6875rem * var(--board-canvas-ui-scale))",
"--mantine-spacing-sm": "calc(0.75rem * var(--board-canvas-ui-scale))",
"--mantine-spacing-xs": "calc(0.625rem * var(--board-canvas-ui-scale))",
} as CSSProperties;
}
return (
<Stack h="100%" mih={0} gap={isTight ? 6 : "sm"} p={isTight ? 6 : "sm"}>
<Stack h="100%" mih={0} gap={isTight ? 6 : "sm"} p={isTight ? 6 : "sm"} style={compactStyle}>
{options.title.length > 0 ? (
<Text fz={11} fw={600} px={2} lh={1.2} lineClamp={1}>
{options.title}
+6 -13
View File
@@ -40,7 +40,8 @@ export const getBookmarkCardDisplay = ({
orientation = "horizontal";
showTitle = true;
}
const showHostname = advanced || (!hideHostname && plan.showHostname);
let showHostname = advanced || (!hideHostname && plan.showHostname);
if (!advanced && plan.itemHeight <= 32 && showTitle) showHostname = false;
const showIcon = advanced || !hideIcon || (!showTitle && !showHostname);
return { orientation, showHostname, showIcon, showTitle };
@@ -246,23 +247,15 @@ export const getBookmarkDisplayPlan = ({
}
if (layout === "column") {
const densitySettings = getBookmarkDensitySettings({
columns: 1,
gap,
height: normalizedHeight,
heightProperty: "columnItemHeight",
itemCount: count,
preferredSettings: heightSettings,
});
return {
columns: 1,
horizontalScroll: false,
itemGap: getBookmarkDensityGap(gap, densitySettings),
itemHeight: densitySettings.columnItemHeight,
itemGap: Math.min(gap, 4),
itemHeight: 32,
itemWidth: width,
orientation: "horizontal",
showHostname: widthSettings.showHostname && densitySettings.showHostname,
showTitle: widthSettings.showTitle && densitySettings.showTitle,
showHostname: widthSettings.showHostname,
showTitle: widthSettings.showTitle,
};
}