From 44a90a53ac1bf2a75f533d88b7d6813be28cbb5c Mon Sep 17 00:00:00 2001 From: Claude Fable 5 Date: Wed, 15 Jul 2026 13:09:31 +0200 Subject: [PATCH] Sidebar: pin the four actions as an icon row at the bottom Graph, new page, import, and trash collapse from scattered text links into one icon row pinned to the sidebar's bottom edge, in that order, each with a hover hint (the trash reads "Papierkorb anzeigen"). The new-page button now toggles the inline form, which still renders above the footer with the same classes; the import trigger becomes an icon whose progress list floats above the row so the icons stay put. All e2e class hooks (.sidebar__new-page, .sidebar__graph-link, .sidebar__import-*) are unchanged. Fixes #124 Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Fb2VzvcoBPHkjh8bZ6PzQn --- apps/web/src/import/ImportControl.tsx | 7 +++- apps/web/src/layout/Sidebar.tsx | 57 ++++++++++++++++++--------- apps/web/src/styles/base.css | 41 ++++++++----------- packages/shared/i18n/de/common.json | 1 + packages/shared/i18n/de/editor.json | 1 + packages/shared/i18n/en/common.json | 1 + packages/shared/i18n/en/editor.json | 1 + 7 files changed, 64 insertions(+), 45 deletions(-) diff --git a/apps/web/src/import/ImportControl.tsx b/apps/web/src/import/ImportControl.tsx index 040458c..a6e8d0e 100644 --- a/apps/web/src/import/ImportControl.tsx +++ b/apps/web/src/import/ImportControl.tsx @@ -1,4 +1,5 @@ import { IMPORT_EXTENSIONS } from '@dorfteich/shared'; +import { Import } from 'lucide-react'; import { useRef } from 'react'; import { useTranslation } from 'react-i18next'; @@ -28,10 +29,12 @@ export function ImportControl({ pondId, pondSlug }: ImportControlProps): React.J
} - {creating ? ( + {creating && ( setCreating(false)} /> - ) : ( - )} - - {/* Keyboard/drag reordering announcements for screen readers. */}

{announcement}

- {/* Graph + trash stay text links, pinned to the sidebar's bottom - (M10 follow-up; pond settings moved to the TopBar gear icon). - The graph is for every member (#112); the trash is owner-only. */} + {/* All four actions live as an icon row pinned to the sidebar's + bottom (#124): graph, new page, import, trash — hover hints via + title. The graph is for every member (#112); trash is owner-only. */}
- - {t('graph:link')} + + + + {isOwner && ( - - {t('editor:trash.link')} + + )}
diff --git a/apps/web/src/styles/base.css b/apps/web/src/styles/base.css index 4236ee7..9bd438c 100644 --- a/apps/web/src/styles/base.css +++ b/apps/web/src/styles/base.css @@ -148,10 +148,6 @@ button { padding: var(--space-1) var(--space-2); } -.sidebar__trash-link { - font-size: 0.85rem; - white-space: nowrap; -} .sidebar__pages { list-style: none; @@ -369,13 +365,6 @@ button { font-weight: 600; } -.sidebar__new-page { - font-size: 0.9rem; - /* The sidebar is a flex column now; keep the stretched button reading - like the left-aligned link it used to be. */ - text-align: left; -} - .sidebar__new-page-form { margin-top: var(--space-2); } @@ -390,21 +379,29 @@ button { gap: var(--space-3); } +/* The import control sits in the pinned footer icon row (#124); its + progress list floats ABOVE the row so the icons stay put. */ .sidebar__import { - margin-top: var(--space-2); -} - -.sidebar__import-action { - font-size: 0.9rem; + position: relative; + display: inline-flex; } .sidebar__import-list { list-style: none; - margin: var(--space-2) 0 0; - padding: 0; + position: absolute; + bottom: calc(100% + var(--space-1)); + left: 0; + width: 14rem; + margin: 0; + padding: var(--space-2); display: flex; flex-direction: column; gap: var(--space-2); + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius); + box-shadow: 0 4px 12px rgb(0 0 0 / 10%); + z-index: 30; } .sidebar__import-item { @@ -1760,12 +1757,8 @@ button { margin-top: auto; padding-top: var(--space-4); display: flex; - gap: var(--space-3); -} - -.sidebar__graph-link { - font-size: 0.85rem; - white-space: nowrap; + align-items: center; + gap: var(--space-1); } /* Knowledge graph (issue #112) + local graph panel (#113). */ diff --git a/packages/shared/i18n/de/common.json b/packages/shared/i18n/de/common.json index 22b7c1a..6f5facf 100644 --- a/packages/shared/i18n/de/common.json +++ b/packages/shared/i18n/de/common.json @@ -21,6 +21,7 @@ "reparented": "{{title}} unter {{parent}} eingeordnet." }, "newPage": "+ Neue Seite", + "newPageHint": "Neue Seite", "newPageTitle": "Titel", "newPageUnder": "Wird unter „{{title}}“ angelegt.", "create": "Erstellen", diff --git a/packages/shared/i18n/de/editor.json b/packages/shared/i18n/de/editor.json index 001e6c0..4a42bcb 100644 --- a/packages/shared/i18n/de/editor.json +++ b/packages/shared/i18n/de/editor.json @@ -142,6 +142,7 @@ }, "trash": { "link": "Papierkorb", + "showLink": "Papierkorb anzeigen", "title": "Papierkorb — {{pond}}", "empty": "Der Papierkorb ist leer.", "deletedAt": "Gelöscht am {{date}}", diff --git a/packages/shared/i18n/en/common.json b/packages/shared/i18n/en/common.json index f27b50d..5a56d04 100644 --- a/packages/shared/i18n/en/common.json +++ b/packages/shared/i18n/en/common.json @@ -21,6 +21,7 @@ "reparented": "Moved {{title}} under {{parent}}." }, "newPage": "+ New page", + "newPageHint": "New page", "newPageTitle": "Title", "newPageUnder": "Will be created under “{{title}}”.", "create": "Create", diff --git a/packages/shared/i18n/en/editor.json b/packages/shared/i18n/en/editor.json index 18541bc..c3060c6 100644 --- a/packages/shared/i18n/en/editor.json +++ b/packages/shared/i18n/en/editor.json @@ -142,6 +142,7 @@ }, "trash": { "link": "Trash", + "showLink": "Show trash", "title": "Trash — {{pond}}", "empty": "The trash is empty.", "deletedAt": "Deleted {{date}}",