diff --git a/LOTUS_BUGS.md b/LOTUS_BUGS.md index 5f6dcc65b..0b4b8d1f4 100644 --- a/LOTUS_BUGS.md +++ b/LOTUS_BUGS.md @@ -318,13 +318,13 @@ This document tracks identified bugs, edge cases, and architectural discrepancie | N11 | AvatarDecoration | `AvatarDecoration.tsx` | 5 / 38–41 | Fixed 8px inset on all sides regardless of avatar size — at folds size `"200"` (~32px) the decoration bleeds 50% of the avatar diameter, clipping against `overflow: hidden` parent containers in member lists. **Inset issue still OPEN.** _Related regression fixed in `useAvatarDecoration.ts`_: the decoration fetch cached **all** failures (including transient 429/5xx) as "no decoration" permanently for the session, so a single rate-limited burst (member list / timeline mount many avatars at once) would make decorations vanish until a full reload. Now only a genuine 404 is cached; transient errors retry on the next mount. | Folds `Avatar` and `PresenceRingAvatar` do not emit overflow outside their bounding box | | N12 | MediaGallery Drawer | `MediaGallery.tsx` | 651–661 | Drawer uses `position: 'fixed'` with hardcoded `width: '320px'` as inline styles on a `` — **FIXED**: moved positioning/width into co-located `MediaGallery.css.ts` using `toRem(320)` + a `max-width: 750px` full-screen media query (mirrors `MembersDrawer`); border/header now use `config.borderWidth`/`config.space` tokens. Added Escape-to-close on the panel (previously only the lightbox handled Escape). **Full chrome redesign (round 2)** to match native conventions: panel + header switched from `Surface` to `Background` variant (matching `MembersDrawer`/Saved Messages); header now `Text size="H4"` + plain close `IconButton` (dropped the bespoke tooltip-wrapped button); tabs moved to a bordered toolbar strip with the `variant={active?'Primary':'Secondary'} fill={active?'Solid':'Soft'}` pattern from `PolicyListViewer` and now show per-tab counts; the centered "lines + label" month divider replaced with a left-aligned group label (Cinny group-label pattern); thumbnail tiles moved hover/focus styling to CSS `:hover`/`:focus-visible` (no JS hover state) and into `MediaGallery.css.ts`; file rows + grid tokenized. **Docking fix (round 3)** — the core of the finding: the gallery was a `position: fixed` overlay floating over the timeline, mounted from `RoomViewHeader`. It is now a **docked flex sibling** in the room layout row, exactly like `MembersDrawer`: open state lifted to a `mediaGalleryAtom` (mirrors `bookmarksPanelAtom`), rendered in `Room.tsx` with a vertical `Line` separator on desktop and `key={room.roomId}` to reset per room; the CSS is static-width on desktop and only `position: fixed; inset: 0` full-screen on mobile (identical strategy to `MembersDrawer.css`). It now shares the row with the timeline instead of overlapping it. | `MembersDrawer` uses a vanilla-extract class with `width: toRem(266)` and is placed by the layout system, not `position: fixed`. 54px width discrepancy also breaks visual rhythm if both panels could be open | | N13 | ScheduledMessagesTray | `ScheduledMessagesTray.tsx` | 108–126 | Collapsible tray header is `` with `cursor: 'pointer'` inline style and no folds variant — no hover state, no focus ring — **FIXED**: replaced with folds `` (spinner while loading) replacing the passive text | `RoomActivityLog.tsx:425` and `MessageSearch.tsx:129` both render a folds `` to fetch the next page | | N66 | DateRangeButton — Native `` | `SearchFilters.tsx` | 558–589 | "From" and "To" date fields are raw `` with inline style overrides including `fontSize: '0.82rem'` — **FIXED**: replaced both with folds ``; removed now-unused `color` import | `SelectRoomButton` (same file, line 224) and `SelectSenderButton` (line 424) both use folds ``; the date inputs are the only native browser inputs in the search filter row | | N67 | SeasonalEffect / NightLight Z-Index Order | `SeasonalEffect.tsx` / `App.tsx` | 759 / 62–77 | `SeasonalEffect` mounts at `zIndex: 9999`; `NightLightOverlay` at `zIndex: 9998`. Seasonal particles render **above** Night Light so they are never tinted. `SeasonalEffect` also shares `z-index: 9999` with the skip-to-content link in `ClientLayout.tsx` — **FIXED**: lowered `SeasonalEffect` overlay to `zIndex: 9997` (below Night Light at 9998 and modals at 9999), so Night Light now tints the particles and dialogs are never obscured | Expected UX: Night Light tints all visible content including effects; requires either a higher Night Light z-index or a lower SeasonalEffect z-index | -| N68 | Syntax Highlighting — `--lt-accent-*` Vars in Non-TDS Themes | `syntaxHighlight.ts` | 313–323 | `tokenStyle()` returns `var(--lt-accent-cyan/green/orange/purple, hardcoded-fallback)` — `--lt-*` vars only exist in TDS mode; fallbacks are Monokai dark colors that have poor contrast on light themes and no relationship to the existing `--prism-*` variables in `ReactPrism.css` | `ReactPrism.css` uses `--prism-keyword`, `--prism-selector` etc. which switch correctly between light and dark palettes; syntax highlighting should use the same variable family | +| N68 | Syntax Highlighting — `--lt-accent-*` Vars in Non-TDS Themes | `syntaxHighlight.ts` | 313–323 | `tokenStyle()` returns `var(--lt-accent-cyan/green/orange/purple, hardcoded-fallback)` — `--lt-*` vars only exist in TDS mode; fallbacks are Monokai dark colors that have poor contrast on light themes and no relationship to the existing `--prism-*` variables in `ReactPrism.css` — **FIXED**: `tokenStyle()` now maps to the `--prism-*` family (keyword/selector/boolean/atrule/comment) which has proper light/dark/TDS palettes; comment uses `--prism-comment` instead of an opacity hack | `ReactPrism.css` uses `--prism-keyword`, `--prism-selector` etc. which switch correctly between light and dark palettes; syntax highlighting should use the same variable family | | N69 | Mention Highlight — `` Instead of `HexColorPickerPopOut` | `General.tsx` | 644–675 | Raw `` with hardcoded pixel dimensions; OS-native color picker chrome renders completely differently from the rest of settings UI | `PowersEditor.tsx:125–143` establishes `}>` as the codebase's color-picking pattern; Reset button should be ` + + {preset.emoji} + + {preset.label} + + + {preset.description} + + + ))} diff --git a/src/app/utils/syntaxHighlight.ts b/src/app/utils/syntaxHighlight.ts index ee7d82e9e..b983ca61a 100644 --- a/src/app/utils/syntaxHighlight.ts +++ b/src/app/utils/syntaxHighlight.ts @@ -306,19 +306,26 @@ export function tokenize(code: string, lang: string): SyntaxToken[] { // ── Inline style helpers ──────────────────────────────────────────────────── -/** Returns the React inline-style object for a given SyntaxToken type. */ +/** + * Returns the React inline-style object for a given SyntaxToken type. + * + * Uses the `--prism-*` variable family (defined in `ReactPrism.css`), which has + * proper light / dark / TDS palettes — unlike the raw `--lt-accent-*` vars, + * which only exist in TDS mode and otherwise fall back to dark-only Monokai + * colors with poor contrast on light themes. + */ export function tokenStyle(type: SyntaxToken['type']): CSSProperties { switch (type) { case 'kw': - return { color: 'var(--lt-accent-cyan, #66d9ef)' }; + return { color: 'var(--prism-keyword)' }; case 'str': - return { color: 'var(--lt-accent-green, #a6e22e)' }; + return { color: 'var(--prism-selector)' }; case 'num': - return { color: 'var(--lt-accent-orange, #fd971f)' }; + return { color: 'var(--prism-boolean)' }; case 'cmt': - return { opacity: 0.5, fontStyle: 'italic' as const }; + return { color: 'var(--prism-comment)', fontStyle: 'italic' as const }; case 'fn': - return { color: 'var(--lt-accent-purple, #ae81ff)' }; + return { color: 'var(--prism-atrule)' }; default: return {}; }