├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github └── FUNDING.yml ├── .gitignore ├── .npmrc ├── LICENSE ├── README.md ├── esbuild.config.mjs ├── main.ts ├── manifest.json ├── package.json ├── rollup.config.js ├── styles.css ├── tsconfig.json └── versions.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | insert_final_newline = true 8 | indent_style = tab 9 | indent_size = 4 10 | tab_width = 4 -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | main.js 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "env": { "node": true }, 5 | "plugins": [ 6 | "@typescript-eslint" 7 | ], 8 | "extends": [ 9 | "eslint:recommended", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "parserOptions": { 14 | "sourceType": "module" 15 | }, 16 | "rules": { 17 | "no-unused-vars": "off", 18 | "@typescript-eslint/no-unused-vars": ["error", { "args": "none" }], 19 | "@typescript-eslint/ban-ts-comment": "off", 20 | "no-prototype-builtins": "off", 21 | "@typescript-eslint/no-empty-function": "off" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: kepano 4 | custom: https://www.buymeacoffee.com/kepano 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Intellij 2 | *.iml 3 | .idea 4 | 5 | # npm 6 | node_modules 7 | package-lock.json 8 | 9 | # build 10 | *.js.map 11 | main.js -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | tag-version-prefix="" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-2024 Steph Ango (@kepano) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Support the development of my plugins and themes **@kepano** on [Twitter](https://www.twitter.com/kepano) or [Buy me a coffee](https://www.buymeacoffee.com/kepano). 2 | 3 | 4 | 5 | ## Overview 6 | 7 | This plugin enables you to hide certain parts of the Obsidian UI. Note that your CSS theme may override Hider. 8 | 9 | - Hide app ribbon (can be bound to a hotkey) 10 | - Hide tab bar (can be bound to a hotkey) 11 | - Hide status bar (can be bound to a hotkey) 12 | - Hide vault name 13 | - Hide scrollbars 14 | - Hide search suggestions 15 | - Hide count of search term matches 16 | - Hide tooltips 17 | - Hide instructions in prompts 18 | - Hide metadata in Reading view 19 | 20 | ## Making your theme compatible with Hider 21 | 22 | Hider injects the following classes on the `body` element when features are toggled on. 23 | 24 | | Toggle | Class | 25 | | ------ | ----- | 26 | | App ribbon | `.hider-ribbon` | 27 | | Status bar | `.hider-status` | 28 | | Tab bar | `.hider-tabs` | 29 | | Vault name | `.hider-vault` | 30 | | Scrollbars | `.hider-scroll` | 31 | | Search suggestions | `.hider-search-suggestions` | 32 | | Search term counts | `.hider-search-counts` | 33 | | Tooltips | `.hider-tooltips` | 34 | | Instructions | `.hider-instructions` | 35 | | Metadata | `.hider-meta` | 36 | -------------------------------------------------------------------------------- /esbuild.config.mjs: -------------------------------------------------------------------------------- 1 | import esbuild from "esbuild"; 2 | import process from "process"; 3 | import builtins from "builtin-modules"; 4 | 5 | const banner = 6 | `/* 7 | THIS IS A GENERATED/BUNDLED FILE BY ESBUILD 8 | if you want to view the source, please visit the github repository of this plugin 9 | */ 10 | `; 11 | 12 | const prod = (process.argv[2] === "production"); 13 | 14 | const context = await esbuild.context({ 15 | banner: { 16 | js: banner, 17 | }, 18 | entryPoints: ["main.ts"], 19 | bundle: true, 20 | external: [ 21 | "obsidian", 22 | "electron", 23 | "@codemirror/autocomplete", 24 | "@codemirror/collab", 25 | "@codemirror/commands", 26 | "@codemirror/language", 27 | "@codemirror/lint", 28 | "@codemirror/search", 29 | "@codemirror/state", 30 | "@codemirror/view", 31 | "@lezer/common", 32 | "@lezer/highlight", 33 | "@lezer/lr", 34 | ...builtins], 35 | format: "cjs", 36 | target: "es2018", 37 | logLevel: "info", 38 | sourcemap: prod ? false : "inline", 39 | treeShaking: true, 40 | outfile: "main.js", 41 | minify: prod, 42 | }); 43 | 44 | if (prod) { 45 | await context.rebuild(); 46 | process.exit(0); 47 | } else { 48 | await context.watch(); 49 | } -------------------------------------------------------------------------------- /main.ts: -------------------------------------------------------------------------------- 1 | import { App, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian'; 2 | 3 | export default class Hider extends Plugin { 4 | settings: HiderSettings; 5 | 6 | async onload() { 7 | // load settings 8 | await this.loadSettings(); 9 | 10 | // add the settings tab 11 | this.addSettingTab(new HiderSettingTab(this.app, this)); 12 | // add the toggle on/off command 13 | 14 | this.addCommand({ 15 | id: 'toggle-tab-containers', 16 | name: 'Toggle tab bar', 17 | callback: () => { 18 | this.settings.hideTabs = !this.settings.hideTabs; 19 | this.saveData(this.settings); 20 | this.refresh(); 21 | } 22 | }); 23 | this.addCommand({ 24 | id: 'toggle-hider-status', 25 | name: 'Toggle status bar', 26 | callback: () => { 27 | this.settings.hideStatus = !this.settings.hideStatus; 28 | this.saveData(this.settings); 29 | this.refresh(); 30 | } 31 | }); 32 | this.refresh() 33 | } 34 | 35 | onunload() { 36 | console.log('Unloading Hider plugin'); 37 | } 38 | 39 | async loadSettings() { 40 | this.settings = Object.assign(DEFAULT_SETTINGS, await this.loadData()); 41 | } 42 | 43 | async saveSettings() { 44 | await this.saveData(this.settings); 45 | } 46 | 47 | // refresh function for when we change settings 48 | refresh = () => { 49 | // re-load the style 50 | this.updateStyle() 51 | } 52 | 53 | // update the styles (at the start, or as the result of a settings change) 54 | updateStyle = () => { 55 | document.body.classList.toggle('hider-status', this.settings.hideStatus); 56 | document.body.classList.toggle('hider-tabs', this.settings.hideTabs); 57 | document.body.classList.toggle('hider-scroll', this.settings.hideScroll); 58 | document.body.classList.toggle('hider-sidebar-buttons', this.settings.hideSidebarButtons); 59 | document.body.classList.toggle('hider-tooltips', this.settings.hideTooltips); 60 | document.body.classList.toggle('hider-search-suggestions', this.settings.hideSearchSuggestions); 61 | document.body.classList.toggle('hider-file-nav-header', this.settings.hideFileNavButtons); 62 | document.body.classList.toggle('hider-search-counts', this.settings.hideSearchCounts); 63 | document.body.classList.toggle('hider-instructions', this.settings.hideInstructions); 64 | document.body.classList.toggle('hider-meta', this.settings.hidePropertiesReading); 65 | document.body.classList.toggle('hider-vault', this.settings.hideVault); 66 | } 67 | 68 | } 69 | 70 | interface HiderSettings { 71 | hideStatus: boolean; 72 | hideTabs: boolean; 73 | hideScroll: boolean; 74 | hideSidebarButtons: boolean; 75 | hideTooltips: boolean; 76 | hideFileNavButtons: boolean; 77 | hideSearchSuggestions: boolean; 78 | hideSearchCounts: boolean; 79 | hideInstructions: boolean; 80 | hidePropertiesReading: boolean; 81 | hideVault: boolean; 82 | } 83 | const DEFAULT_SETTINGS: HiderSettings = { 84 | hideStatus: false, 85 | hideTabs: false, 86 | hideScroll: false, 87 | hideSidebarButtons: false, 88 | hideTooltips: false, 89 | hideFileNavButtons: false, 90 | hideSearchSuggestions: false, 91 | hideSearchCounts: false, 92 | hideInstructions: false, 93 | hidePropertiesReading: false, 94 | hideVault: false 95 | } 96 | 97 | class HiderSettingTab extends PluginSettingTab { 98 | 99 | 100 | plugin: Hider; 101 | constructor(app: App, plugin: Hider) { 102 | super(app, plugin); 103 | this.plugin = plugin; 104 | } 105 | 106 | display(): void { 107 | let {containerEl} = this; 108 | 109 | containerEl.empty(); 110 | 111 | new Setting(containerEl) 112 | .setName('Hide tab bar') 113 | .setDesc('Hides the tab container at the top of the window.') 114 | .addToggle(toggle => toggle.setValue(this.plugin.settings.hideTabs) 115 | .onChange((value) => { 116 | this.plugin.settings.hideTabs = value; 117 | this.plugin.saveData(this.plugin.settings); 118 | this.plugin.refresh(); 119 | }) 120 | ); 121 | 122 | new Setting(containerEl) 123 | .setName('Hide status bar') 124 | .setDesc('Hides word count, character count and backlink count.') 125 | .addToggle(toggle => toggle.setValue(this.plugin.settings.hideStatus) 126 | .onChange((value) => { 127 | this.plugin.settings.hideStatus = value; 128 | this.plugin.saveData(this.plugin.settings); 129 | this.plugin.refresh(); 130 | }) 131 | ); 132 | 133 | new Setting(containerEl) 134 | .setName('Hide vault name') 135 | .setDesc('Hides your vault profile. Warning: this also hides access to the Settings and vault switcher icons. You can use hotkeys or the command palette to open them.') 136 | .addToggle(toggle => toggle.setValue(this.plugin.settings.hideVault) 137 | .onChange((value) => { 138 | this.plugin.settings.hideVault = value; 139 | this.plugin.saveData(this.plugin.settings); 140 | this.plugin.refresh(); 141 | }) 142 | ); 143 | 144 | new Setting(containerEl) 145 | .setName('Hide scroll bars') 146 | .setDesc('Hides all scroll bars.') 147 | .addToggle(toggle => toggle.setValue(this.plugin.settings.hideScroll) 148 | .onChange((value) => { 149 | this.plugin.settings.hideScroll = value; 150 | this.plugin.saveData(this.plugin.settings); 151 | this.plugin.refresh(); 152 | }) 153 | ); 154 | 155 | new Setting(containerEl) 156 | .setName('Hide sidebar toggle buttons') 157 | .setDesc('Hides both sidebar buttons.') 158 | .addToggle(toggle => toggle.setValue(this.plugin.settings.hideSidebarButtons) 159 | .onChange((value) => { 160 | this.plugin.settings.hideSidebarButtons = value; 161 | this.plugin.saveData(this.plugin.settings); 162 | this.plugin.refresh(); 163 | }) 164 | ); 165 | 166 | new Setting(containerEl) 167 | .setName('Hide tooltips') 168 | .setDesc('Hides all tooltips.') 169 | .addToggle(toggle => toggle.setValue(this.plugin.settings.hideTooltips) 170 | .onChange((value) => { 171 | this.plugin.settings.hideTooltips = value; 172 | this.plugin.saveData(this.plugin.settings); 173 | this.plugin.refresh(); 174 | }) 175 | ); 176 | 177 | new Setting(containerEl) 178 | .setName('Hide file explorer buttons') 179 | .setDesc('Hides buttons at the top of file explorer (new file, new folder, etc).') 180 | .addToggle(toggle => toggle.setValue(this.plugin.settings.hideFileNavButtons) 181 | .onChange((value) => { 182 | this.plugin.settings.hideFileNavButtons = value; 183 | this.plugin.saveData(this.plugin.settings); 184 | this.plugin.refresh(); 185 | }) 186 | ); 187 | 188 | new Setting(containerEl) 189 | .setName('Hide instructions') 190 | .setDesc('Hides instructional tips in modals.') 191 | .addToggle(toggle => toggle.setValue(this.plugin.settings.hideInstructions) 192 | .onChange((value) => { 193 | this.plugin.settings.hideInstructions = value; 194 | this.plugin.saveData(this.plugin.settings); 195 | this.plugin.refresh(); 196 | }) 197 | ); 198 | 199 | new Setting(containerEl) 200 | .setName('Hide search suggestions') 201 | .setDesc('Hides suggestions in search pane.') 202 | .addToggle(toggle => toggle.setValue(this.plugin.settings.hideSearchSuggestions) 203 | .onChange((value) => { 204 | this.plugin.settings.hideSearchSuggestions = value; 205 | this.plugin.saveData(this.plugin.settings); 206 | this.plugin.refresh(); 207 | }) 208 | ); 209 | 210 | new Setting(containerEl) 211 | .setName('Hide count of search term matches') 212 | .setDesc('Hides the number of matches within each search result.') 213 | .addToggle(toggle => toggle.setValue(this.plugin.settings.hideSearchCounts) 214 | .onChange((value) => { 215 | this.plugin.settings.hideSearchCounts = value; 216 | this.plugin.saveData(this.plugin.settings); 217 | this.plugin.refresh(); 218 | }) 219 | ); 220 | 221 | new Setting(containerEl) 222 | .setName('Hide properties in Reading view') 223 | .setDesc('Hides the properties section in Reading view.') 224 | .addToggle(toggle => toggle.setValue(this.plugin.settings.hidePropertiesReading) 225 | .onChange((value) => { 226 | this.plugin.settings.hidePropertiesReading = value; 227 | this.plugin.saveData(this.plugin.settings); 228 | this.plugin.refresh(); 229 | }) 230 | ); 231 | 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "obsidian-hider", 3 | "name": "Hider", 4 | "version": "1.5.1", 5 | "minAppVersion": "1.6.0", 6 | "description": "Hide UI elements such as tooltips, status, titlebar and more", 7 | "author": "@kepano", 8 | "authorUrl": "https://www.twitter.com/kepano", 9 | "fundingUrl": "https://www.buymeacoffee.com/kepano", 10 | "isDesktopOnly": false 11 | } 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "obsidian-hider", 3 | "version": "1.0.0", 4 | "description": "Hider", 5 | "main": "main.js", 6 | "scripts": { 7 | "dev": "node esbuild.config.mjs", 8 | "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", 9 | "version": "node version-bump.mjs && git add manifest.json versions.json" 10 | }, 11 | "keywords": [], 12 | "author": "@kepano", 13 | "license": "MIT", 14 | "devDependencies": { 15 | "@types/node": "^16.11.6", 16 | "@typescript-eslint/eslint-plugin": "5.29.0", 17 | "@typescript-eslint/parser": "5.29.0", 18 | "builtin-modules": "3.3.0", 19 | "esbuild": "0.17.3", 20 | "obsidian": "latest", 21 | "tslib": "2.4.0", 22 | "typescript": "4.7.4" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import typescript from '@rollup/plugin-typescript'; 2 | import {nodeResolve} from '@rollup/plugin-node-resolve'; 3 | import commonjs from '@rollup/plugin-commonjs'; 4 | 5 | export default { 6 | input: 'main.ts', 7 | output: { 8 | dir: '.', 9 | sourcemap: 'inline', 10 | format: 'cjs', 11 | exports: 'default' 12 | }, 13 | external: ['obsidian'], 14 | plugins: [ 15 | typescript(), 16 | nodeResolve({browser: true}), 17 | commonjs(), 18 | ] 19 | }; -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | /* Hides vault name */ 2 | .hider-vault .workspace-sidedock-vault-profile, 3 | body.hider-vault:not(.is-mobile) .workspace-split.mod-left-split .workspace-sidedock-vault-profile { 4 | display:none; 5 | } 6 | 7 | /* Hide tabs */ 8 | .hider-tabs .mod-root .workspace-tabs .workspace-tab-header-container { 9 | display: none; 10 | } 11 | 12 | .hider-tabs .mod-top-left-space .view-header { 13 | padding-left: var(--frame-left-space); 14 | } 15 | 16 | /* Hide sidebar buttons */ 17 | .hider-sidebar-buttons .sidebar-toggle-button.mod-right, 18 | .hider-sidebar-buttons .sidebar-toggle-button.mod-left { 19 | display: none; 20 | } 21 | .hider-sidebar-buttons.mod-macos.is-hidden-frameless:not(.is-popout-window) .workspace .workspace-tabs.mod-top-right-space .workspace-tab-header-container { 22 | padding-right: 4px; 23 | } 24 | .hider-sidebar-buttons.mod-macos { 25 | --frame-left-space: 60px; 26 | } 27 | 28 | /* Hide meta */ 29 | .hider-meta .markdown-reading-view .metadata-container { 30 | display:none; 31 | } 32 | 33 | /* Hide scrollbars */ 34 | .hider-scroll ::-webkit-scrollbar { 35 | display:none; 36 | } 37 | 38 | /* Hide status */ 39 | .hider-status .status-bar { 40 | display:none; 41 | } 42 | 43 | /* Hide tooltips */ 44 | .hider-tooltips .tooltip { 45 | display:none; 46 | } 47 | 48 | /* Hide search suggestions */ 49 | .hider-search-suggestions .suggestion-container.mod-search-suggestion { 50 | display: none; 51 | } 52 | 53 | /* Hide search count flair */ 54 | .hider-search-counts .tree-item-flair:not(.tag-pane-tag-count) { 55 | display:none; 56 | } 57 | 58 | /* Hide instructions */ 59 | .hider-instructions .prompt-instructions { 60 | display:none; 61 | } 62 | 63 | /* Hide file nav header */ 64 | .hider-file-nav-header .workspace-leaf-content[data-type=file-explorer] .nav-header { 65 | display: none; 66 | } 67 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "inlineSourceMap": true, 5 | "inlineSources": true, 6 | "module": "ESNext", 7 | "target": "es6", 8 | "allowJs": true, 9 | "noImplicitAny": true, 10 | "moduleResolution": "node", 11 | "importHelpers": true, 12 | "lib": [ 13 | "dom", 14 | "es5", 15 | "scripthost", 16 | "es2015" 17 | ] 18 | }, 19 | "include": [ 20 | "**/*.ts" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "1.4.0": "1.6.0", 3 | "1.3.1": "1.4.0", 4 | "1.3.1": "1.4.0", 5 | "1.3.0": "1.4.0", 6 | "1.2.5": "0.16.0", 7 | "1.2.4": "0.16.0", 8 | "1.2.3": "0.16.0", 9 | "1.2.2": "0.16.0", 10 | "1.2.1": "0.16.0", 11 | "1.2.0": "0.16.0", 12 | "1.1.1": "0.12.2", 13 | "1.1.0": "0.12.2", 14 | "1.0.8": "0.12.2", 15 | "1.0.7": "0.12.2", 16 | "1.0.6": "0.12.2", 17 | "1.0.5": "0.9.12", 18 | "1.0.4": "0.9.12", 19 | "1.0.3": "0.9.12", 20 | "1.0.2": "0.9.12", 21 | "1.0.1": "0.9.12", 22 | "1.0.0": "0.9.12" 23 | } 24 | --------------------------------------------------------------------------------