From b03e6c3b198b3c710bec8a93c5d1de2af77080c2 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 10 Dec 2025 11:41:14 +0200 Subject: [PATCH] chore(breadcrumb_badges/backlinks): display list of backlinks on click --- apps/client/src/widgets/BreadcrumbBadges.css | 12 ++++ apps/client/src/widgets/BreadcrumbBadges.tsx | 66 ++++++++++++++----- .../widgets/FloatingButtonsDefinitions.tsx | 2 +- 3 files changed, 64 insertions(+), 16 deletions(-) diff --git a/apps/client/src/widgets/BreadcrumbBadges.css b/apps/client/src/widgets/BreadcrumbBadges.css index 0e0a564e8..5dbfd74fc 100644 --- a/apps/client/src/widgets/BreadcrumbBadges.css +++ b/apps/client/src/widgets/BreadcrumbBadges.css @@ -37,4 +37,16 @@ text-decoration: none; } } + + .dropdown { + &.dropdown-backlinks-badge .dropdown-menu { + min-width: 500px; + } + + .btn { + border: 0; + margin: 0; + padding: 0; + } + } } diff --git a/apps/client/src/widgets/BreadcrumbBadges.tsx b/apps/client/src/widgets/BreadcrumbBadges.tsx index 8945b447b..9c066f04e 100644 --- a/apps/client/src/widgets/BreadcrumbBadges.tsx +++ b/apps/client/src/widgets/BreadcrumbBadges.tsx @@ -5,6 +5,8 @@ import { ComponentChildren, MouseEventHandler } from "preact"; import { useRef } from "preact/hooks"; import { t } from "../services/i18n"; +import { BacklinksList } from "./FloatingButtonsDefinitions"; +import Dropdown, { DropdownProps } from "./react/Dropdown"; import { useIsNoteReadOnly, useNoteContext, useStaticTooltip } from "./react/hooks"; import Icon from "./react/Icon"; import { useShareInfo } from "./shared_info"; @@ -28,21 +30,19 @@ function ReadOnlyBadge() { if (isTemporarilyEditable) { return enableEditing(false)} - > - {t("breadcrumb_badges.read_only_temporarily_disabled")} - ; + />; } else if (isReadOnly) { return enableEditing()} - > - {isExplicitReadOnly ? t("breadcrumb_badges.read_only_explicit") : t("breadcrumb_badges.read_only_auto")} - ; + />; } } @@ -53,28 +53,45 @@ function ShareBadge() { return (link && - {isSharedExternally ? t("breadcrumb_badges.shared_publicly") : t("breadcrumb_badges.shared_locally")} - + /> ); } function BacklinksBadge() { + const { note } = useNoteContext(); const count = 1; - return ( - - {t("breadcrumb_badges.backlinks", { count })} - + return (note && count > 0 && + + + ); } -function Badge({ icon, className, children, tooltip, onClick, href }: { icon?: string, className: string, tooltip: string, children: ComponentChildren, onClick?: MouseEventHandler, href?: string }) { +interface BadgeProps { + text: string; + icon?: string; + className: string; + tooltip?: string; + onClick?: MouseEventHandler; + href?: string; +} + +function Badge({ icon, className, text, tooltip, onClick, href }: BadgeProps) { const containerRef = useRef(null); useStaticTooltip(containerRef, { placement: "bottom", @@ -86,7 +103,7 @@ function Badge({ icon, className, children, tooltip, onClick, href }: { icon?: s const content = <> {icon && <> } - {children} + {text} ; return ( @@ -99,3 +116,22 @@ function Badge({ icon, className, children, tooltip, onClick, href }: { icon?: s ); } + +function BadgeWithDropdown({ children, tooltip, className, dropdownOptions, ...props }: BadgeProps & { + children: ComponentChildren, + dropdownOptions?: Partial +}) { + return ( + } + noDropdownListStyle + noSelectButtonStyle + hideToggleArrow + title={tooltip} + titlePosition="bottom" + dropdownOptions={{ popperConfig: { placement: "bottom" } }} + {...dropdownOptions} + >{children} + ); +} diff --git a/apps/client/src/widgets/FloatingButtonsDefinitions.tsx b/apps/client/src/widgets/FloatingButtonsDefinitions.tsx index 65743984e..e1e60ccc3 100644 --- a/apps/client/src/widgets/FloatingButtonsDefinitions.tsx +++ b/apps/client/src/widgets/FloatingButtonsDefinitions.tsx @@ -355,7 +355,7 @@ function Backlinks({ note, isDefaultViewMode }: FloatingButtonContext) { ); } -function BacklinksList({ note }: { note: FNote }) { +export function BacklinksList({ note }: { note: FNote }) { const [ backlinks, setBacklinks ] = useState([]); function refresh() {