mirror of
https://github.com/zadam/trilium.git
synced 2025-10-26 07:46:30 +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 RefreshButton from "../widgets/floating_buttons/refresh_button.js";
|
||||
import { applyModals } from "./layout_commons.js";
|
||||
import Ribbon from "../widgets/ribbon/Ribbon.jsx";
|
||||
|
||||
export default class DesktopLayout {
|
||||
|
||||
@@ -159,29 +160,7 @@ export default class DesktopLayout {
|
||||
.child(new ClosePaneButton())
|
||||
.child(new CreatePaneButton())
|
||||
)
|
||||
.child(
|
||||
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(<Ribbon />)
|
||||
.child(new SharedInfoWidget())
|
||||
.child(new WatchedFileUpdateStatusWidget())
|
||||
.child(
|
||||
|
||||
@@ -7,116 +7,6 @@ import type { NoteType } from "../../entities/fnote.js";
|
||||
import type { EventData, EventNames } from "../../components/app_context.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);
|
||||
|
||||
export default class RibbonContainer extends NoteContextAwareWidget {
|
||||
@@ -160,8 +50,6 @@ export default class RibbonContainer extends NoteContextAwareWidget {
|
||||
}
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
|
||||
this.$tabContainer = this.$widget.find(".ribbon-tab-container");
|
||||
this.$buttonContainer = this.$widget.find(".ribbon-button-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-name", (ribbonWidget as any).name as string) // TODO: base class for ribbon widgets
|
||||
.append(
|
||||
$('<span class="ribbon-tab-title-icon">')
|
||||
.addClass(ret.icon)
|
||||
.attr("title", ret.title)
|
||||
$('<span class="">')
|
||||
.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('<div class="ribbon-tab-spacer">');
|
||||
this.$tabContainer.append('');
|
||||
|
||||
if (ret.activate && !this.lastActiveComponentId && !$ribbonTabToActivate && !noExplicitActivation) {
|
||||
$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() {
|
||||
return {
|
||||
show: !this.note?.isLaunchBarConfig(),
|
||||
title: t("basic_properties.basic_properties"),
|
||||
icon: "bx bx-slider"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user