From c8ec549fa571da1e8c75b2ec852ca8693ab54470 Mon Sep 17 00:00:00 2001 From: Claude Fable 5 Date: Sun, 12 Jul 2026 15:33:32 +0200 Subject: [PATCH] UI polish: frameless plugin blocks in read mode, sticky toolbar, pinned footer, icon uninstall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three refinements from Stefan's review of the plugin work: - read mode integrates plugin output like normal content: no border, no name bar, no selection outline around plugin blocks — same principle as the frameless reading shell (M10) - the editor toolbar pins to the top of the scrolling content area on long articles instead of scrolling away (position: sticky within the main scroll container) - the app footer (connection status + legal links) moved out of the scroll container into a main-column wrapper — always visible at the bottom edge of the window on every view - the plugin uninstall buttons in the admin list are icon buttons now (Trash2, house pattern: aria-label keeps the accessible name) - lint hygiene: eslint/prettier ignore packages/plugins/*/vendor — the unpacked drawio webapp drove eslint out of memory Verified in the browser against a local stack (5/5 scripted checks: icon buttons, toolbar sticky at scroll bottom, footer pinned in edit and read mode, plugin block computed border/outline none in read mode) plus 8 layout-sensitive e2e packs re-run individually, all green (comments, collab, legal, content, plugin-admin, plugin-blocks, page-tools, plugins). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01EwZ4jR4KFAPvpjWevfUGX1 --- .prettierignore | 1 + apps/web/src/layout/AppLayout.tsx | 10 ++++++--- apps/web/src/pages/PluginManager.tsx | 10 ++++++--- apps/web/src/styles/base.css | 32 ++++++++++++++++++++++++++-- eslint.config.mjs | 2 ++ 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/.prettierignore b/.prettierignore index a19c045..ab6b0b5 100644 --- a/.prettierignore +++ b/.prettierignore @@ -14,3 +14,4 @@ fixtures/import/*.src.html # Export fidelity corpus (issue #69): the round-trip snapshots must stay exactly # as pandoc reads the exported document back — Prettier would break them. fixtures/export/*.expected.md +packages/plugins/*/vendor/ diff --git a/apps/web/src/layout/AppLayout.tsx b/apps/web/src/layout/AppLayout.tsx index 0f9cc43..cd0ab18 100644 --- a/apps/web/src/layout/AppLayout.tsx +++ b/apps/web/src/layout/AppLayout.tsx @@ -63,10 +63,14 @@ export function AppLayout(): React.JSX.Element { > {!collapsed && } -
- +
+
+ +
+ {/* Outside the scroll container: always visible at the bottom + edge of the window (M10 follow-up 3). */}
-
+ diff --git a/apps/web/src/pages/PluginManager.tsx b/apps/web/src/pages/PluginManager.tsx index 8c68db5..ce1772b 100644 --- a/apps/web/src/pages/PluginManager.tsx +++ b/apps/web/src/pages/PluginManager.tsx @@ -1,3 +1,4 @@ +import { Trash2 } from 'lucide-react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useRef, useState } from 'react'; import { Link } from 'react-router-dom'; @@ -122,12 +123,15 @@ export function PluginManager(): React.JSX.Element { diff --git a/apps/web/src/styles/base.css b/apps/web/src/styles/base.css index 8544c1b..2041659 100644 --- a/apps/web/src/styles/base.css +++ b/apps/web/src/styles/base.css @@ -248,8 +248,16 @@ button { max-width: 36rem; } +.main-column { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; +} + .main { flex: 1; + min-height: 0; min-width: 0; overflow-y: auto; padding: var(--space-6) var(--space-8); @@ -497,9 +505,10 @@ button { display: flex; align-items: center; gap: var(--space-2); - margin-top: var(--space-8); - padding-top: var(--space-3); + flex-shrink: 0; + padding: var(--space-2) var(--space-8); border-top: 1px solid var(--color-border); + background: var(--color-bg); color: var(--color-text-muted); font-size: 0.85rem; } @@ -832,6 +841,11 @@ button { padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--color-border); background: var(--color-bg-subtle); + /* Long articles: the toolbar pins to the top of the scrolling content + area instead of scrolling away. */ + position: sticky; + top: 0; + z-index: 20; } .editor-toolbar__group { @@ -931,6 +945,20 @@ button { border: none; } +/* Read mode integrates plugin output like normal content: no frame, no + name bar — same principle as the frameless reading shell (M10). */ +.editor-shell--reading .plugin-block { + border: none; + border-radius: 0; + background: transparent; + /* No selection outline either — reading is not editing. */ + outline: none; +} + +.editor-shell--reading .plugin-block__bar { + display: none; +} + .plugin-block__fallback { padding: var(--space-2) var(--space-3); } diff --git a/eslint.config.mjs b/eslint.config.mjs index c7ea911..7e1782e 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -9,6 +9,8 @@ export default tseslint.config( { ignores: [ '**/dist/**', + // Vendored third-party apps bundled into plugins (drawio) — never linted. + 'packages/plugins/*/vendor/**', '**/node_modules/**', '**/coverage/**', '**/.pnpm-store/**',