Notes and focus panel

Floating minimal control panel: dark mode, focus mode, rich-text notes with save/open/delete

Ajankohdalta 1.10.2025. Katso uusin versio.

// ==UserScript==
// @name         Notes and focus panel
// @namespace    http://tampermonkey.net/
// @version      2.1
// @description  Floating minimal control panel: dark mode, focus mode, rich-text notes with save/open/delete
// @match        *://*/*
// @grant        GM_addStyle
// ==/UserScript==

(function () {
    'use strict';

    // --- STYLES ---
    GM_addStyle(`
      #tm-utility-btn {
        position: fixed; top: 50%; right: 0;
        transform: translateY(-50%);
        background: rgba(30,30,30,0.9);
        color: white; border: none;
        padding: 10px 14px;
        border-radius: 12px 0 0 12px;
        cursor: pointer;
        z-index: 999999;
        transition: background 0.3s ease, right 0.3s ease;
      }
      #tm-utility-btn:hover { background: rgba(50,50,50,0.95); }

      #tm-utility-panel {
        position: fixed; top: 50%; right: -360px;
        transform: translateY(-50%);
        width: 340px; height: 500px;
        background: rgba(250,250,250,0.98);
        box-shadow: -4px 0 20px rgba(0,0,0,0.2);
        border-radius: 12px 0 0 12px;
        display: flex; flex-direction: column;
        transition: right 0.4s ease;
        z-index: 999999;
        font-family: sans-serif;
      }
      #tm-utility-panel.open { right: 0; }

      #tm-controls {
        display: flex; gap: 6px;
        padding: 8px;
        background: #f0f0f0;
        border-bottom: 1px solid #ddd;
      }
      #tm-controls button {
        flex: 1;
        background: #fff;
        border: 1px solid #ccc;
        border-radius: 6px;
        padding: 4px 6px;
        cursor: pointer;
        font-size: 13px;
        transition: background 0.2s;
      }
      #tm-controls button:hover { background: #eee; }

      #tm-editor {
        flex: 1; padding: 10px;
        border: none; outline: none;
        font-size: 14px;
        overflow-y: auto;
        color: black; /* default text color */
        background: #fff;
      }

      #tm-editor[contenteditable="true"]:focus {
        outline: none;
      }

      /* Dark mode */
      .tm-dark { filter: invert(1) hue-rotate(180deg); transition: filter 0.4s ease; }
      .tm-dark #tm-editor {
        color: white !important;
        background: #222 !important;
      }

      /* Focus mode */
      .tm-focus aside, .tm-focus header, .tm-focus footer,
      .tm-focus nav, .tm-focus [class*="sidebar"], .tm-focus [id*="sidebar"] {
        display: none !important;
      }

      #tm-actions {
        display: flex; gap: 6px;
        padding: 8px;
        border-top: 1px solid #ddd;
        background: #fafafa;
      }
      #tm-actions button {
        flex: 1;
        background: #0078d7; color: white;
        border: none; border-radius: 6px;
        padding: 6px 8px;
        cursor: pointer;
        font-size: 13px;
        transition: background 0.2s;
      }
      #tm-actions button:hover { background: #005ea6; }
    `);

    // --- PANEL + BUTTON ---
    const btn = document.createElement("button");
    btn.id = "tm-utility-btn";
    btn.textContent = "☰ Tools";
    document.body.appendChild(btn);

    const panel = document.createElement("div");
    panel.id = "tm-utility-panel";
    panel.innerHTML = `
      <div id="tm-controls">
        <button id="bold">B</button>
        <button id="underline">U</button>
        <button id="link">🔗</button>
        <button id="dark">🌙</button>
        <button id="focus">🧘</button>
      </div>
      <div id="tm-editor" contenteditable="true"></div>
      <div id="tm-actions">
        <button id="save">Save</button>
        <button id="open">Open</button>
        <button id="clear">Delete</button>
      </div>
    `;
    document.body.appendChild(panel);

    const editor = panel.querySelector("#tm-editor");

    // Load saved note if exists
    editor.innerHTML = localStorage.getItem("tm-note") || "";

    // --- TOGGLE PANEL ---
    btn.onclick = () => {
        panel.classList.toggle("open");
    };

    // --- FORMAT BUTTONS ---
    panel.querySelector("#bold").onclick = () => document.execCommand("bold");
    panel.querySelector("#underline").onclick = () => document.execCommand("underline");
    panel.querySelector("#link").onclick = () => {
        const url = prompt("Enter link URL:");
        if (url) document.execCommand("createLink", false, url);
    };

    // --- DARK MODE ---
    panel.querySelector("#dark").onclick = () => {
        document.body.classList.toggle("tm-dark");
    };

    // --- FOCUS MODE ---
    panel.querySelector("#focus").onclick = () => {
        document.body.classList.toggle("tm-focus");
    };

    // --- NOTE ACTIONS ---
    panel.querySelector("#save").onclick = () => {
        localStorage.setItem("tm-note", editor.innerHTML);
        alert("Note saved ✅");
    };

    panel.querySelector("#open").onclick = () => {
        editor.innerHTML = localStorage.getItem("tm-note") || "";
    };

    panel.querySelector("#clear").onclick = () => {
        if (confirm("Delete your saved note?")) {
            localStorage.removeItem("tm-note");
            editor.innerHTML = "";
        }
    };
})();