feat(status_bar): basic integration of attribute editor

This commit is contained in:
Elian Doran
2025-12-12 21:29:40 +02:00
parent efff38b116
commit c6d97e3d4b
3 changed files with 112 additions and 72 deletions

View File

@@ -2,70 +2,74 @@
contain: none;
border-top: 1px solid var(--main-border-color);
background-color: var(--left-pane-background-color);
display: flex;
align-items: center;
padding-inline: 0.25em;
min-height: 32px;
> .breadcrumb-row {
flex-grow: 1;
}
> .actions-row {
padding: 0.1em;
.status-bar-main-row {
min-height: 32px;
display: flex;
gap: 0.1em;
font-size: 0.85em;
align-items: center;
padding-inline: 0.25em;
.btn {
padding: 0 0.5em !important;
background: transparent;
> .breadcrumb-row {
flex-grow: 1;
}
> .actions-row {
padding: 0.1em;
display: flex;
align-items: center;
border: 0;
gap: 0.1em;
font-size: 0.85em;
&:focus,
&:hover {
background: var(--input-background-color);
}
}
.btn {
padding: 0 0.5em !important;
background: transparent;
display: flex;
align-items: center;
border: 0;
.status-bar-dropdown-button {
&:after {
content: unset;
}
}
}
.dropdown {
.dropdown-toggle {
padding: 0.1em 0.25em;
}
}
.dropdown-note-info {
width: max-content;
ul {
list-style-type: none;
padding: 0.5em;
margin: 0;
display: table;
li {
display: table-row;
> strong {
display: table-cell;
padding: 0.2em 0;
&:focus,
&:hover {
background: var(--input-background-color);
}
}
> span {
display: table-cell;
user-select: text;
padding-left: 2em;
.status-bar-dropdown-button {
&:after {
content: unset;
}
}
}
.dropdown {
.dropdown-toggle {
padding: 0.1em 0.25em;
}
}
.dropdown-note-info {
width: max-content;
ul {
list-style-type: none;
padding: 0.5em;
margin: 0;
display: table;
li {
display: table-row;
> strong {
display: table-cell;
padding: 0.2em 0;
}
> span {
display: table-cell;
user-select: text;
padding-left: 2em;
}
}
}
}
}
}

View File

@@ -9,6 +9,7 @@ import { useContext, useRef, useState } from "preact/hooks";
import { CommandNames } from "../../components/app_context";
import NoteContext from "../../components/note_context";
import FNote from "../../entities/fnote";
import attributes from "../../services/attributes";
import { t } from "../../services/i18n";
import { ViewScope } from "../../services/link";
import { openInAppHelpFromUrl } from "../../services/utils";
@@ -20,11 +21,11 @@ import { useActiveNoteContext, useStaticTooltip, useTriliumEvent } from "../reac
import Icon from "../react/Icon";
import { ParentComponent } from "../react/react_utils";
import { ContentLanguagesModal, useLanguageSwitcher } from "../ribbon/BasicPropertiesTab";
import AttributeEditor, { AttributeEditorImperativeHandlers } from "../ribbon/components/AttributeEditor";
import { NoteSizeWidget, useNoteMetadata } from "../ribbon/NoteInfoTab";
import { useAttachments } from "../type_widgets/Attachment";
import { useProcessedLocales } from "../type_widgets/options/components/LocaleSelector";
import Breadcrumb from "./Breadcrumb";
import attributes from "../../services/attributes";
interface StatusBarContext {
note: FNote;
@@ -38,19 +39,23 @@ export default function StatusBar() {
return (
<div className="status-bar">
{context && <>
<div className="breadcrumb-row">
<Breadcrumb {...context} />
</div>
{context && <AttributesPane {...context} />}
<div className="actions-row">
<AttributesButton {...context} />
<AttachmentCount {...context} />
<BacklinksBadge {...context} />
<LanguageSwitcher {...context} />
<NoteInfoBadge {...context} />
</div>
</>}
<div className="status-bar-main-row">
{context && <>
<div className="breadcrumb-row">
<Breadcrumb {...context} />
</div>
<div className="actions-row">
<AttributesButton {...context} />
<AttachmentCount {...context} />
<BacklinksBadge {...context} />
<LanguageSwitcher {...context} />
<NoteInfoBadge {...context} />
</div>
</>}
</div>
</div>
);
}
@@ -81,14 +86,18 @@ function StatusBarDropdown({ children, icon, text, buttonClassName, titleOptions
);
}
function StatusBarButton({ className, icon, text, title, triggerCommand }: {
interface StatusBarButtonBaseProps {
className?: string;
icon: string;
title: string;
text?: string | number;
disabled?: boolean;
triggerCommand: CommandNames;
}) {
}
type StatusBarButtonWithCommand = StatusBarButtonBaseProps & { triggerCommand: CommandNames; };
type StatusBarButtonWithClick = StatusBarButtonBaseProps & { onClick: () => void; };
function StatusBarButton({ className, icon, text, title, ...restProps }: StatusBarButtonWithCommand | StatusBarButtonWithClick) {
const parentComponent = useContext(ParentComponent);
const buttonRef = useRef<HTMLButtonElement>(null);
useStaticTooltip(buttonRef, {
@@ -103,7 +112,13 @@ function StatusBarButton({ className, icon, text, title, triggerCommand }: {
ref={buttonRef}
className={clsx("btn select-button", className)}
type="button"
onClick={() => parentComponent?.triggerCommand(triggerCommand)}
onClick={() => {
if ("triggerCommand" in restProps) {
parentComponent?.triggerCommand(restProps.triggerCommand);
} else {
restProps.onClick();
}
}}
>
<Icon icon={icon} />&nbsp;{text}
</button>
@@ -246,7 +261,27 @@ function AttributesButton({ note }: StatusBarContext) {
icon="bx bx-list-check"
title={t("status_bar.attributes_title")}
text={t("status_bar.attributes", { count })}
onClick={() => {
alert("Hi");
}}
/>
);
}
function AttributesPane({ note, noteContext }: StatusBarContext) {
const parentComponent = useContext(ParentComponent);
const api = useRef<AttributeEditorImperativeHandlers>(null);
return (
<div className="attribute-list">
{parentComponent && <AttributeEditor
componentId={parentComponent.componentId}
api={api}
ntxId={noteContext.ntxId}
note={note}
hidden={!note}
/>}
</div>
);
}
//#endregion

View File

@@ -1,4 +1,5 @@
import { useMemo, useRef } from "preact/hooks";
import { useLegacyImperativeHandlers, useTriliumEvents } from "../react/hooks";
import AttributeEditor, { AttributeEditorImperativeHandlers } from "./components/AttributeEditor";
import { TabContext } from "./ribbon-interface";
@@ -25,5 +26,5 @@ export default function OwnedAttributesTab({ note, hidden, activate, ntxId, ...r
<AttributeEditor api={api} ntxId={ntxId} note={note} {...restProps} hidden={hidden} />
)}
</div>
)
);
}