README file from
GithubThe Most Colorful Obsidian Toolbar
A fully customizable, collapsible toolbar that floats above the keyboard, replacing the default toolbar. Highly polished, feature-rich. Built (and maintained!) with ❤️
In edit mode (wrench 🔧 icon, or obsidian command Gay Toolbar: Toggle edit mode), each button can be assigned a primary (tap) and optional secondary (long-press) obsidian command, as well as any number of swipe commands, each assigned to a different swipe direction. Buttons can be moved between slots by long-pressing and dragging in edit mode. Their colors can be customized from a customizable color palette or assigned in bulk. The background color of the whole toolbar can be set to a solid color, or you can use your own CSS value for crazy radial gradients or whatever. Did I mention this toolbar is customizable? The number and size of rows and columns can also be set independently, and when you arrive at a config you like, you can snapshot it like a video game save slot.
P.S. My partner and I are looking for freelance work. She specializes in real-time full-stack app development (web sockets, Go, etc.). I specialize in real-time front ends, animation, and performance. Together, we've built apps, AI integrations, plugins, and much more. P.P.S. I've found Code Editor Shortcuts to be utterly indispensable so I highly recommend you explore what other plugins add the behavior you want so you can add it to your Gay toolbar.
(now for the AI-generated part BUT there's still helpful clarifications here. Think of it like a Q&A)
Highlighted Features
- Customizable Toolbar:
- Move (via dragging), add, remove, and personalize buttons (color, icons, and commands).
- Button slots can remain empty, creating gaps in the toolbar if desired.
- Save and load configs -- freely experiment and return to layouts you know work for you if you get lost.
- Many Commands Per Button:
- Primary Action: Triggered by a tap.
- Secondary Action: Triggered by a long press (tap and hold for a customizable duration, default: 200ms).
- Swipe Actions: Triggered by swiping from the button in the assigned direction.
- Each action can have distinct, customizable icons.
- Smart Icon Colors:
- Icon colors are automatically chosen to maximize contrast against button background colors, using perceived luminance. This, was not easy.
- Show/Hide Toolbar: The
Gay Toolbar: Minimizecommand hides the toolbar, leaving one floating button that re-opens the toolbar. In the default config, it's the middle button in the right-most column.
Toolbar Edit Mode
Main Settings (if no button is selected)
- The default config includes a 🔧 wrench icon in the top right — tap it to enter Edit Mode, or run
Gay Toolbar: Toggle Edit Modevia the Command Palette. - Saved Configs: Save the current config and load previous saved configs anytime. Configs are stored in a markdown file in your vault; the file path is configurable in Obsidian Settings → Gay Toolbar (“Saved configs file path”).
- Use a custom background (your own CSS value, e.g.
radial-gradient(circle at bottom, pink, grey, white)). Layout, appearance, and other options are grouped in accordion sections. - Custom Commands: Open the Command editor from main settings to create your own Obsidian commands with custom JavaScript (the editor is JavaScript only; no in-app TypeScript compilation). Write JavaScript that has access to
plugin,app, andconsole. Use Test to run the code; anyconsole.log/warn/erroroutput appears in the panel below. For full debugging, use Help → Developer tools. Test commands before saving and manage them in a table. Commands are persisted and loaded on startup. You can also Restore defaults (toolbar layout and settings) from the main settings without losing your custom commands or color presets. - Mobile only: In Obsidian Settings → Gay Toolbar you can enable “Mobile only” so the toolbar is shown only on mobile (restart to apply).
Example Command - Toggle underline on selected text:
const view = app.workspace.activeEditor;
if (view && view.editor) {
const editor = view.editor;
const selection = editor.getSelection();
if (selection) {
const underlineRegex = /^\s*<u>(.*?)<\/u>\s*$/s;
const match = selection.match(underlineRegex);
if (match) {
editor.replaceSelection(match[1]);
} else {
editor.replaceSelection(`<u>${selection}</u>`);
}
} else {
new Notice("No text selected");
}
}
Button Settings
- Add Buttons: Tap an empty slot (
+) to insert a button (new button color is chosen randomly from color presets -- edit these in the color picker modal). - Edit Buttons: Tap an existing button to change its primary action/icon (bottom right button), secondary action/icon (top left button), or color, or to remove it.
- Drag & Drop: Long-press to initiate a drag operation to move buttons. If you drop a button on a non-empty slot, the button in that slot swaps positions with the one being dragged.
- Group Actions: Assign multiple commands per button, each with its own icon. The press duration is user-configurable in the main settings via the
Long-press delayoption. Personally, I like to group related commands likeundo/redoandindent/outdent.
Roadmap
If you’re excited about seeing any of these or other ideas implemented, I’d love to collaborate! I’m happy to hop on a call and pair-code with you, even if you’re new to coding. What matters most to me is our shared investment in shaping our tools to meet our needs — I cherish connection built on loving the technology that supports us.
-
Time-dependent Colors: Automatically change toolbar colors based on time (daily or even every second).
-
Better Icon Support: Add emoji support to icon selector.
-
Separate Icon and Command Selection Flow
-
Swipe Button Actions: Add additional swipe gestures for more commands (e.g., swipe up, down, left, right). Visual cues will display custom colors for each gesture on the border of each button and dynamically as the user swipes. Example button for block editing:
- Tap: Select the current block.
- Long-Press: Copy the current block.
- Swipe Left: Outdent.
- Swipe Right: Indent.
- Swipe Down: Move the block down.
- Swipe Up: Move the block up.
Contributions
Development Setup
To run the plugin locally:
-
Install dependencies:
npm i -
Start development mode (builds
main.jsfromsrc/main.tsx, watches source andstyles/*.cssand writes combinedstyles.css):npm run dev -
Build for production:
npm run build -
Run tests:
npm run test npm run test:watch # watch mode npm run test:coverage # coverage report
Android Development Sync
To sync changes to your Android Obsidian installation via ADB on save, have npm run dev running in another terminal and then:
fswatch -o main.js styles.css manifest.json data.json | xargs -n1 -I{} sh -c 'echo "Files changed, syncing..."; adb push main.js <path/to/.obsidian>/plugins/gay-toolbar/ && adb push styles.css <path/to/.obsidian>/plugins/gay-toolbar/ && adb push manifest.json <path/to/.obsidian>/plugins/gay-toolbar/ && adb push data.json <path/to/.obsidian>/plugins/gay-toolbar/ && echo "Sync complete"'
Replace <path/to/.obsidian> with your actual Obsidian vault path. The data.json sync is optional - you can remove it from the command if you don't want to sync your settings.
I've found the hot-reload plugin sometimes useful, as well as the dev tools plugin, tho for the latter case it's often easier to use the chrome devtools on mac, connected to android via adb. Lmk if you need help; happy to accept PRs!