Replace the single-line tooltip with the two-line pattern used elsewhere
in the icon picker (color picker recents lane, contrast indicator):
Reset to this default
Replaces 4 custom icons
The previous copy ("Clear N customized icons — these rows will inherit
from this default again") repeated the button label, used an em dash,
and tied the framing to table-row terminology that doesn't translate
to other views. The new copy puts the outcome verb on the bold line
("Reset to this default", matching the codebase's :keymap/reset-to-default
key) and uses the muted line for scope ("Replaces N custom icons"),
keeping the subject on the icons themselves so it reads cleanly across
table, list, and gallery views.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Three coordinated fixes to align the bracket popover and property-value
combobox with CMD-K's existing single-icon pattern:
1. De-dup: drop the inline `block-title-with-icon` icon prepend on both
surfaces; titles render alone. Previously every result row that had a
committed `:logseq.property/icon` rendered the icon twice — once in
the leading slot via `get-node-icon-cp` and again inlined into the
title. CMD-K's `list_item.cljs:114-122` already documented this
exact de-dup; the other two surfaces never got it.
2. Slot: pin the icon column to a fixed 20×20 box
(`w-5 h-5 flex items-center justify-center shrink-0`) so all titles
start at the same x-axis regardless of whether the row's icon is a
14px tabler glyph or a 20px avatar. CMD-K's
`list_item.cljs:98-109` is the reference pattern.
3. Guard fix in property/value.cljs: the leading-icon `when-not` used
to suppress for `:logseq.property/classes`-having properties
(Attendees, Collaborators, etc.) because the old inline title path
prepended an icon. With (1) removing that path, the suppression now
leaves the slot empty. Narrow the guard to just `:class`/`:property`
property-types (which are intentionally iconless — the entities
being picked ARE the classes).
CMD-K is untouched; it was already correct.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two related polish passes on the inline icon slot:
- Emoji glyphs in page-ref and left-sidebar contexts now render at
font-size 16 (was 20). emoji-mart's <em-emoji size="N"> only sets
font-size on its inner spans, and native emoji fonts produce a
bounding box ~32% taller than font-size — so size=20 visually
rendered at ~26.5px and bled into the row below in the left
sidebar. Clamping to 16px lands the glyph at ~21px, fitting the
20x20 slot. Both `em-emoji` and `em-emoji span` selectors are
load-bearing because emoji-mart's inline font-size on the inner
span wins over !important on the ancestor — same pattern as the
customize-band compact state at icon.css:2214.
- Pull all inline page-ref icons up 1px via translateY. vertical-align:
middle centers icons on x-height/2, but readers compare against
cap-height/2 (~2px higher in Inter at body size), so the
geometric center reads as a sag. translateY decouples optical
correction from layout flow.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
On a fresh session, page entities carry icon metadata (asset-uuid)
before their referenced asset blocks have transacted into the
main-thread DataScript DB. The render bodies of avatar-image-cp /
image-icon-cp were gating the loaded blob URL on
(db/entity [:block/uuid uuid]) — which returned nil during this
hydration window, flipping asset-missing? true and masking a working
URL with the image-error / initials fallback. The workaround was to
visit #Asset, whose table query hydrated the blocks via
db.async/<get-block; once the block landed, asset-missing? cleared
and the already-loaded URL became visible everywhere.
Drop the entity-presence gate. Render is now driven purely by load
outcome (URL set → image, *error → fallback, else → placeholder).
Retraction is handled in :did-update by watching the per-tx
:deleted-ids set: when the asset's uuid appears there, *url is
cleared and a fresh load is fired; the outliner pipeline has
deleted the file, so the load fails into *error and the fallback
renders.
The Avatar :key now toggles on URL presence (was asset-missing?)
to keep Radix's image-loading state machine fresh across
load/clear transitions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Tabler/text/emoji glyphs and avatar/image icons all share the same
20x20 visual slot in [[page-refs]] now, matching the left-sidebar's
.page-icon dimensions. Photo icons (avatar, image) fill the slot;
non-photo glyphs render at 16px centered with 2px breathing room.
Drop the legacy .page-ref svg { width: 16px } clamp that overrode
the per-icon size attributes, drop the 1lh height/line-height clamp
on the wrappers that resolved to 16px and capped emoji glyphs, and
opt the icon wrappers out of the .block-content-wrapper svg { 18px }
sledgehammer. The cljs side simply defaults inline icon-size to 20
(was nil) and lets heading contexts override via heading-icon-size.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two related fixes converging on the same root issue: render-time JS
reads of CSS variables (via `colors/read-bg-var` / `getComputedStyle`)
produce hex values that go stale or out of contrast across themes.
1) Global theme-toggle reactivity (theme.cljs)
The earlier pointwise `(state/sub :ui/theme)` subscriptions in
`avatar-image-cp`, `get-node-icon-cp`, and `icon-picker-trigger-icon`
covered the high-traffic surfaces but left picker-internal tiles
and future icon-rendering components vulnerable to the same
staleness. Pivot to one `(ui-handler/re-render-root!)` call inside
theme.cljs's existing data-theme `use-effect!`. Fires after the
DOM attribute is stamped on <html>, marks every reactive component
dirty, and lets the next reconciliation re-sample fresh CSS
variables. Pattern-consistent with the language-change handler at
settings.cljs:298. Theme toggle is a rare user-initiated action;
the one-frame reconciliation cost is imperceptible. Removes the
three pointwise subs as redundant.
2) Text icon contrast (icon.cljs text branch)
The text-icon SVG previously baked the raw user-picked hex into
`:fill`, which won the cascade over the surrounding `color?`
wrapper's contrast-adjusted `:style {:color …}`. Result: a
`#000000` text-icon pick rendered as invisible black on a dark
theme even though the wrapper had computed a readable shade right
above it in the tree. Same `colors/adjust-for-contrast` path
tabler icons have always used — they inherit via
`stroke="currentColor"`; text icons just need to opt into the
same inheritance via `:fill "currentColor"`. One-line behavioral
change; the `text-color` let-binding is no longer needed.
Net diff: theme.cljs +12 / icon.cljs -20.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Extends the previous theme-toggle fix to cover the page-title render
path. `block.cljs:3223` (page-title) routes through `icon-picker` →
`icon-picker-trigger-icon` → `(icon …)`, bypassing `get-node-icon-cp`
entirely. The earlier `(state/sub :ui/theme)` on `get-node-icon-cp`
covered the sidebar, cmdk, breadcrumb, and inline page references,
but the page-title's reactive boundary is `icon-picker-trigger-icon`
— which only subscribed to `:ui/icon-hover-preview`, not theme.
Result: page-title avatars with user-picked custom hex colors (which
get contrast-adjusted differently per theme via `adjust-for-contrast`)
stayed frozen with the previous theme's tone until something else
triggered a re-render.
One-line patch: add `_theme (state/sub :ui/theme)` to the trigger's
let block. The subscribed value is discarded; the subscription is
just there to tick Rum's dependency graph when the user hits `t t`.
Known follow-up: same pattern exists in other less-trafficked render
paths (avatar-cp picker-tile, custom-tab-cp preview, asset-picker
customize-band, and a handful of external callers in property/value,
property, property/config, views). They'll exhibit the same staleness
but only when visible — most are picker-internal (rare during theme
toggle). Best addressed in a focused refactor that extracts the
avatar-only and colored-icon branches of `icon` into reactive
subcomponents, killing the bug class at the right abstraction layer.
Filed for after this PR lands.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The avatar fallback hex (background + text) is computed in JS by
`avatar-fallback-style` → `colors/read-bg-var` → `getComputedStyle`,
so its output is a snapshot of the current theme's CSS variables at
render time. The result is written into the element's inline style.
On `tt` (theme toggle) the snapshot stayed frozen until something
unrelated triggered a re-render, leaving avatars carrying the wrong
theme's tone — too bright in dark mode, too dark in light mode.
Two coordinated changes:
1. state/set-theme-mode! now stamps `data-theme` + body classes
synchronously *before* mutating `:ui/theme`. The previous flow
left the DOM update inside theme.cljs's `use-effect!`, which
fires AFTER React's render commit — so subscribers re-rendering
on the state change still read the old theme's CSS vars. The
theme.cljs effect remains as an idempotent safety net plus the
side effects (plugin hook, custom-theme application).
2. `avatar-image-cp` and `get-node-icon-cp` subscribe to `:ui/theme`.
The subscribed value is discarded — the subscription's job is to
tick Rum's dependency graph so the component re-renders on toggle
and recomputes `avatar-fallback-style` against the (now fresh)
CSS variables. Combined with the synchronous DOM update above,
the read-bg-var snapshot is correct on the first render after
toggle, no second tick required.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Resting state restructured for clearer affordance + better
discoverability:
- Avatar tile demoted from <button> to <div aria-hidden> — it's a
live preview, not a control. Removes the redundant second toggle.
- Banner demoted from <button> to <div aria-hidden>. The chevron-down
is gone — it was miscueing as a <select>-style dropdown, and the
morph-in-place transition meant it never lived long enough to read
as a disclosure rotation anyway.
- New invisible <button.cb-row-trigger> overlays the resting row
edge-to-edge (covering the zone's 18px padding) so the entire
surface is one accessible click target. Mounted only when collapsed
(`when-not expanded?`) — when expanded, the dropdown chips inside
`.cb-rows` are unparented so there's no nested-interactive risk.
- aria-label composes scope + descriptor + verb so screen readers
announce the current state on focus ("Custom · Image, circle.
Customize avatar."). aria-controls links to the rows panel id;
panel gets role="region" + aria-label for the disclosure pair.
- Right-side "Edit" text label replaces the chevron — muted gray-09
at rest, brightens to gray-12 when the row is hovered.
Zone background swapped to solid theme tokens (no alpha veil):
- Rest: var(--lx-gray-01) — most recessed surface in both themes
- Hover: var(--lx-gray-03) — two-step lift via :has(.cb-row-trigger:hover)
- 120ms cubic-bezier(0.32, 0.72, 0, 1) on background-color only
Solid colors compose more reliably across light + dark themes than
stacked alphas, and avoid the content-clipping issue that would
happen if the trigger overlay carried a near-opaque background of
its own. The :has() pattern means the hover paints on the same
element that already backs the content, so the avatar / banner-text
/ Edit label naturally show through.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Asset deletion (three independent failures stacked):
- Unlink file on asset-block retract via the existing <unlink-asset
helper at handler/assets.cljs (modules/outliner/pipeline.cljs:74-80).
The block was commented out; deleted-assets was computed but never
consumed, so files leaked indefinitely.
- Reactive existence check in image-icon-cp / avatar-image-cp via
state/sub :db/latest-transacted-entity-uuids. model/sub-block can't
drive this — worker/react.cljs:63-67 calls (d/entity db-after id),
which returns nil for retracted entities, so [::block id] is never
emitted in affected-keys and subscriptions never fire on deletion.
- Force-remount Avatar root via :key on asset-missing? toggle. Radix's
Avatar primitive tracks image-loading status in context; once
AvatarImage reported 'loaded', the status sticks even after the image
unmounts, so AvatarFallback stays hidden.
PR-review cleanup (no behavior change):
- Strip 17+ [DEBUG ...] console statements across icon, block, views,
two editor handlers, and assets.
- Close content.cljs preview gap: pass :preview-target-db-id +
:property to icon-search so the block bullet observes hover preview
consistently with every other surface.
- Scope-correct close-fallback-menu! — use dissoc-icon-preview-field!
instead of unconditional state/set-state! nil.
- Delete dead code: heal-dangling-asset-icon (raced lazy hydrate),
asset-uuid->entity, rgb-string->hex, name->hex (named + css),
format-pairs.
- Hoist icon-grid-cols / custom-tab-cols magic numbers (9 sites).
- Search inputs: add :type "search" and :aria-label (both picker +
asset-picker).
- Replace hardcoded #6B7280 with (colors/variable :gray :09).
- Reconcile recents-cap doc drift in storage.cljc + recents-lane
docstring (cap lives in handler/icon-color/max-recents).
- Remove orphan-asset cleanup from outliner/core save-block-inner. Root
cause (migration 65.27's :url ref-type) is fixed by 65.28/65.29; all
asset writers are atomic (save-image-asset!, new-asset-block,
build-new-asset), and the cleanup ran on every save with a silent-
retract failure mode.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`get-node-icon` (icon.cljs:783) references `derive-abbreviated`,
defined later at line 2235 — added to the existing `declare` for
the other derive helpers to silence the `:undeclared-var` warning.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ux): incorrect reaction for the order list sibling blocks
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix: lint
* chore(test): add tests for order list type and sibling block interactions
* fix: refresh nested ordered lists
* fix: split affected query keys helper
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
* feat(editor): add support for dollar sign in autopair feature
* fix(editor): handle dollar autopair for markdown math
* feat(help): add inline math example
* fix(editor): double dollar autopair behavior
1. Derive the effective heading level consistently for auto headings, and reuse it for block icons, page-ref icons, and heading layout attributes.
2. Align heading bullets and page-ref icons so h3-h6 and auto heading changes no longer shift vertically.
3. Show the active heading and background color in the single-block context menu.