mirror of
https://github.com/zadam/trilium.git
synced 2025-11-02 03:16:11 +01:00
feat(react/ribbon): port base structure
This commit is contained in:
@@ -73,6 +73,7 @@ import ToggleReadOnlyButton from "../widgets/floating_buttons/toggle_read_only_b
|
|||||||
import PngExportButton from "../widgets/floating_buttons/png_export_button.js";
|
import PngExportButton from "../widgets/floating_buttons/png_export_button.js";
|
||||||
import RefreshButton from "../widgets/floating_buttons/refresh_button.js";
|
import RefreshButton from "../widgets/floating_buttons/refresh_button.js";
|
||||||
import { applyModals } from "./layout_commons.js";
|
import { applyModals } from "./layout_commons.js";
|
||||||
|
import Ribbon from "../widgets/ribbon/Ribbon.jsx";
|
||||||
|
|
||||||
export default class DesktopLayout {
|
export default class DesktopLayout {
|
||||||
|
|
||||||
@@ -159,29 +160,7 @@ export default class DesktopLayout {
|
|||||||
.child(new ClosePaneButton())
|
.child(new ClosePaneButton())
|
||||||
.child(new CreatePaneButton())
|
.child(new CreatePaneButton())
|
||||||
)
|
)
|
||||||
.child(
|
.child(<Ribbon />)
|
||||||
new RibbonContainer()
|
|
||||||
// the order of the widgets matter. Some of these want to "activate" themselves
|
|
||||||
// when visible. When this happens to multiple of them, the first one "wins".
|
|
||||||
// promoted attributes should always win.
|
|
||||||
.ribbon(new ClassicEditorToolbar())
|
|
||||||
.ribbon(new ScriptExecutorWidget())
|
|
||||||
.ribbon(new SearchDefinitionWidget())
|
|
||||||
.ribbon(new EditedNotesWidget())
|
|
||||||
.ribbon(new BookPropertiesWidget())
|
|
||||||
.ribbon(new NotePropertiesWidget())
|
|
||||||
.ribbon(new FilePropertiesWidget())
|
|
||||||
.ribbon(new ImagePropertiesWidget())
|
|
||||||
.ribbon(new BasicPropertiesWidget())
|
|
||||||
.ribbon(new OwnedAttributeListWidget())
|
|
||||||
.ribbon(new InheritedAttributesWidget())
|
|
||||||
.ribbon(new NotePathsWidget())
|
|
||||||
.ribbon(new NoteMapRibbonWidget())
|
|
||||||
.ribbon(new SimilarNotesWidget())
|
|
||||||
.ribbon(new NoteInfoWidget())
|
|
||||||
.button(new RevisionsButton())
|
|
||||||
.button(new NoteActionsWidget())
|
|
||||||
)
|
|
||||||
.child(new SharedInfoWidget())
|
.child(new SharedInfoWidget())
|
||||||
.child(new WatchedFileUpdateStatusWidget())
|
.child(new WatchedFileUpdateStatusWidget())
|
||||||
.child(
|
.child(
|
||||||
|
|||||||
@@ -7,116 +7,6 @@ import type { NoteType } from "../../entities/fnote.js";
|
|||||||
import type { EventData, EventNames } from "../../components/app_context.js";
|
import type { EventData, EventNames } from "../../components/app_context.js";
|
||||||
import type NoteActionsWidget from "../buttons/note_actions.js";
|
import type NoteActionsWidget from "../buttons/note_actions.js";
|
||||||
|
|
||||||
const TPL = /*html*/`
|
|
||||||
<div class="ribbon-container">
|
|
||||||
<style>
|
|
||||||
.ribbon-container {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-top-row {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-tab-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
margin-left: 10px;
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-flow: row wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-tab-title {
|
|
||||||
color: var(--muted-text-color);
|
|
||||||
border-bottom: 1px solid var(--main-border-color);
|
|
||||||
min-width: 24px;
|
|
||||||
flex-basis: 24px;
|
|
||||||
max-width: max-content;
|
|
||||||
flex-grow: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-tab-title .bx {
|
|
||||||
font-size: 150%;
|
|
||||||
position: relative;
|
|
||||||
top: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-tab-title.active {
|
|
||||||
color: var(--main-text-color);
|
|
||||||
border-bottom: 3px solid var(--main-text-color);
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-tab-title:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-tab-title:hover {
|
|
||||||
color: var(--main-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-tab-title:first-of-type {
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-tab-spacer {
|
|
||||||
flex-basis: 0;
|
|
||||||
min-width: 0;
|
|
||||||
max-width: 35px;
|
|
||||||
flex-grow: 1;
|
|
||||||
border-bottom: 1px solid var(--main-border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-tab-spacer:last-of-type {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-basis: 0;
|
|
||||||
min-width: 0;
|
|
||||||
max-width: 10000px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-button-container {
|
|
||||||
display: flex;
|
|
||||||
border-bottom: 1px solid var(--main-border-color);
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-button-container > * {
|
|
||||||
position: relative;
|
|
||||||
top: -3px;
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-body {
|
|
||||||
display: none;
|
|
||||||
border-bottom: 1px solid var(--main-border-color);
|
|
||||||
margin-left: 10px;
|
|
||||||
margin-right: 5px; /* needs to have this value so that the bottom border is the same width as the top one */
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-body.active {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-tab-title-label {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ribbon-tab-title.active .ribbon-tab-title-label {
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="ribbon-top-row">
|
|
||||||
<div class="ribbon-tab-container"></div>
|
|
||||||
<div class="ribbon-button-container"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="ribbon-body-container"></div>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
type ButtonWidget = (CommandButtonWidget | NoteActionsWidget);
|
type ButtonWidget = (CommandButtonWidget | NoteActionsWidget);
|
||||||
|
|
||||||
export default class RibbonContainer extends NoteContextAwareWidget {
|
export default class RibbonContainer extends NoteContextAwareWidget {
|
||||||
@@ -160,8 +50,6 @@ export default class RibbonContainer extends NoteContextAwareWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
|
||||||
|
|
||||||
this.$tabContainer = this.$widget.find(".ribbon-tab-container");
|
this.$tabContainer = this.$widget.find(".ribbon-tab-container");
|
||||||
this.$buttonContainer = this.$widget.find(".ribbon-button-container");
|
this.$buttonContainer = this.$widget.find(".ribbon-button-container");
|
||||||
this.$bodyContainer = this.$widget.find(".ribbon-body-container");
|
this.$bodyContainer = this.$widget.find(".ribbon-body-container");
|
||||||
@@ -241,16 +129,11 @@ export default class RibbonContainer extends NoteContextAwareWidget {
|
|||||||
.attr("data-ribbon-component-id", ribbonWidget.componentId)
|
.attr("data-ribbon-component-id", ribbonWidget.componentId)
|
||||||
.attr("data-ribbon-component-name", (ribbonWidget as any).name as string) // TODO: base class for ribbon widgets
|
.attr("data-ribbon-component-name", (ribbonWidget as any).name as string) // TODO: base class for ribbon widgets
|
||||||
.append(
|
.append(
|
||||||
$('<span class="ribbon-tab-title-icon">')
|
$('<span class="">')
|
||||||
.addClass(ret.icon)
|
|
||||||
.attr("title", ret.title)
|
|
||||||
.attr("data-toggle-command", (ribbonWidget as any).toggleCommand)
|
.attr("data-toggle-command", (ribbonWidget as any).toggleCommand)
|
||||||
) // TODO: base class
|
)
|
||||||
.append(" ")
|
|
||||||
.append($('<span class="ribbon-tab-title-label">').text(ret.title));
|
|
||||||
|
|
||||||
this.$tabContainer.append($ribbonTitle);
|
this.$tabContainer.append('');
|
||||||
this.$tabContainer.append('<div class="ribbon-tab-spacer">');
|
|
||||||
|
|
||||||
if (ret.activate && !this.lastActiveComponentId && !$ribbonTabToActivate && !noExplicitActivation) {
|
if (ret.activate && !this.lastActiveComponentId && !$ribbonTabToActivate && !noExplicitActivation) {
|
||||||
$ribbonTabToActivate = $ribbonTitle;
|
$ribbonTabToActivate = $ribbonTitle;
|
||||||
|
|||||||
37
apps/client/src/widgets/ribbon/Ribbon.tsx
Normal file
37
apps/client/src/widgets/ribbon/Ribbon.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { t } from "../../services/i18n";
|
||||||
|
import "./style.css";
|
||||||
|
|
||||||
|
export default function Ribbon() {
|
||||||
|
return (
|
||||||
|
<div class="ribbon-container" style={{ contain: "none" }}>
|
||||||
|
<div className="ribbon-top-row">
|
||||||
|
<div className="ribbon-tab-container">
|
||||||
|
<RibbonTab
|
||||||
|
title={t("basic_properties.basic_properties")}
|
||||||
|
icon="bx bx-slider"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="ribbon-button-container"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="ribbon-body-container"></div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function RibbonTab({ icon, title }: { icon: string; title: string }) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="ribbon-tab-title">
|
||||||
|
<span
|
||||||
|
className={`ribbon-tab-title-icon ${icon}`}
|
||||||
|
title={title}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<span class="ribbon-tab-title-label">{title}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ribbon-tab-spacer" />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
94
apps/client/src/widgets/ribbon/style.css
Normal file
94
apps/client/src/widgets/ribbon/style.css
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
.ribbon-container {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-top-row {
|
||||||
|
display: flex;
|
||||||
|
min-height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-tab-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: 10px;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-tab-title {
|
||||||
|
color: var(--muted-text-color);
|
||||||
|
border-bottom: 1px solid var(--main-border-color);
|
||||||
|
min-width: 24px;
|
||||||
|
flex-basis: 24px;
|
||||||
|
max-width: max-content;
|
||||||
|
flex-grow: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-tab-title .bx {
|
||||||
|
font-size: 150%;
|
||||||
|
position: relative;
|
||||||
|
top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-tab-title.active {
|
||||||
|
color: var(--main-text-color);
|
||||||
|
border-bottom: 3px solid var(--main-text-color);
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-tab-title:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-tab-title:hover {
|
||||||
|
color: var(--main-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-tab-title:first-of-type {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-tab-spacer {
|
||||||
|
flex-basis: 0;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 35px;
|
||||||
|
flex-grow: 1;
|
||||||
|
border-bottom: 1px solid var(--main-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-tab-spacer:last-of-type {
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-basis: 0;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 10000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-button-container {
|
||||||
|
display: flex;
|
||||||
|
border-bottom: 1px solid var(--main-border-color);
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-button-container > * {
|
||||||
|
position: relative;
|
||||||
|
top: -3px;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-body {
|
||||||
|
display: none;
|
||||||
|
border-bottom: 1px solid var(--main-border-color);
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 5px; /* needs to have this value so that the bottom border is the same width as the top one */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-body.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-tab-title.active .ribbon-tab-title-label {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
@@ -99,8 +99,6 @@ export default class BasicPropertiesWidget extends NoteContextAwareWidget {
|
|||||||
getTitle() {
|
getTitle() {
|
||||||
return {
|
return {
|
||||||
show: !this.note?.isLaunchBarConfig(),
|
show: !this.note?.isLaunchBarConfig(),
|
||||||
title: t("basic_properties.basic_properties"),
|
|
||||||
icon: "bx bx-slider"
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user