feat(layout): focus exactly on basic properties

This commit is contained in:
Elian Doran 2025-12-16 18:29:46 +02:00
parent c0eb34927f
commit 713900b2b3
No known key found for this signature in database
2 changed files with 25 additions and 8 deletions

View File

@ -2,13 +2,13 @@ import "./FormList.css";
import { Dropdown as BootstrapDropdown, Tooltip } from "bootstrap";
import clsx from "clsx";
import { ComponentChildren } from "preact";
import { ComponentChildren, RefObject } from "preact";
import { type CSSProperties,useEffect, useMemo, useRef, useState } from "preact/compat";
import { CommandNames } from "../../components/app_context";
import { handleRightToLeftPlacement, isMobile, openInAppHelpFromUrl } from "../../services/utils";
import FormToggle from "./FormToggle";
import { useStaticTooltip } from "./hooks";
import { useStaticTooltip, useSyncedRef } from "./hooks";
import Icon from "./Icon";
interface FormListOpts {
@ -97,6 +97,7 @@ interface FormListItemOpts {
className?: string;
rtl?: boolean;
postContent?: ComponentChildren;
itemRef?: RefObject<HTMLLIElement>;
}
const TOOLTIP_CONFIG: Partial<Tooltip.Options> = {
@ -104,8 +105,8 @@ const TOOLTIP_CONFIG: Partial<Tooltip.Options> = {
fallbackPlacements: [ handleRightToLeftPlacement("right") ]
};
export function FormListItem({ className, icon, value, title, active, disabled, checked, container, onClick, selected, rtl, triggerCommand, description, ...contentProps }: FormListItemOpts) {
const itemRef = useRef<HTMLLIElement>(null);
export function FormListItem({ className, icon, value, title, active, disabled, checked, container, onClick, selected, rtl, triggerCommand, description, itemRef: externalItemRef, ...contentProps }: FormListItemOpts) {
const itemRef = useSyncedRef<HTMLLIElement>(externalItemRef, null);
if (checked) {
icon = "bx bx-check";

View File

@ -1,6 +1,7 @@
import { ConvertToAttachmentResponse } from "@triliumnext/commons";
import { Dropdown as BootstrapDropdown } from "bootstrap";
import { useContext, useRef } from "preact/hooks";
import { RefObject } from "preact";
import { useContext, useEffect, useRef } from "preact/hooks";
import appContext, { CommandNames } from "../../components/app_context";
import Component from "../../components/component";
@ -60,6 +61,8 @@ function RevisionsButton({ note }: { note: FNote }) {
);
}
type ItemToFocus = "basic-properties";
function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: NoteContext }) {
const dropdownRef = useRef<BootstrapDropdown>(null);
const parentComponent = useContext(ParentComponent);
@ -79,10 +82,12 @@ function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: Not
const [syncServerHost] = useTriliumOption("syncServerHost");
const { isReadOnly, enableEditing } = useIsNoteReadOnly(note, noteContext);
const isNormalViewMode = noteContext?.viewScope?.viewMode === "default";
const itemToFocusRef = useRef<ItemToFocus>(null);
// Keyboard shortcuts.
useTriliumEvent("toggleRibbonTabBasicProperties", () => {
if (!isNewLayout) return;
itemToFocusRef.current = "basic-properties";
dropdownRef.current?.toggle();
});
@ -93,7 +98,9 @@ function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: Not
className="note-actions"
hideToggleArrow
noSelectButtonStyle
iconAction>
iconAction
onHidden={() => itemToFocusRef.current = null }
>
{isReadOnly && <>
<CommandItem icon="bx bx-pencil" text={t("read-only-info.edit-note")}
@ -108,7 +115,7 @@ function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: Not
<FormDropdownDivider />
{isNewLayout && isNormalViewMode && !isHelpPage && <>
<NoteBasicProperties note={note} />
<NoteBasicProperties note={note} focus={itemToFocusRef} />
<FormDropdownDivider />
</>}
@ -157,14 +164,22 @@ function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: Not
);
}
function NoteBasicProperties({ note }: {
function NoteBasicProperties({ note, focus }: {
note: FNote;
focus: RefObject<ItemToFocus>;
}) {
const itemToFocusRef = useRef<HTMLLIElement>(null);
const [ isBookmarked, setIsBookmarked ] = useNoteBookmarkState(note);
const [ isShared, switchShareState ] = useShareState(note);
const [ isTemplate, setIsTemplate ] = useNoteLabelBoolean(note, "template");
const isProtected = useNoteProperty(note, "isProtected");
useEffect(() => {
if (focus.current === "basic-properties") {
itemToFocusRef.current?.focus();
}
}, [ focus ]);
return <>
<FormListToggleableItem
icon="bx bx-share-alt"
@ -172,6 +187,7 @@ function NoteBasicProperties({ note }: {
currentValue={isShared} onChange={switchShareState}
helpPage="R9pX4DGra2Vt"
disabled={["root", "_share", "_hidden"].includes(note?.noteId ?? "") || note?.noteId.startsWith("_options")}
itemRef={itemToFocusRef}
/>
<FormListToggleableItem
icon="bx bx-lock-alt"