CI's spell-check (crate-ci/typos) flagged two patterns introduced by
this PR:
- `daa` inside hex color values (`e6daa6` beige, `daa520` goldenrod)
in colors/named.cljs and colors/css.cljs. Pure tokenizer artifact;
the hex codes are W3C canonical and can't be renamed.
- `unparseable` in 3 docstrings + 1 comment of colors.cljs. Both
spellings are valid English; typos prefers `unparsable`.
Fix surgically rather than growing the global word allowlist: add the
two color-data files to `extend-exclude` (they're pure lookup tables
with no prose to spell-check anyway), and rename `unparseable` in
colors.cljs to `unparsable`. No code semantics changed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The icon-picker's search-input had a `:focus-within` rule lifting
`.ls-icon-search` from opacity-50 → opacity-75 — the active-state
signal that replaces a focus ring. The asset-picker's
`.asset-picker-search` block mirrored the rest of the chrome but
omitted this rule, so its search input gave no visual feedback when
focused. Comment in the asset-picker block already documents the
lift as the intended active-state signal — this aligns code with
that contract.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The asset-picker's segmented control toggling between Avatar and Image
modes carried a hardcoded English `:aria-label "Icon rendering mode"`.
Every other aria-label in this file goes through `(t :icon.*)`; this
one was missed. The two option labels were already translated
(`:icon.asset-mode/avatar` / `:icon.asset-mode/image`) — only the
group label was bare.
Add `:icon.asset-mode/picker-aria-label "Asset type"` (en) / "资产类型"
(zh-cn), mirroring the existing `:icon.color/picker-aria-label`
convention.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Both properties were declared in property.cljs and registered via
migrations (65.31, 65.32) but had zero consumers anywhere in the
source. They slipped in from the prep commit (e782310e57) when the
unified-picker scope was reconstructed, intended for follow-up PRs
that have not yet landed. Built-ins can never be cleanly removed once
shipped, so cleaning before the PR goes out.
- Remove `:logseq.property/wikidata-id` declaration + 65.31 migration.
- Remove `:logseq.property/property-key-width` declaration + 65.32 migration.
- Renumber remaining migrations: old 65.33→new 65.31 (asset properties),
old 65.34→new 65.32 (fix-asset-source-url-property-type),
old 65.35→new 65.33 (fix-asset-source-url-schema-lock). Docstring
comments at migrate.cljs:96/106 updated to reference the new numbers.
- Bump schema.cljs version 65.35 → 65.33.
Local dev DBs that have already migrated past 65.30 need to be wiped;
Logseq's migration runner refuses to load DBs with schema-version
higher than the code expects.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Three manual conflict resolutions, applied via Python to bypass the
auto-formatter (which corrupts cond-> map literals when invoked on
files containing conflict markers):
- block.cljs: take master's nil-safe `(when ext ...)` guard on the
electron asset-ref path and master's `:class "ls-block-content-indent"`
in place of the inline `:style {:padding-left ...}`. Our prior
20-default icon-size fix is preserved (auto-merged cleanly).
- cmdk/core.cljs: take master's `:block.temp/unique-title` worker-
precomputed field for `page-item` and `block-item`; drop our dead
`:ignore-current-icon?` opt.
- content.cljs: take master's new "Copy block URL" + "Show asset in
folder" dropdown items (the `(when (util/electron?))` block was
refactored to use `get-logseq-web-block-url` + `current-graph-id`).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Commit 74bf1a089c set the inline page-ref `icon-size` default to 20
(non-heading contexts) so refs match the sidebar Recent / right
sidebar tabs as the canonical "this is a page" baseline. The May-20
merge conflict resolution in e3d9c54651 silently took master's form
that lets `icon-size` fall through to `heading-icon-size`'s 14
default, dropping inline refs to 14×14. The matching CSS (the 20×20
slot, 16×16 inner SVG clamp, translateY(-1px) optical lift, and
emoji font-size clamp from 091c6b347d) survived the merge intact,
so this is a single-line cljs restoration.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Three separator declarations used `var(--lx-gray-04)` with no
fallback. In OG/OG-turquoise themes that variable resolves to a tone
nearly identical to the popover surface, so the vertical rule
between Default/Custom column and preset grid, the border under the
hex input, and the pane's top border on open all read as invisible.
Switch to the canonical
`var(--lx-gray-05, var(--ls-border-color, var(--rx-gray-05)))` chain
already used by every other separator in icon.css.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two animation glitches in `.avatar-customize-zone`:
1. Collapse ghosting: `.cb-rows` carried an 80ms transition delay on
its base rule, so on collapse the rows sat at opacity 1 for 80ms
while `.cb-banner` faded back in — the two layers overlapped for
a ~120ms window. Move the delay onto the `[data-expanded="true"]`
rule so it fires only on expand (banner exits → rows wait → rows
enter); collapse starts the rows fade-out immediately at t=0.
2. Avatar glyph step-change: the JS renderer bakes the expanded
font-size (22px) / icon size (30px) / emoji size (30px) inline on
the avatar fallback. The compact-state CSS used
`:not([data-expanded]) … { font-size: 10px !important }` to snap
to compact in resting. That snap meant at t=0 of expand the font
jumped 10→22px while the container took 200ms to grow — "DD"
rendered at 22px inside a ~25px circle, clipping and wrapping to
two lines. Drive font/icon/emoji size via CSS variables
(`--avatar-font-size`, `--avatar-icon-size`, `--avatar-emoji-size`)
alongside `--avatar-size`, and add matching 200ms transitions so
all four interpolate in lockstep.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bring all three picker chrome surfaces (`.asset-picker-tabrow`,
`.text-picker-back`, `.avatar-customize-zone`) to symmetric 12px
horizontal padding so the back-chevron, trash button, avatar
preview, banner text, and Edit affordance share a single vertical
column with the icon-picker tabs (`.tabs-section` uses `px-3`).
Also bumps the trash↔color-swatch gap from `gap-1` (4px) to
`gap-1.5` (6px) across `.tab-actions`, `.asset-picker-topbar-actions`,
and `.text-picker-actions` so the two top-right buttons read as
distinct rather than near-touching.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- `.text-picker-back` and `.asset-picker-tabrow` left padding 14px → 12px
so the `< Back` chevron lines up with the icon-picker tabs
(`.tabs-section` uses `px-3`), eliminating the prior 2px misalignment
when switching modes via `< Back`. Right side stays at 14px.
- `.avatar-customize-zone` symmetric padding 18px → 14px, pulling the
avatar preview, banner text, and Edit affordance inward and matching
the topbar's right inset above. Inner content width 352px (was 344px).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Avatar and Image tiles in custom-tab-cp already commit their
synthesized item on click and then navigate to asset-picker. The
Text tile was the odd one out — it only switched view, leaving
the page icon stuck on the prior icon (e.g. an emoji) while the
text-picker visibly claimed "Initials" was selected. Worse, the
text-picker's :will-unmount commits on every close path, so the
prior "look without commit" semantic was already a fiction.
Commit text-item on click to make the semantic explicit and
remove the stale-preview window.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The text-picker's :will-mount unconditionally read [:data :value],
[:data :alignment], [:data :color], and [:data :mode] off the prior
committed icon. For non-text icons (emoji, tabler, avatar) normalize-icon
stamps the shortcode/initials/foreground color into those same paths,
so a smiley emoji seeded `*text-value` with "smiley" and an avatar
leaked its foreground color into the picker's `*color`. The Initials
tile still appeared selected because the `valid-modes` fallback masked
the bad `*mode` value at render time, but the text input and Custom
tile preview surfaced the leak. Gate all four reads on
`(= :text (:type current-icon))`.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Mode tiles only fired on click. Add on-mouse-enter/-leave handlers that
write a full :icon override to :ui/icon-hover-preview — same pattern the
asset-picker uses for shape/fallback tiles. Each tile previews the
would-be commit (mode-specific derived text + overridden :data :mode);
mouse-leave clears only the :icon field, so a concurrent color-swatch
hover keeps composing. No consumer-side change — get-node-icon-cp's
existing :icon overlay path handles it.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The page-title's `.ls-page-icon svg { 38px }` cascade descended into the
avatar's nested fallback SVG and forced it to fill the whole 38×38 box,
overriding `shui/tabler-icon`'s computed `:size` (~0.55× the avatar).
Reset width/height to auto for avatar-internal SVGs so the glyph renders
at its intrinsic size, matching the picker preview and other surfaces.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
get-node-icon-cp's effective-color only checked top-level :color on the
icon map. Instance icons written by the text/avatar picker store color
nested under :data, so sidebars (left & right) fell back to "inherit"
on commit and the SVG's currentColor fill picked up the muted text
color. Inherited class-default icons happened to render correctly
because get-node-icon stamps color at both levels.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The page-title heading had its own inline copy of the class-default-icon
inheritance fallback that lost :mode (and :alignment) when building the
per-instance text icon. Result: a page like Math 201 inheriting #Course's
abbreviated text default rendered "Math 201" in the sidebar, list view,
and table view — but "M2" in the page heading.
Delegate to icon-component/get-node-icon, the same resolver every other
surface uses. Filter to map results so string type-defaults ("file",
"hash", …) keep flowing through the page-title's own :tabler-icon
fallbacks instead.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Logseq's `frontend.state/dom-clear-selection!` runs on every
pointerdown/mousedown and brute-force strips the bare `selected`
class from every DOM node — it's how block-selection cleanup
works. Our text-picker tile used the same class for its
"this variant is chosen" state, so any pointer interaction
killed the ring on the selected tile.
Also adds a radio-button no-op guard on the tile click handler
and a `current-mode` fallback so the picker never renders with
zero selected tiles.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Hovering a color swatch in the text-picker didn't tint anything live
— neither the gallery preview tiles nor the page-icon next to the
page title. Previous commit (5551f6eb86) added the SUBSCRIBER side
in text-picker but no WRITER existed on this code path. The icon-picker
already broadcasts via `:on-hover!` / `:on-hover-end!` callbacks
supplied to `color-picker` (icon.cljs:3961-3972); the text-picker's
call passed only `*color` + selection callback.
Port the same pattern:
1. text-picker mount in icon-search (line 7159) now forwards the
preview-scope opts (`:preview-target-db-id`,
`:preview-target-db-ids`, `:preview-inheritor-db-ids`, `:property`).
2. text-picker's destructure (line 6416) accepts these keys and builds
`preview-base-target` via the same cond-> as the icon-picker
(icon.cljs:3545).
3. The existing subscriber gains a scope filter via
`icon-preview-matches?` so a hover meant for another entity
doesn't bleed in.
4. The `color-picker` call (line 6485) gains `:on-hover!` /
`:on-hover-end!` that call `merge-into-icon-preview!` /
`dissoc-icon-preview-field!` with `preview-base-target` — same
pattern as the icon-picker.
Result: hovering a swatch tints all three gallery preview tiles AND
the page-icon next to the page title; mouse-leave reverts both
together; only the entity actually being themed is affected (scope
filter does its job).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Hovering a color swatch in the color popover updated the page-icon
live (via `:ui/icon-hover-preview` state) but the text-picker's
gallery previews stayed locked to the committed color — same mismatch
the custom-tab Text tile already had, fixed here with the same recipe.
Subscribe to `:ui/icon-hover-preview` in text-picker (component is
already `rum/reactive`). Compute `selected-color = (or hover-color
committed-color)` and pass it to `build-icon` instead of raw `@*color`.
Result: as the user moves over swatches, the Initials / Abbreviated /
Custom tiles tint live; on mouse-leave the committed color re-emerges.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous "selected" state used `var(--lx-accent-09)` for the
border, which in Radix-blue reads as a blue focus ring and in OG as
a cyan one — looks like keyboard focus, not selection. User feedback:
the blue border feels wrong, especially in Radix theme.
Replace with a "pressed in" look:
- bg stays at @apply !bg-gray-04 (themed quaternary teal in OG,
slight gray-tint in Radix)
- border-color reverts to the resting `--ls-border-color` chain so the
button matches the chrome rhythm
- box-shadow: inset 0 1px 2px rgba(0,0,0,0.18) adds a subtle depth
that reads as "this segment is pressed"
- color stays at the brighter --ls-secondary-text-color
Result: selection cue is bg + slight pressed shadow + brighter glyph,
no accent ring that competes with the focus-ring style.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The text-picker gallery (Initials / Abbreviated / Custom) called the
`icon` fn without `:color? true`, so the SVG text rendered with
default theme foreground instead of the user's chosen color — visible
mismatch where the page-icon next to the page title showed the new
color, but the preview tiles in the picker stayed white/themed.
Same fix as the Custom-tab Text tile (commit 63c7236f74). The icon
fn only wraps its output in `.ls-icon-color-wrap` when `:color? true`,
and the wrapper's `style: color: ...` is what makes the SVG's
`fill: currentColor` resolve to the chosen color.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The three alignment buttons (left / center / right) were rendered via
shadcn's button variants `:outline` (inactive) / `:secondary` (active).
In OG dark, both variants resolve through neutral-gray `--secondary` /
`--accent` chains and end up almost indistinguishable — no clear
"this is selected" signal.
Override per-state inside `.text-picker-alignment` with themed chains:
- Inactive: transparent bg, --ls-border-color border, --ls-primary-text-color glyph
- Hover: @apply bg-gray-03 lift + --ls-secondary-text-color glyph
- Active (selected, has `.as-secondary` class): @apply !bg-gray-04
with --lx-accent-09 border, matching the subtle-bg + accent-outline
pattern used for tile selections in icon/asset pickers
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The separator between the gallery row (Initials / Abbreviated / Custom)
and the Text/Alignment controls used `shui/separator {:class "my-0
opacity-50 -mx-3"}` — shadcn's default `bg-border opacity-50` which
fades to near-invisible against the dark OG bg.
Swap to the shared `.icon-picker-separator` class (already in use for
icon + asset picker topbar dividers). Pulls the themed
`--lx-gray-05 → --ls-border-color → --rx-gray-05` chain at full opacity,
so the line is visible across themes. `-mx-3` preserved for the
edge-to-edge layout.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Text-picker (the avatar-text variant shown when picking Initials /
Abbreviated / Custom) had ~10 raw `var(--lx-gray-N)` references that
fell to neutral gray in OG. The preview tile bg, gallery labels,
back button, format note, section label, top-border, etc. all read
as out-of-theme.
Per-element fixes (matches the pattern used across the icon/asset pickers):
- .text-picker outer bg → @apply bg-gray-02 (themed chain)
- .text-picker-back bg → @apply bg-gray-03 (themed topbar tertiary teal)
- .text-picker-back border-bottom → gains --ls-border-color middle step
- .back-button color (rest/hover) → gains --ls-primary/secondary-text-color
- .format-note color → gains --ls-primary-text-color
- .text-picker-section > label color → gains --ls-primary-text-color
- .text-picker-gallery-preview border-color → gains --ls-border-color
- .text-picker-gallery-preview bg → @apply bg-gray-03 (tile sits one
step above the picker body)
- .text-picker-gallery-label color → gains --ls-primary-text-color
- .section-header-row .info-icon (rest/hover) → gains --ls-primary/secondary-text-color
User-picked color on the preview's WO/initials text is unaffected
(that flows through icon-color-wrap, not this CSS). Radix themes
preserved — --lx-gray-N still wins step 1 of every chain.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The "Paste from clipboard" / "Add from your computer" rows shown when
the gallery is empty had several theme-agnostic surfaces:
1. Inter-row separator (::after) → raw `var(--lx-gray-06, --rx-gray-06)`.
Gains `--ls-border-color` middle step → themed teal in OG.
2. Row icon (clipboard/folder) → raw `var(--lx-gray-11, --rx-gray-11)`.
Gains `--ls-primary-text-color` middle.
3. Row title → raw `var(--lx-gray-12, --rx-gray-12)`. Gains
`--ls-secondary-text-color` middle.
4. Row subtitle + chevron → raw `var(--lx-gray-10, --rx-gray-10)`.
Gains `--ls-primary-text-color` middle.
5. Hover bg → raw `var(--lx-gray-03)`. Switched to @apply bg-gray-03
for the full themed chain.
6. Keyboard-highlight bg → was `var(--lx-accent-04) !important` which
in OG renders as bright cyan (#0e5263-ish) drowning the text below.
Replaced with `@apply !bg-gray-04` — the same subtle themed
quaternary teal we use for icon-picker `is-highlighted`. The
accent-09 outline still carries the "I am selected" signal so the
row body text remains readable.
Radix themes unaffected; --lx-gray-N still wins step 1 of every chain.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The dropdown trigger chips (Rectangle / Letters / etc.) used raw
var(--lx-gray-02, --rx-gray-02) for hover/open bg and
var(--lx-gray-05, --rx-gray-05) for border — both fell to neutral
gray in OG, breaking the themed Linear/Notion ghost-chip aesthetic.
- bg → @apply bg-gray-03 (themed tertiary teal chain → #08404f in OG
dark, lifts the chip clearly above the recessed banner bg)
- border-color → gains `--ls-border-color` middle step
Radix themes unaffected — they still pick up --lx-gray-N at step 1.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`--ls-secondary-border-color` in dark OG is `#126277` — BRIGHTER than
`--ls-border-color` (#0e5263). So the previous "secondary" override
made the rail more prominent, not muter — opposite of the intent.
Switch to `color-mix(--ls-border-color, transparent 50%)` so the line
renders as 50% alpha of the themed teal blended into the recessed
banner bg. Result is a subtle hue-aligned teal stroke instead of a
loud full-intensity ring.
The available OG dark border tier (#126277 secondary → loud,
rgba(0,2,0,0.1) tertiary → invisible) couldn't bridge the gap on its
own; opacity-blending the primary gets us a clean middle.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previous commit (8f3b8d992d) over-applied the light-mode bump to three
borders (topbar separator + zone bottom + cb-rail). User clarified only
the inner cb-rail (between Shape/Fallback rows and Reset/Done) needed
adjustment; the other two should keep their default chain.
Also addresses the dark-mode side: the cb-rail at the default chain
resolves to `--ls-border-color` (themed teal #0e5263), which reads as
too prominent against the recessed banner bg. Switch dark-mode
cb-rail to `--ls-secondary-border-color` — a softer line that still
belongs to the theme palette.
Net:
- Light cb-rail: `--ls-border-color` (#ccc) — visible against white
- Dark cb-rail: `--ls-secondary-border-color` — muted vs prior #0e5263
- Topbar separator + zone bottom: unchanged (default chain, calibrated already)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Three picker dividers were near-invisible in OG light theme:
- The shared `.icon-picker-separator` (topbar)
- `.avatar-customize-zone` bottom border
- `.avatar-customize-zone .cb-rail` border-top (inner separator
visible when banner is expanded)
All three resolve through `var(--lx-gray-05, var(--ls-border-color, ...))`.
In OG light, `--lx-gray-05` is defined as `hsl(0,0%,90.9%)` = #e8e8e8
— a Tailwind-style ultra-subtle divider that barely registers against
white. Same chain in OG dark falls to `--ls-border-color` (#0e5263)
which IS visible. Hence the perceived "lines almost invisible in light,
prominent in dark" asymmetry.
Light-mode override via `html:not(.dark)` bumps all three borders to
`--ls-border-color` directly (#ccc in OG light) — perceptual weight
now comparable to dark mode's themed teal. Dark mode untouched.
Scoped to `html:not(.dark)` so it only affects the light variant.
Radix themes pick up the same override since they don't carry the
`.dark` class either — but their `--ls-border-color` is theme-tuned,
so the visual result remains sensible across themes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The `.cb-rail` (the line between the Shape/Fallback rows and the
Reset/Done row when the customize banner is expanded) used a 2-step
fallback `var(--lx-gray-05, var(--rx-gray-05))` — neutral gray in OG.
Add `--ls-border-color` middle step so the rail matches the topbar
separator and the customize-zone bottom border (all #0e5263 in OG).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previous `color-mix(picker-bg 65%, black)` worked great in dark mode
but rendered the light-mode banner as muddy mid-gray — the same 35%
black blend that produces a clear recess on dark teal kills text
contrast against a near-white bg, making "Letters, rectangle" almost
illegible.
Split the recipe by mode:
- Default (light): mix(picker-bg 95%, black) — subtle 5% darkening
- html.dark override: mix(picker-bg 65%, black) — stronger 35% for visible recess on dark bgs
Both branches use the same Tailwind-style chain so OG and Radix themes
adapt cleanly. Hover state (still @apply bg-gray-03) is mode-agnostic
via the Tailwind utility, so no separate override needed there.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The asset-picker's `.asset-picker-tabrow` had a `border-bottom`, AND
a shui/separator (with `.icon-picker-separator` class) was rendered
immediately below it. The result: two visible 1px lines stacked
between the tabrow and the search input — a visible double-line in
OG that doesn't appear in the icon picker (which only has the
separator).
Drop the tabrow's border-bottom — the separator already draws the
divider with the themed `--ls-border-color` chain. Matches the icon
picker's pattern (tabs-section has no border-bottom; the separator
between tabs and search carries the line).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Resting state was `color-mix(picker-bg 80%, black)` — only ~20% darker
than the picker bg, too subtle to read as recessed in OG.
Bump to `color-mix(picker-bg 65%, black)` so the banner is ~35% darker.
The band now clearly reads as a sunken section between the topbar
above and the gallery below.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The asset-picker footer (`Tip: Drop an image, paste a link, or browse`)
used raw var(--lx-gray-05) for the top border and var(--lx-gray-03)
for the bg, both invalid in OG (where --lx-gray-N is unset). The
result: no top border + transparent bg, killing the elevated-footer
effect the Radix theme gets.
Fixes:
- border-top: var(--lx-gray-05, var(--ls-border-color, var(--rx-gray-05)))
- bg: @apply bg-gray-03 (themed tertiary teal in OG, same chain as topbar)
- .tip-label color: gains --ls-secondary-text-color middle
- .tip-body color: gains --ls-primary-text-color middle
Tip-link colors already used --lx-accent-11/12 which are theme-adaptive,
so the "browse" link continues to honor the theme accent. Radix themes
preserved via --lx-gray-N winning step 1 of every chain.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two related tweaks after user feedback that the banner color was
"not distinct enough" and hover revealed neutral gray:
1. Resting state: was color-mix(secondary 90%, black) — only ~2%
darker than the picker bg. Drop to 80% (20% black) so the banner
is visibly recessed against the picker, while still distinct from
the page bg behind the popover. The chain is still based on the
themed `--ls-secondary-background-color`, so OG gets a teal-tinted
dark band rather than a neutral black.
2. Hover state: was raw `var(--lx-gray-03, var(--rx-gray-03))` —
neutral gray in OG. Switch to @apply bg-gray-03 which chains
through `--ls-tertiary-background-color`. Hover now LIFTS the
banner from its recessed dark state up to the topbar's tertiary
teal — a clear interactive cue across themes.
Also the .banner-edit hover-state color gains the `--ls-secondary-text-color`
middle step (matches the rest of the picker text-theming work).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two follow-up tweaks after the asset-picker chrome theming pass:
1. `.license-badge` (the "Free for any use" pill in the web-image hover
preview card) used raw var(--lx-gray-04) for bg — invalid in OG,
making the pill background completely transparent. Switch to
@apply bg-gray-04 for the themed chain. Color also gains the
--ls-primary-text-color middle step. The same raw-var pattern was
present on `.web-images-error` — fixed in the same pass.
2. The shui/separator between the asset-picker's tabrow and search
input used the shadcn default `bg-border opacity-50`, which rendered
washed-out teal in OG (~#003947 at 50% alpha). Apply the
`icon-picker-separator` class so it picks up the same themed
--ls-border-color (#0e5263, full opacity) as the icon picker.
To make this work across both pickers, `.icon-picker-separator` is
moved out of the `.cp__emoji-icon-picker` parent block to top-level
(now shared with `.asset-picker`).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Asset-picker chrome rendered with neutral grays in OG turquoise:
- topbar/tabrow used raw var(--lx-gray-03) — invalid in OG → transparent
- segmented control bg used var(--lx-gray-06, --rx-gray-06) — neutral
- active segment used raw var(--lx-gray-01) — invalid in OG → unset
- customize zone used var(--lx-gray-01, --rx-gray-01) — fell through to
--ls-primary-background-color (#002b36) which is the SAME color as the
page bg behind the popover, making the band look like a hole punched
through the picker
- gray-05 borders + gray-10/11/12 text fell to neutral
Fixes:
- .asset-picker-tabrow bg → @apply bg-gray-03 (matches icon picker's
tabs-section via the full Tailwind themed chain)
- .segmented-control bg → @apply bg-gray-06 (themed quaternary teal)
- .segment[data-active] bg → @apply bg-gray-01 (carved-in feel against
the lighter control)
- .avatar-customize-zone bg → color-mix(secondary-bg 90%, black) — a
recessed-but-still-distinct band that doesn't bleed into page bg in OG
- All gray-05 borders gain --ls-border-color middle step
- All gray-10/11/12 text gains --ls-primary-/--ls-secondary-text-color
middle steps
Radix themes unaffected: --lx-gray-N still wins step 1.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`add-button-inner` previously rendered the trailing add-sibling
button only when the rendered entity was a page or on mobile, so a
block opened via "Open in sidebar" or rendered as an embedded root
had no discoverable way to append a child on desktop.
Destructure `block?` (already set by `page-blocks-cp` to
`(not (db/page? block))` when building hiccup-config) and add it to
the render predicate so block-rooted views surface the button too.
* feat(search): add support for page aliases in search results
* enhance(alias): enforce strict alias ownership invariants
* fix(exporter): streamline page extraction and alias sanitization
* fix(search): add alias support to search result mapping
* fix(exporter): handle self-alias in page alias sanitization
* feat(outliner): enhance alias handling in set-block-db-attribute!
* fix(outliner): remove redundant db reference in set-block-property
* fix(search): keep canonical page title for alias-indexed results
* feat(property): enhance alias handling for source page identification
* feat(search): improve alias handling for snippet display in search results
* fix: correct alias assignment in block processing
* feat: add validation for batch alias assignment to prevent multiple owners
---------
Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
The regular icon/emoji grid animates outline-width 0 → 2px AND
outline-offset 0 → 2px in parallel when .is-highlighted lands on a
tile, producing a satisfying scale-up feel as the ring grows outward.
The Custom tab tiles used a baseline of `2px solid transparent` with
outline-offset -2px (inset) and only transitioned outline-color, so
arrow-key navigation through Text/Avatar/Image only showed a fade.
Visually inconsistent with the rest of the picker.
- Baseline: `outline: 0 solid transparent; outline-offset: 0`
- Highlighted: `outline: 2px solid accent-09; outline-offset: 2px`
- Transition: extended to include outline-width and outline-offset
(matches the per-cell transition in the regular grid)
Outline now grows outward (positive offset) on highlight, scaling up
the ring rather than fading it in place.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Arrow-key navigation through Text/Avatar/Image tiles flashed the
browser's default :focus-visible outline around the entire
<button.custom-tab-item> (preview + label) for one frame before the
.is-highlighted class applied our intended preview-only ring. Visually
choppy and inconsistent with the keyboard-nav style of the regular
icon/emoji grid (which doesn't trigger DOM focus on individual tiles).
Override :focus / :focus-visible on .custom-tab-item to remove the
outline and box-shadow. The .is-highlighted .custom-tab-item-preview
rule (already defined below) remains the canonical keyboard-nav
indicator — accessible focus is preserved, just rendered on the 48x48
preview tile rather than wrapping the whole column.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Five issues in the Custom tab fixed in one pass.
1. Hover bg of the 48x48 tile preview (`.custom-tab-item-preview:hover`)
was raw var(--lx-gray-05, var(--rx-gray-05)) — neutral gray in OG.
Inject --ls-border-color middle step (matches the regular grid's
hover, also updated earlier this session).
2. Keyboard-highlighted preview bg used bright var(--lx-accent-04),
swamping content. Replace with the same color-mix-diluted quaternary
teal used by the regular grid's ghost/highlighted tiles. Accent-09
outline still carries the "I am selected" signal.
3. Tile labels ("Text", "Avatar", "Image") used raw gray-11/12 — neutral
in OG. Add --ls-primary-text-color and --ls-secondary-text-color
middle steps for label resting/hover respectively (matches the rest
of the picker text-theming work this session).
4. Image tile's dashed border was raw var(--rx-gray-08) — neutral. Use
the lx-gray-08 / --ls-border-color / rx-gray-08 chain. Same chain
applied to the image-placeholder branch in the `icon` fn (cljs:691)
so the page-icon's `Pick an image` preview matches.
5. Text tile preview wasn't picking up the user's selected color — the
`icon` fn only wraps its output in .ls-icon-color-wrap when
`:color?` is truthy, and the Custom-tab text branch was calling it
without that opt. Pass `:color? true` so the SVG's
`fill: currentColor` resolves to the chosen color (verified live:
green preset now shows on the WO preview).
Avatar and Image tile color application unchanged — those paths use
explicit bg/color inline styles, not the currentColor wrapper.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Ghost (#094b5a) and hover (#0e5263) were only ~4% apart in lightness —
visually indistinguishable on a teal picker bg. Drop ghost to 50%
alpha via color-mix with transparent, which mixes the quaternary
teal half-and-half with the picker bg behind it. Ghost pulls two
shades closer to the picker bg, hover (still full --ls-border-color)
gets a real visual lift.
color-mix(srgb) is Chrome 111+ / Safari 16.2+; safe in Logseq
Electron and modern web targets.
Same Tailwind chain token so Radix themes still receive their
themed gray (just at half intensity), preserving the muted-ghost
aesthetic there too.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two tweaks to picker tile interaction states:
1. .is-highlighted (arrow-key selected): bg dropped from --lx-accent-04
(bright cyan in OG) to @apply !bg-gray-04 (themed quaternary teal —
same value as ghost). Bright accent-09 outline still carries the
"I am selected" signal. Line icons (especially green) now remain
readable instead of getting drowned by the accent-tinted bg.
2. Button :hover: was raw var(--lx-gray-05, var(--rx-gray-05)) — falls
to neutral gray in OG and is identical to ghost's bg in Radix.
Inject --ls-border-color (#0e5263, one shade lighter than the
ghost's #094b5a) as the themed middle step so hover actually pops
above ghost in OG. Radix themes still use --lx-gray-05 step 1.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>