Saving these notes.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# Aether Journals UI Update (2026)
|
||||
|
||||
> **Status:** 🚧 Stuck on Phase 4 (Security/Encryption Blockers)
|
||||
> **Last Updated:** 2026-01-14
|
||||
> **Status:** 🚧 Phase 4 Active (Security/Encryption Blockers remain; Style pass complete)
|
||||
> **Last Updated:** 2026-03-06
|
||||
> **Primary Agent:** Frontend SvelteKit Agent
|
||||
|
||||
## 1. Project Overview
|
||||
@@ -73,6 +73,10 @@ This document outlines the modernization of the Journals module UI in the Svelte
|
||||
- [x] Extract decryption workflow to non-reactive helper.
|
||||
- [x] **Standardize Configuration Modals:** Refactored Module, Journal, and Entry configuration into a unified tabbed UI.
|
||||
- [x] **RESOLVED:** Decryption workflow stability (Fixed via dependency isolation).
|
||||
- [x] **Style Standardization (2026-03-06):** Full Skeleton v4 `preset-*` class pass across all 17 journal components. See style token table in Lessons Learned below.
|
||||
- [x] **Dark mode fixes:** Entry content hover, journal view section/description background and text colors.
|
||||
- [x] **Modal close button:** All 3 config modals use `dismissable={false}` + explicit `<X>` button in header snippet for correct right-aligned placement.
|
||||
- [x] **Global select padding:** Added `padding-inline: 0.5rem` to `@layer base` in `app.css` (safe — utility `px-*` classes override it where intentional).
|
||||
- [ ] Solidify E2EE passcode system for Journals and Entries.
|
||||
- [ ] Audit encryption flow for Quick Added and Imported entries.
|
||||
- [ ] Integrate Outbound Email sharing.
|
||||
@@ -84,23 +88,58 @@ This document outlines the modernization of the Journals module UI in the Svelte
|
||||
During the implementation of the Privacy/Decryption toggle and the new Configuration Modals, we encountered critical browser hangs caused by infinite reactivity loops. Here is how we resolved them:
|
||||
|
||||
### 1. Rigorous Dependency Isolation (`untrack`)
|
||||
Svelte 5 runes (`$effect`, `$derived`) automatically track **every** reactive variable read inside them.
|
||||
Svelte 5 runes (`$effect`, `$derived`) automatically track **every** reactive variable read inside them.
|
||||
* **The Problem:** An effect would read `save_status` or `tmp_entry_obj.content` to decide if it should sync, but the act of syncing would update those same variables, re-triggering the effect.
|
||||
* **The Fix:** Wrap any "check-only" state or store reads in `untrack(() => ... )`. This allows the effect to use the value without becoming a dependency of it. This is **CRITICAL** when initializing local state from props inside an effect.
|
||||
|
||||
### 2. Standardized Modal UI ("Aether Orange")
|
||||
We have established a unified design language for configuration interfaces:
|
||||
* **Header/Footer:** Use `bg-orange-100 dark:bg-orange-900` with consistent borders.
|
||||
* **Tabs:** Center-aligned tabbed navigation using Skeleton UI `btn` and `variant-filled-primary` / `variant-soft-surface`.
|
||||
### 2. Standardized Modal UI ("Aether Orange") & Style Token Conventions
|
||||
We have established a unified design language for configuration interfaces and all Journals UI. **Use these as the module template.**
|
||||
|
||||
#### Modal Chrome
|
||||
* **Header/Footer:** `bg-orange-100 dark:bg-orange-900` with consistent orange borders.
|
||||
* **Close button:** Always use `dismissable={false}` on the `<Modal>` and add an explicit `<button>` with `<X>` inside the `{#snippet header()}` so placement is fully in our control. The `flex-1` class on the `<h3>` pushes it right.
|
||||
* **Tabs:** Center-aligned `btn btn-sm` with `preset-filled-primary` (active) / `preset-tonal-surface` (inactive).
|
||||
* **Icons:** Every tab and primary action should have a Lucide icon for better scannability.
|
||||
* **Explicit Persistence:** All configuration modals must follow an "Edit working copy -> Save Changes" pattern to prevent accidental store/API churn.
|
||||
* **Explicit Persistence:** Follow "Edit working copy → Save Changes" pattern to prevent accidental store/API churn.
|
||||
|
||||
#### Skeleton v4 Style Token Reference (Journals = canonical example)
|
||||
| Intent | Class |
|
||||
|---|---|
|
||||
| Primary CTA (save, create, open) | `btn preset-filled-primary` |
|
||||
| Neutral / cancel / close | `btn preset-tonal-surface` |
|
||||
| Secondary action | `btn preset-tonal-secondary` |
|
||||
| Success (confirmed save) | `btn preset-filled-success` |
|
||||
| Warning (caution action) | `btn preset-tonal-warning hover:preset-filled-warning-500` |
|
||||
| Error / danger (delete, force reset) | `btn preset-tonal-error hover:preset-filled-error-500` |
|
||||
| Active tab | `preset-filled-primary` |
|
||||
| Inactive tab | `preset-tonal-surface` |
|
||||
| Icon button | `btn-icon btn-icon-sm preset-tonal-surface` |
|
||||
| Input (base) | `input` |
|
||||
| Input (small) | `input input-sm` |
|
||||
| Select (base) | `select` |
|
||||
| Select (small) | `select select-sm` |
|
||||
| Textarea | `textarea` |
|
||||
| Badge (info/neutral) | `badge preset-tonal-surface` |
|
||||
| Badge (success) | `badge preset-tonal-success` |
|
||||
| Badge (error) | `badge preset-tonal-error` |
|
||||
|
||||
#### Removed Patterns (never use)
|
||||
- `variant-filled-*`, `variant-soft-*`, `variant-ghost-*`, `variant-ringed-*` — Skeleton v2, removed
|
||||
- `variant-form-material` — Skeleton v2, removed from all inputs/selects/textareas
|
||||
- `input-bordered` — non-standard, removed
|
||||
- DaisyUI `modal` / `modal-box` / `modal-action` wrapper divs inside Flowbite `<Modal>` — removed
|
||||
|
||||
#### Dark Mode Rules
|
||||
- Any `bg-{color}-100` dynamic background **must** have a `dark:bg-gray-800` (or similar) override — light shades are unreadable in dark mode.
|
||||
- Hover states on content areas need both light and dark variants: `hover:bg-blue-100 dark:hover:bg-blue-950`.
|
||||
- Text locked to `dark:text-gray-900` is almost always wrong — use `dark:text-gray-100`.
|
||||
|
||||
### 3. Dexie LiveQuery Subscriptions
|
||||
* **The Problem:** Accessing `liveQuery` observables directly in templates results in `[object Object]` or `undefined` property errors.
|
||||
* **The Mandate:** ALWAYS use the `$` prefix (e.g. `$lq__obj`) when passing or using data from a Dexie `liveQuery`.
|
||||
|
||||
### 4. Manual Deep Copying vs. Proxies
|
||||
Svelte 5 state is backed by Proxies.
|
||||
Svelte 5 state is backed by Proxies.
|
||||
* **The Problem:** Using `JSON.parse(JSON.stringify(proxy))` can sometimes trigger unexpected behavior or loops when used inside a reactive context.
|
||||
* **The Fix:** Implement a manual `deep_copy` helper or selective property assignment when syncing "Original" vs "Temporary" state. This ensures `orig_entry_obj` is a plain JS object, making the `has_unsaved_changes` check stable.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user