mirror of
https://github.com/thejusticeman/obsidian-mobile-plugin.git
synced 2026-07-22 06:40:12 +00:00
Refactor toolbar extension and styles for improved readability and consistency
- Updated formatting in `toolbar-extension.ts` for better code clarity. - Enhanced tooltip functionality to ensure it displays correctly based on context. - Adjusted CSS styles for the mobile FAB and selection toolbar for a more consistent design. - Ensured proper spacing and alignment in the CSS for better mobile responsiveness.
This commit is contained in:
parent
b358ac13d1
commit
aab03fc24e
4 changed files with 818 additions and 863 deletions
|
|
@ -5,6 +5,5 @@ root = true
|
|||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
tab_width = 4
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
|
|
|||
1040
src/settings.ts
1040
src/settings.ts
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +1,9 @@
|
|||
import {
|
||||
ViewPlugin,
|
||||
EditorView,
|
||||
ViewUpdate,
|
||||
Decoration,
|
||||
DecorationSet,
|
||||
ViewPlugin,
|
||||
EditorView,
|
||||
ViewUpdate,
|
||||
Decoration,
|
||||
DecorationSet,
|
||||
} from "@codemirror/view";
|
||||
import { syntaxTree } from "@codemirror/language";
|
||||
import { App, ButtonComponent } from "obsidian";
|
||||
|
|
@ -13,289 +13,267 @@ import { ToolbarConfig, ContextBinding, ContextType } from "./settings";
|
|||
* Creates a CodeMirror 6 ViewPlugin that displays a context-aware toolbar at the bottom
|
||||
* when text is selected or cursor is in a specific context.
|
||||
*/
|
||||
export function createToolbarExtension(
|
||||
app: App,
|
||||
settings: any
|
||||
) {
|
||||
return ViewPlugin.fromClass(
|
||||
class {
|
||||
decorations: DecorationSet;
|
||||
tooltip: HTMLElement | null = null;
|
||||
app: App;
|
||||
toolbars: ToolbarConfig[];
|
||||
contextBindings: ContextBinding[];
|
||||
useIcons: boolean;
|
||||
commandIcons: Record<string, string>;
|
||||
enableHapticFeedback: boolean;
|
||||
editorContainer: HTMLElement | null = null;
|
||||
export function createToolbarExtension(app: App, settings: any) {
|
||||
return ViewPlugin.fromClass(
|
||||
class {
|
||||
decorations: DecorationSet;
|
||||
tooltip: HTMLElement | null = null;
|
||||
app: App;
|
||||
toolbars: ToolbarConfig[];
|
||||
contextBindings: ContextBinding[];
|
||||
useIcons: boolean;
|
||||
commandIcons: Record<string, string>;
|
||||
enableHapticFeedback: boolean;
|
||||
editorContainer: HTMLElement | null = null;
|
||||
|
||||
constructor(view: EditorView) {
|
||||
this.decorations = Decoration.none;
|
||||
this.app = app;
|
||||
this.toolbars = settings.toolbars;
|
||||
this.contextBindings = settings.contextBindings;
|
||||
this.useIcons = settings.useIcons;
|
||||
this.commandIcons = settings.commandIcons;
|
||||
this.enableHapticFeedback = settings.enableHapticFeedback;
|
||||
constructor(view: EditorView) {
|
||||
this.decorations = Decoration.none;
|
||||
this.app = app;
|
||||
this.toolbars = settings.toolbars;
|
||||
this.contextBindings = settings.contextBindings;
|
||||
this.useIcons = settings.useIcons;
|
||||
this.commandIcons = settings.commandIcons;
|
||||
this.enableHapticFeedback = settings.enableHapticFeedback;
|
||||
|
||||
// Find the editor container to anchor the toolbar
|
||||
this.editorContainer = this.findEditorContainer(view.dom);
|
||||
// Find the editor container to anchor the toolbar
|
||||
this.editorContainer = this.findEditorContainer(view.dom);
|
||||
|
||||
this.updateTooltip(view);
|
||||
}
|
||||
this.updateTooltip(view);
|
||||
}
|
||||
|
||||
hapticFeedback(duration: number = 10) {
|
||||
if (this.enableHapticFeedback && navigator.vibrate) {
|
||||
navigator.vibrate(duration);
|
||||
}
|
||||
}
|
||||
hapticFeedback(duration: number = 10) {
|
||||
if (this.enableHapticFeedback && navigator.vibrate) {
|
||||
navigator.vibrate(duration);
|
||||
}
|
||||
}
|
||||
|
||||
findEditorContainer(element: HTMLElement): HTMLElement | null {
|
||||
// Find the workspace-leaf-content container
|
||||
let current = element.parentElement;
|
||||
while (current) {
|
||||
if (current.classList.contains("workspace-leaf-content")) {
|
||||
return current;
|
||||
}
|
||||
current = current.parentElement;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
findEditorContainer(element: HTMLElement): HTMLElement | null {
|
||||
// Find the workspace-leaf-content container
|
||||
let current = element.parentElement;
|
||||
while (current) {
|
||||
if (current.classList.contains("workspace-leaf-content")) {
|
||||
return current;
|
||||
}
|
||||
current = current.parentElement;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
update(update: ViewUpdate) {
|
||||
if (
|
||||
update.selectionSet ||
|
||||
update.viewportChanged ||
|
||||
update.docChanged
|
||||
) {
|
||||
// Defer tooltip update to avoid reading layout during update
|
||||
requestAnimationFrame(() => {
|
||||
this.updateTooltip(update.view);
|
||||
});
|
||||
}
|
||||
}
|
||||
update(update: ViewUpdate) {
|
||||
if (
|
||||
update.selectionSet ||
|
||||
update.viewportChanged ||
|
||||
update.docChanged
|
||||
) {
|
||||
// Defer tooltip update to avoid reading layout during update
|
||||
requestAnimationFrame(() => {
|
||||
this.updateTooltip(update.view);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
updateTooltip(view: EditorView) {
|
||||
const selection = view.state.selection.main;
|
||||
updateTooltip(view: EditorView) {
|
||||
const selection = view.state.selection.main;
|
||||
|
||||
// Remove existing tooltip if present
|
||||
if (this.tooltip) {
|
||||
this.tooltip.remove();
|
||||
this.tooltip = null;
|
||||
}
|
||||
// Remove existing tooltip if present
|
||||
if (this.tooltip) {
|
||||
this.tooltip.remove();
|
||||
this.tooltip = null;
|
||||
}
|
||||
|
||||
// Show toolbar if there's a selection or cursor is in specific context
|
||||
if (!selection.empty || this.hasContext(view, selection.from)) {
|
||||
this.showTooltip(view);
|
||||
}
|
||||
}
|
||||
// Show toolbar if there's a selection or cursor is in specific context
|
||||
if (!selection.empty || this.hasContext(view, selection.from)) {
|
||||
this.showTooltip(view);
|
||||
}
|
||||
}
|
||||
|
||||
hasContext(view: EditorView, pos: number): boolean {
|
||||
const activeContexts = this.getMatchingContexts(view, pos);
|
||||
// Check if any binding matches the current context
|
||||
for (const binding of this.contextBindings) {
|
||||
if (activeContexts.has(binding.contextType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
hasContext(view: EditorView, pos: number): boolean {
|
||||
const activeContexts = this.getMatchingContexts(view, pos);
|
||||
// Check if any binding matches the current context
|
||||
for (const binding of this.contextBindings) {
|
||||
if (activeContexts.has(binding.contextType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getActiveToolbar(
|
||||
view: EditorView,
|
||||
pos: number
|
||||
): ToolbarConfig | null {
|
||||
const activeContexts = this.getMatchingContexts(view, pos);
|
||||
// Collect all matching toolbars and concatenate their commands
|
||||
const matchingToolbars: ToolbarConfig[] = [];
|
||||
const seenCommands = new Set<string>();
|
||||
getActiveToolbar(view: EditorView, pos: number): ToolbarConfig | null {
|
||||
const activeContexts = this.getMatchingContexts(view, pos);
|
||||
// Collect all matching toolbars and concatenate their commands
|
||||
const matchingToolbars: ToolbarConfig[] = [];
|
||||
const seenCommands = new Set<string>();
|
||||
|
||||
for (const binding of this.contextBindings) {
|
||||
if (activeContexts.has(binding.contextType)) {
|
||||
const toolbar = this.toolbars.find(
|
||||
(t) => t.id === binding.toolbarId
|
||||
);
|
||||
if (toolbar) {
|
||||
matchingToolbars.push(toolbar);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const binding of this.contextBindings) {
|
||||
if (activeContexts.has(binding.contextType)) {
|
||||
const toolbar = this.toolbars.find(
|
||||
(t) => t.id === binding.toolbarId
|
||||
);
|
||||
if (toolbar) {
|
||||
matchingToolbars.push(toolbar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no matches, return null
|
||||
if (matchingToolbars.length === 0) {
|
||||
return null;
|
||||
}
|
||||
// If no matches, return null
|
||||
if (matchingToolbars.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Concatenate commands from all matching toolbars, removing duplicates
|
||||
const combinedCommands: string[] = [];
|
||||
for (const toolbar of matchingToolbars) {
|
||||
for (const command of toolbar.commands) {
|
||||
if (!seenCommands.has(command)) {
|
||||
seenCommands.add(command);
|
||||
combinedCommands.push(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Concatenate commands from all matching toolbars, removing duplicates
|
||||
const combinedCommands: string[] = [];
|
||||
for (const toolbar of matchingToolbars) {
|
||||
for (const command of toolbar.commands) {
|
||||
if (!seenCommands.has(command)) {
|
||||
seenCommands.add(command);
|
||||
combinedCommands.push(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return a virtual toolbar with combined commands
|
||||
return {
|
||||
id: "combined",
|
||||
name: "Combined Toolbar",
|
||||
commands: combinedCommands,
|
||||
};
|
||||
}
|
||||
// Return a virtual toolbar with combined commands
|
||||
return {
|
||||
id: "combined",
|
||||
name: "Combined Toolbar",
|
||||
commands: combinedCommands,
|
||||
};
|
||||
}
|
||||
|
||||
getMatchingContexts(
|
||||
view: EditorView,
|
||||
pos: number
|
||||
): Set<ContextType> {
|
||||
const contexts = new Set<ContextType>();
|
||||
contexts.add("default");
|
||||
getMatchingContexts(view: EditorView, pos: number): Set<ContextType> {
|
||||
const contexts = new Set<ContextType>();
|
||||
contexts.add("default");
|
||||
|
||||
if (!view.state.selection.main.empty) {
|
||||
contexts.add("selection");
|
||||
}
|
||||
if (!view.state.selection.main.empty) {
|
||||
contexts.add("selection");
|
||||
}
|
||||
|
||||
syntaxTree(view.state).iterate({
|
||||
from: pos,
|
||||
to: pos,
|
||||
enter: (node: any) => {
|
||||
const nodeName = node.type.name;
|
||||
syntaxTree(view.state).iterate({
|
||||
from: pos,
|
||||
to: pos,
|
||||
enter: (node: any) => {
|
||||
const nodeName = node.type.name;
|
||||
|
||||
if (
|
||||
nodeName === "BulletList" ||
|
||||
nodeName === "OrderedList" ||
|
||||
nodeName.startsWith(
|
||||
"HyperMD-list-line_HyperMD-list-line-"
|
||||
)
|
||||
) {
|
||||
contexts.add("list");
|
||||
}
|
||||
if (
|
||||
nodeName === "BulletList" ||
|
||||
nodeName === "OrderedList" ||
|
||||
nodeName.startsWith("HyperMD-list-line_HyperMD-list-line-")
|
||||
) {
|
||||
contexts.add("list");
|
||||
}
|
||||
|
||||
if (
|
||||
nodeName === "Task" ||
|
||||
nodeName.includes("HyperMD-task-line")
|
||||
) {
|
||||
contexts.add("task");
|
||||
}
|
||||
if (nodeName === "Task" || nodeName.includes("HyperMD-task-line")) {
|
||||
contexts.add("task");
|
||||
}
|
||||
|
||||
if (
|
||||
nodeName.startsWith("ATXHeading") ||
|
||||
nodeName === "SetextHeading" ||
|
||||
nodeName.startsWith("HyperMD-header")
|
||||
) {
|
||||
contexts.add("heading");
|
||||
}
|
||||
if (
|
||||
nodeName.startsWith("ATXHeading") ||
|
||||
nodeName === "SetextHeading" ||
|
||||
nodeName.startsWith("HyperMD-header")
|
||||
) {
|
||||
contexts.add("heading");
|
||||
}
|
||||
|
||||
if (
|
||||
nodeName === "FencedCode" ||
|
||||
nodeName === "CodeBlock" ||
|
||||
nodeName.includes("HyperMD-codeblock")
|
||||
) {
|
||||
contexts.add("code-block");
|
||||
}
|
||||
if (
|
||||
nodeName === "FencedCode" ||
|
||||
nodeName === "CodeBlock" ||
|
||||
nodeName.includes("HyperMD-codeblock")
|
||||
) {
|
||||
contexts.add("code-block");
|
||||
}
|
||||
|
||||
if (
|
||||
nodeName === "Table" ||
|
||||
nodeName.startsWith("Table") ||
|
||||
nodeName.includes("HyperMD-table")
|
||||
) {
|
||||
contexts.add("table");
|
||||
}
|
||||
if (
|
||||
nodeName === "Table" ||
|
||||
nodeName.startsWith("Table") ||
|
||||
nodeName.includes("HyperMD-table")
|
||||
) {
|
||||
contexts.add("table");
|
||||
}
|
||||
|
||||
if (
|
||||
nodeName === "Blockquote" ||
|
||||
nodeName === "QuoteMark" ||
|
||||
nodeName.includes("HyperMD-quote")
|
||||
) {
|
||||
contexts.add("blockquote");
|
||||
}
|
||||
if (
|
||||
nodeName === "Blockquote" ||
|
||||
nodeName === "QuoteMark" ||
|
||||
nodeName.includes("HyperMD-quote")
|
||||
) {
|
||||
contexts.add("blockquote");
|
||||
}
|
||||
|
||||
if (
|
||||
nodeName === "Link" ||
|
||||
nodeName.includes("link") ||
|
||||
nodeName.includes("URL") ||
|
||||
nodeName.includes("HyperMD-link")
|
||||
) {
|
||||
contexts.add("link");
|
||||
}
|
||||
},
|
||||
});
|
||||
if (
|
||||
nodeName === "Link" ||
|
||||
nodeName.includes("link") ||
|
||||
nodeName.includes("URL") ||
|
||||
nodeName.includes("HyperMD-link")
|
||||
) {
|
||||
contexts.add("link");
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return contexts;
|
||||
}
|
||||
return contexts;
|
||||
}
|
||||
|
||||
showTooltip(view: EditorView) {
|
||||
const selection = view.state.selection.main;
|
||||
showTooltip(view: EditorView) {
|
||||
const selection = view.state.selection.main;
|
||||
|
||||
// Get the active toolbar based on context
|
||||
const activeToolbar = this.getActiveToolbar(
|
||||
view,
|
||||
selection.from
|
||||
);
|
||||
// Get the active toolbar based on context
|
||||
const activeToolbar = this.getActiveToolbar(view, selection.from);
|
||||
|
||||
if (!activeToolbar || activeToolbar.commands.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (!activeToolbar || activeToolbar.commands.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create tooltip element
|
||||
this.tooltip = (this.editorContainer || view.dom).createDiv({
|
||||
cls: "mobile-selection-toolbar",
|
||||
attr: { "data-toolbar-id": activeToolbar.id },
|
||||
});
|
||||
// Create tooltip element
|
||||
this.tooltip = (this.editorContainer || view.dom).createDiv({
|
||||
cls: "mobile-selection-toolbar",
|
||||
attr: { "data-toolbar-id": activeToolbar.id },
|
||||
});
|
||||
|
||||
// Get all available commands
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const commands = (this.app as any).commands?.commands || {};
|
||||
// Get all available commands
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const commands = (this.app as any).commands?.commands || {};
|
||||
|
||||
// Add command buttons
|
||||
activeToolbar.commands.forEach((commandId) => {
|
||||
const command = commands[commandId];
|
||||
const iconToUse =
|
||||
this.commandIcons[commandId] || command.icon;
|
||||
if (command && this.tooltip) {
|
||||
if (this.useIcons && iconToUse) {
|
||||
new ButtonComponent(this.tooltip)
|
||||
/* .setClass("mobile-toolbar-button") */
|
||||
.setIcon(iconToUse)
|
||||
.setTooltip(command.name || commandId)
|
||||
.onClick((e) => {
|
||||
// Haptic feedback on button click
|
||||
this.hapticFeedback(10);
|
||||
// Execute the command
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(
|
||||
this.app as any
|
||||
).commands?.executeCommandById(commandId);
|
||||
});
|
||||
} else {
|
||||
new ButtonComponent(this.tooltip)
|
||||
/* .setClass("mobile-toolbar-button") */
|
||||
.setButtonText(command.name || commandId)
|
||||
.setTooltip(command.name || commandId)
|
||||
.onClick((e) => {
|
||||
// Haptic feedback on button click
|
||||
this.hapticFeedback(10);
|
||||
// Execute the command
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(
|
||||
this.app as any
|
||||
).commands?.executeCommandById(commandId);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// Add command buttons
|
||||
activeToolbar.commands.forEach((commandId) => {
|
||||
const command = commands[commandId];
|
||||
const iconToUse = this.commandIcons[commandId] || command.icon;
|
||||
if (command && this.tooltip) {
|
||||
if (this.useIcons && iconToUse) {
|
||||
new ButtonComponent(this.tooltip)
|
||||
/* .setClass("mobile-toolbar-button") */
|
||||
.setIcon(iconToUse)
|
||||
.setTooltip(command.name || commandId)
|
||||
.onClick((e) => {
|
||||
// Haptic feedback on button click
|
||||
this.hapticFeedback(10);
|
||||
// Execute the command
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(this.app as any).commands?.executeCommandById(commandId);
|
||||
});
|
||||
} else {
|
||||
new ButtonComponent(this.tooltip)
|
||||
/* .setClass("mobile-toolbar-button") */
|
||||
.setButtonText(command.name || commandId)
|
||||
.setTooltip(command.name || commandId)
|
||||
.onClick((e) => {
|
||||
// Haptic feedback on button click
|
||||
this.hapticFeedback(10);
|
||||
// Execute the command
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(this.app as any).commands?.executeCommandById(commandId);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.tooltip) {
|
||||
this.tooltip.remove();
|
||||
this.tooltip = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
// No decorations needed for this plugin
|
||||
}
|
||||
);
|
||||
destroy() {
|
||||
if (this.tooltip) {
|
||||
this.tooltip.remove();
|
||||
this.tooltip = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
// No decorations needed for this plugin
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
144
styles.css
144
styles.css
|
|
@ -5,134 +5,134 @@ Includes FAB and selection toolbar styles with mobile-friendly design
|
|||
|
||||
/* Ensure workspace-leaf-content is positioned for absolute children */
|
||||
.workspace-leaf-content {
|
||||
position: relative;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Floating Action Button (FAB) */
|
||||
.mobile-fab {
|
||||
position: absolute;
|
||||
bottom: calc(20px + env(safe-area-inset-bottom));
|
||||
right: 20px;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
border-radius: 50%;
|
||||
background-color: var(--interactive-accent);
|
||||
color: var(--text-on-accent);
|
||||
border: none;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 100;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
position: absolute;
|
||||
bottom: calc(20px + env(safe-area-inset-bottom));
|
||||
right: 20px;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
border-radius: 50%;
|
||||
background-color: var(--interactive-accent);
|
||||
color: var(--text-on-accent);
|
||||
border: none;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 100;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.mobile-fab:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.mobile-fab:active {
|
||||
transform: scale(0.95);
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.mobile-fab svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
/* Selection Toolbar */
|
||||
.mobile-selection-toolbar {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 8px;
|
||||
background-color: var(--background-primary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
position: absolute;
|
||||
bottom: calc(10px + env(safe-area-inset-bottom));
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 8px;
|
||||
background-color: var(--background-primary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
position: absolute;
|
||||
bottom: calc(10px + env(safe-area-inset-bottom));
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.mobile-toolbar-button {
|
||||
padding: 6px 12px;
|
||||
background-color: var(--interactive-normal);
|
||||
color: var(--text-normal);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 36px;
|
||||
min-height: 36px;
|
||||
padding: 6px 12px;
|
||||
background-color: var(--interactive-normal);
|
||||
color: var(--text-normal);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 36px;
|
||||
min-height: 36px;
|
||||
}
|
||||
|
||||
.mobile-toolbar-button:hover {
|
||||
background-color: var(--interactive-hover);
|
||||
background-color: var(--interactive-hover);
|
||||
}
|
||||
|
||||
.mobile-toolbar-button:active {
|
||||
background-color: var(--interactive-accent);
|
||||
color: var(--text-on-accent);
|
||||
background-color: var(--interactive-accent);
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
.mobile-toolbar-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.mobile-toolbar-icon svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
/* Settings Page Styles */
|
||||
.mobile-toolbar-section {
|
||||
margin: 1.5em 0;
|
||||
padding: 1em;
|
||||
background-color: var(--background-secondary);
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
margin: 1.5em 0;
|
||||
padding: 1em;
|
||||
background-color: var(--background-secondary);
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.mobile-toolbar-header {
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid var(--background-modifier-border);
|
||||
padding-bottom: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid var(--background-modifier-border);
|
||||
padding-bottom: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.mobile-command-list {
|
||||
margin: 0.5em 0;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
.mobile-add-command-btn {
|
||||
margin-top: 0.5em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
/* Settings Drag and Drop */
|
||||
.mobile-plugin-draggable-item {
|
||||
cursor: grab;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.mobile-plugin-draggable-item.is-dragging {
|
||||
opacity: 0.5;
|
||||
cursor: grabbing;
|
||||
opacity: 0.5;
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.mobile-plugin-draggable-item.drag-over-top {
|
||||
border-top: 2px solid var(--interactive-accent);
|
||||
border-top: 2px solid var(--interactive-accent);
|
||||
}
|
||||
|
||||
.mobile-plugin-draggable-item.drag-over-bottom {
|
||||
border-bottom: 2px solid var(--interactive-accent);
|
||||
border-bottom: 2px solid var(--interactive-accent);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue