Merge branch 'dev' into main: v0.13.0
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 24s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sandrodachandClaude Opus 5.5 committed 2026-10-30 23:12:06 +01:00
commit 333d83304d
15 files changed
+148 -89

No files matched your search

+14 -1
View File
@@ -6,6 +6,18 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die V
## [Unreleased]
## [0.13.0] - 2026-10-30
### Added
- Neues Theme **Terrakotta Nacht**: das dunkle Gegenstück zu Terrakotta – Espresso-Braun, Creme-Schrift, glühender Terrakotta-Akzent, Salbeigrün, weiche Ecken.
- Animationen: Menüs (Benutzermenü, Drei-Punkte-Menü), Dialoge und Bottom-Sheets blenden und gleiten weich ein; am Handy schiebt sich eine Notiz von rechts herein und die Liste beim Zurück von links. Am PC bleibt der Notizwechsel sofort. Bei „Bewegung reduzieren“ im System gibt es keine Animationen.
### Removed
- Theme „Soft Slate“; wer es aktiv hatte, bekommt automatisch „Terrakotta Nacht“.
### Fixed
- Die vorhandenen Ein-/Ausblend-Animationen (`animate-in`, `fade-in`, `slide-in-from-*`) liefen nie, weil das Tailwind-Plugin fehlte (`tailwindcss-animate`).
## [0.12.2] - 2026-10-30
### Fixed
@@ -312,7 +324,8 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die V
- Geteilte Listen (Einkaufs-, Pack- und Checklisten) mit `#Kategorie`-Gruppierung, Mengenangaben und Echtzeit-Abhaken.
- Benutzer-, Gruppen- und Admin-Verwaltung (Ersteinrichtungs-Assistent, Einladungscodes, Profilbilder, persönliche API-Keys & Webhook-Ingest `/api/v1/webhooks/ingest`, JSON-Datenexport) sowie CSS-Theme-Engine mit 4 Themes (`Dark`, `Light`, `High Contrast`, `Soft`) und PWA-Unterstützung.
[Unreleased]: https://git.dsit.me/sandrodach/MindSift/compare/v0.12.2...dev
[Unreleased]: https://git.dsit.me/sandrodach/MindSift/compare/v0.13.0...dev
[0.13.0]: https://git.dsit.me/sandrodach/MindSift/compare/v0.12.2...v0.13.0
[0.12.2]: https://git.dsit.me/sandrodach/MindSift/compare/v0.12.1...v0.12.2
[0.12.1]: https://git.dsit.me/sandrodach/MindSift/compare/v0.12.0...v0.12.1
[0.12.0]: https://git.dsit.me/sandrodach/MindSift/compare/v0.11.1...v0.12.0
+1 -1
View File
@@ -81,7 +81,7 @@ Jede Theme-Datei gliedert sich in sechs exakt definierte Bereiche:
| `dark` | [`theme-dark.css`](../frontend/src/themes/theme-dark.css) | Standard Dark Slate / Monochrom | Streng eckig (`0px` Cards, `2px` Buttons) |
| `light` | [`theme-light.css`](../frontend/src/themes/theme-light.css) | Daylight Clean White / Minimalistisch | Modern dezent (`4px` Cards, `4px` Buttons) |
| `terracotta` | [`theme-terracotta.css`](../frontend/src/themes/theme-terracotta.css) | Warmes Cremepapier, Tinte, Terrakotta-Akzent, eigene Code-Farben in Erdtönen | Weich (`12px`) |
| `soft` | [`theme-soft.css`](../frontend/src/themes/theme-soft.css) | Warmes Soft Slate mit Indigo-Akzent | Weich gerundet (`12px` Cards, `8px` Buttons) |
| `terracotta-night` | [`theme-terracotta-night.css`](../frontend/src/themes/theme-terracotta-night.css) | Espresso-Braun, Creme-Schrift, glühender Terrakotta-Akzent | Weich (`12px`) |
| `polarized` | [`theme-polarized.css`](../frontend/src/themes/theme-polarized.css) | Tiefdunkles Obsidian mit elektrischem Grün/Türkis | Streng eckig (`0px` Cards, `2px` Buttons) |
| `suri` | [`theme-suri.css`](../frontend/src/themes/theme-suri.css) | Warmes Mitternachts-Pflaume mit samtiger Orchidee | Weich gerundet (`10px` Cards, `6px` Buttons) |
| *Template* | [`theme-template.css`](../frontend/src/themes/theme-template.css) | Vollständig dokumentierte Kopiervorlage | Frei anpassbar |
+1 -1
View File
@@ -100,7 +100,7 @@ Technik dahinter: [Doku/modules/collaboration.md](Doku/modules/collaboration.md)
* Geführte Ersteinrichtung, Rollen *Admin* und *Mitglied*, Einladungscodes, optional offene Registrierung.
* Gruppen mit Gruppen-Admins für Freigaben.
* Admin-Bereich: Benutzer, Einladungen, Instanzname, SMTP, Freigabe-Modus.
* Sechs Themes (Dark, Light, Terrakotta, Soft, Polarized, Suri) plus Theme-Manager für eigene CSS-Themes, installierbar als PWA. Die App startet auch ohne Netz mit dem zuletzt geladenen Stand; offline erfasste Gedanken und abgehakte Aufgaben oder Listeneinträge werden nachgereicht, sobald die Verbindung wieder da ist.
* Sechs Themes (Dark, Light, Terrakotta, Terrakotta Nacht, Polarized, Suri) plus Theme-Manager für eigene CSS-Themes, installierbar als PWA. Die App startet auch ohne Netz mit dem zuletzt geladenen Stand; offline erfasste Gedanken und abgehakte Aufgaben oder Listeneinträge werden nachgereicht, sobald die Verbindung wieder da ist.
### 🔌 Integrationen
+13 -2
View File
@@ -1,12 +1,12 @@
{
"name": "mindsift-frontend",
"version": "0.12.2",
"version": "0.13.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mindsift-frontend",
"version": "0.12.2",
"version": "0.13.0",
"license": "Unlicense",
"dependencies": {
"@fontsource-variable/inter": "5.3.0",
@@ -33,6 +33,7 @@
"jsdom": "^25.0.1",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.17",
"tailwindcss-animate": "1.0.7",
"typescript": "^5.6.3",
"typescript-eslint": "8.18.2",
"vite": "^5.4.11",
@@ -4782,6 +4783,16 @@
"node": ">=14.0.0"
}
},
"node_modules/tailwindcss-animate": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
"integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"tailwindcss": ">=3.0.0 || insiders"
}
},
"node_modules/thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+2 -1
View File
@@ -1,7 +1,7 @@
{
"name": "mindsift-frontend",
"private": true,
"version": "0.12.2",
"version": "0.13.0",
"license": "Unlicense",
"type": "module",
"scripts": {
@@ -37,6 +37,7 @@
"jsdom": "^25.0.1",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.17",
"tailwindcss-animate": "1.0.7",
"typescript": "^5.6.3",
"typescript-eslint": "8.18.2",
"vite": "^5.4.11",
+1 -1
View File
@@ -960,7 +960,7 @@ export const App: React.FC = () => {
</button>
{showProfileMenu && (
<div className="absolute right-0 top-full mt-1.5 w-64 panel-surface shadow-panel z-50 divide-y divide-border text-xs">
<div className="absolute right-0 top-full mt-1.5 w-64 panel-surface shadow-panel z-50 divide-y divide-border text-xs origin-top-right animate-in fade-in zoom-in-95 slide-in-from-top-1 duration-150">
{/* User Info Header */}
<div className="p-3 bg-canvas flex items-center gap-2.5">
<UserAvatar user={user} size="md" className="border border-border/70" />
@@ -941,7 +941,7 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
{showActionsMenu && (
<div
role="menu"
className="absolute right-0 top-full mt-1.5 w-60 rounded-card bg-panel border border-border shadow-lg p-1 z-30 text-xs"
className="absolute right-0 top-full mt-1.5 w-60 rounded-card bg-panel border border-border shadow-lg p-1 z-30 text-xs origin-top-right animate-in fade-in zoom-in-95 slide-in-from-top-1 duration-150"
>
{!inTrash && (
<button
@@ -187,7 +187,7 @@ export const JournalView: React.FC<JournalViewProps> = ({
</div>
{showCalendar && (
<div className="lg:hidden shrink-0 px-4 py-3 border-b border-border bg-sidebar">
<div className="lg:hidden shrink-0 px-4 py-3 border-b border-border bg-sidebar animate-in fade-in slide-in-from-top-2 duration-200">
<JournalCalendar
activeDate={activeDate}
entryDates={entryDates}
@@ -1658,7 +1658,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
: mobileShowDetail
? 'hidden lg:flex'
: 'flex'
} w-full lg:w-72 xl:w-80 shrink-0 flex-col bg-sidebar border-r border-border transition-all duration-200`
} w-full lg:w-72 xl:w-80 shrink-0 flex-col bg-sidebar border-r border-border transition-all duration-200 max-lg:animate-in max-lg:slide-in-from-left-1/4 max-lg:fade-in max-lg:duration-200`
}
>
{/* Sidebar header: search and the create buttons in one row */}
@@ -1925,7 +1925,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
<main
className={`${
subView !== 'editor' || mobileShowDetail || isSidebarCollapsed || focusMode ? 'flex' : 'hidden lg:flex'
} flex-1 flex-col min-w-0 h-full overflow-hidden bg-editor`}
} flex-1 flex-col min-w-0 h-full overflow-hidden bg-editor max-lg:animate-in max-lg:slide-in-from-right-1/3 max-lg:fade-in max-lg:duration-200`}
>
{subView === 'journal' && journalEnabled ? (
<JournalView
+9 -1
View File
@@ -12,7 +12,7 @@
@import './themes/theme-dark.css';
@import './themes/theme-light.css';
@import './themes/theme-terracotta.css';
@import './themes/theme-soft.css';
@import './themes/theme-terracotta-night.css';
@import './themes/theme-polarized.css';
@import './themes/theme-suri.css';
@@ -595,3 +595,11 @@ fieldset:disabled :is(button, input, select, textarea) {
@media (prefers-reduced-motion: reduce) {
.view-enter { animation: none; }
}
/* No sliding or zooming for people who asked their system for less motion */
@media (prefers-reduced-motion: reduce) {
.animate-in,
.animate-out {
animation: none !important;
}
}
+18
View File
@@ -65,3 +65,21 @@ describe('custom themes', () => {
expect(document.documentElement.classList.contains('dark')).toBe(true);
});
});
describe('built-in themes', () => {
beforeEach(() => localStorage.clear());
it('moves removed themes to their successors', () => {
localStorage.setItem('mindsift_active_theme', 'soft');
expect(getActiveTheme()).toBe('terracotta-night');
localStorage.setItem('mindsift_active_theme', 'high-contrast');
expect(getActiveTheme()).toBe('dark');
});
it('treats Terrakotta as a light theme and Terrakotta Nacht as dark', () => {
setActiveTheme('terracotta');
expect(document.documentElement.classList.contains('dark')).toBe(false);
setActiveTheme('terracotta-night');
expect(document.documentElement.classList.contains('dark')).toBe(true);
});
});
+13 -9
View File
@@ -58,14 +58,14 @@ export const AVAILABLE_THEMES: ThemeOption[] = [
isRounded: true,
},
{
id: 'soft',
name: 'Soft Slate (Abgerundet)',
subtitle: 'Schiefer-Blau mit weichen Radien (10px)',
file: 'src/themes/theme-soft.css',
previewBg: '#0f172a',
previewPanel: '#1e293b',
previewAccent: '#3b82f6',
previewText: '#f8fafc',
id: 'terracotta-night',
name: 'Terrakotta Nacht (Glut)',
subtitle: 'Espresso, Creme & glühende Terrakotta (12px)',
file: 'src/themes/theme-terracotta-night.css',
previewBg: '#17110d',
previewPanel: '#211913',
previewAccent: '#e8794a',
previewText: '#f3e8da',
isRounded: true,
},
{
@@ -188,8 +188,12 @@ function load(key: string): string | null {
}
}
// Removed themes and their successors
const RETIRED_THEMES: Record<string, ThemeId> = { soft: 'terracotta-night', 'high-contrast': 'dark' };
export function getActiveTheme(): ThemeId {
const saved = load(THEME_STORAGE_KEY);
const stored = load(THEME_STORAGE_KEY);
const saved = stored && RETIRED_THEMES[stored] ? RETIRED_THEMES[stored] : stored;
if (saved && AVAILABLE_THEMES.some((t) => t.id === saved)) return saved;
if (saved && isCustomThemeId(saved) && load(CUSTOM_CSS_CACHE_KEY)) return saved;
return 'dark';
-67
View File
@@ -1,67 +0,0 @@
/* ==========================================================================
MINDSIFT THEME: SOFT SLATE (Abgerundete Geometrie & Sanftes Schiefer-Blau)
Demonstriert, wie über die Rundungs-Variablen in einer einzigen Datei
das gesamte App-Layout auf abgerundete Ecken umschaltet.
========================================================================== */
:root[data-theme="soft"] {
/* --- 1. AKZENTFARBE --- */
--accent-primary: #3b82f6;
--accent-hover: #60a5fa;
--accent-dim: rgba(59, 130, 246, 0.15);
--accent-border: rgba(96, 165, 250, 0.40);
--text-on-accent: #ffffff;
/* --- 2. OBERFLÄCHEN & HINTERGRÜNDE --- */
--bg-app: #0f172a;
--bg-panel: #1e293b;
--bg-panel-elevated: #293548;
--bg-panel-hover: #334155;
--bg-input: #0f172a;
--bg-overlay: rgba(2, 6, 23, 0.72);
--bg-code: #090d16;
/* --- 3. TEXT & KONTRASTE --- */
--text-main: #f8fafc;
--text-muted: #94a3b8;
--text-faint: #64748b;
/* --- 4. RAHMEN, LINIEN & SCHATTEN --- */
--border-color: rgba(148, 163, 184, 0.16);
--border-subtle: rgba(148, 163, 184, 0.08);
--border-strong: rgba(148, 163, 184, 0.32);
--shadow-panel: 0 12px 32px rgba(2, 6, 23, 0.40);
--scrollbar-thumb: rgba(148, 163, 184, 0.22);
--scrollbar-thumb-hover: rgba(148, 163, 184, 0.38);
/* --- 5. STATUS- & SIGNALFARBEN --- */
--color-success: #10b981;
--bg-success: rgba(16, 185, 129, 0.14);
--border-success: rgba(16, 185, 129, 0.38);
--color-danger: #f43f5e;
--bg-danger: rgba(244, 63, 94, 0.14);
--border-danger: rgba(244, 63, 94, 0.38);
--color-warning: #f59e0b;
--bg-warning: rgba(245, 158, 11, 0.14);
--border-warning: rgba(245, 158, 11, 0.38);
/* --- 6. RUNDUNGEN (Weich abgerundete Ecken überall) --- */
--radius-card: 10px;
--radius-btn: 6px;
--radius-input: 6px;
--radius-checkbox: 4px;
--radius-pill: 9999px;
/* --- 7. CODE-SYNTAX-HIGHLIGHTING (VS Code Dark+) --- */
--code-keyword: #569cd6;
--code-string: #ce9178;
--code-number: #b5cea8;
--code-comment: #6a9955;
--code-property: #9cdcfe;
--code-function: #dcdcaa;
--code-type: #4ec9b0;
--code-punctuation: #d4d4d4;
--code-variable: #9cdcfe;
}
@@ -0,0 +1,69 @@
/* ==========================================================================
MINDSIFT THEME: TERRAKOTTA NACHT (Espresso & Glut)
Das dunkle Gegenstück zu Terrakotta: Espresso-Braun statt Schwarz,
warme Creme-Schrift, glühender Terrakotta-Akzent, Salbeigrün, weiche Ecken.
========================================================================== */
:root[data-theme="terracotta-night"] {
/* --- 1. AKZENTFARBE (Glühende Terrakotta) --- */
--accent-primary: #e8794a;
--accent-hover: #f39669;
--accent-dim: rgba(232, 121, 74, 0.15);
--accent-border: rgba(232, 121, 74, 0.40);
--text-on-accent: #1c1410;
/* --- 2. OBERFLÄCHEN & HINTERGRÜNDE (Espresso, Mokka, Leder) --- */
--bg-app: #17110d;
--bg-panel: #211913;
--bg-panel-elevated: #2c2219;
--bg-panel-hover: #382b20;
--bg-input: #1a130f;
--bg-overlay: rgba(10, 6, 4, 0.72);
--bg-code: #120d0a;
--bg-editor: #1c1510;
--bg-sidebar: #17110d;
/* --- 3. TEXT & KONTRASTE (Creme auf Espresso) --- */
--text-main: #f3e8da;
--text-muted: #c4b19c;
--text-faint: #8d7a66;
/* --- 4. RAHMEN, LINIEN & SCHATTEN --- */
--border-color: rgba(243, 214, 184, 0.12);
--border-subtle: rgba(243, 214, 184, 0.06);
--border-strong: rgba(243, 214, 184, 0.24);
--shadow-panel: 0 12px 32px rgba(5, 3, 2, 0.55);
--scrollbar-thumb: rgba(232, 121, 74, 0.22);
--scrollbar-thumb-hover: rgba(232, 121, 74, 0.38);
/* --- 5. STATUS- & SIGNALFARBEN (Salbei, Ziegel, Honig) --- */
--color-success: #8fbf8a;
--bg-success: rgba(143, 191, 138, 0.14);
--border-success: rgba(143, 191, 138, 0.36);
--color-danger: #f07a6a;
--bg-danger: rgba(240, 122, 106, 0.14);
--border-danger: rgba(240, 122, 106, 0.36);
--color-warning: #e6b450;
--bg-warning: rgba(230, 180, 80, 0.14);
--border-warning: rgba(230, 180, 80, 0.36);
/* --- 6. RUNDUNGEN (Weich wie Papierkarten) --- */
--radius-card: 12px;
--radius-btn: 8px;
--radius-input: 8px;
--radius-checkbox: 4px;
--radius-pill: 9999px;
/* --- 7. CODE-SYNTAX-HIGHLIGHTING (warme Erdtöne auf Espresso) --- */
--code-keyword: #f39669;
--code-string: #a9cf9c;
--code-number: #e6b450;
--code-comment: #8d7a66;
--code-property: #f0c9a4;
--code-function: #d8b4fe;
--code-type: #7fc7b8;
--code-punctuation: #c4b19c;
--code-variable: #f0c9a4;
}
+3 -1
View File
@@ -1,3 +1,4 @@
import animate from 'tailwindcss-animate';
// Theme colours are CSS variables, so Tailwind cannot apply opacity modifiers (bg-accent/15) by itself.
// v() mixes the variable with transparent for a modifier; plain classes keep the bare variable, so only
// the tints depend on color-mix() support.
@@ -98,5 +99,6 @@ export default {
},
},
},
plugins: [],
// animate-in / fade-in / slide-in-from-* / zoom-in-* used by menus, sheets and dialogs
plugins: [animate],
};