Skip to content

library: fix object icon visibility and refine interactive cover hots…#149

Merged
MaryWylde merged 2 commits into
devfrom
feat/library-animation
Jun 17, 2026
Merged

library: fix object icon visibility and refine interactive cover hots…#149
MaryWylde merged 2 commits into
devfrom
feat/library-animation

Conversation

@MaryWylde

Copy link
Copy Markdown
Contributor

…pots

Object icons (book/video/audio) rendered white-on-white in the library card list and the sidebar "Total objects" zone. Switch the sprite symbols to currentColor and pin a dark tone on the Object icon wrapper so they stay visible on light surfaces while the cover card keeps its white icons.

Also inline the icon sprite for cross-browser support, and tune hotspot geometry, card edge anchoring, and pagination gating on the cover.

…pots

Object icons (book/video/audio) rendered white-on-white in the library
card list and the sidebar "Total objects" zone. Switch the sprite symbols
to currentColor and pin a dark tone on the Object icon wrapper so they
stay visible on light surfaces while the cover card keeps its white icons.

Also inline the icon sprite for cross-browser <use> support, and tune
hotspot geometry, card edge anchoring, and pagination gating on the cover.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@MaryWylde

Copy link
Copy Markdown
Contributor Author

@claude, review this PR.

@claude

claude Bot commented Jun 17, 2026

Copy link
Copy Markdown

Claude finished @MaryWylde's task in 2m 32s —— View job


PR Review — library: fix object icon visibility and refine interactive cover hotspots

Todo

  • Load tools and read repo guidelines
  • Read diff and changed files
  • Review Icon/SVG sprite changes
  • Review InteractiveCover changes (hotspots, types, SCSS)
  • Review Sidebar, Object, RatingBox, layout changes
  • Review useAnchoredPosition hook changes
  • Post full review

Overview

The approach is solid: currentColor on sprite paths + a pinned dark color on the Object icon wrapper correctly solves the white-on-white problem without duplicating values. The sprite-inlining workaround for Safari <use> is the right fix. A few issues need attention before merging.


Issues — Should Fix

1. Debug artifact paths in all.svgbook and video symbols

Both symbols contain giant, out-of-bounds rectangles colored #0000FF that are clearly Figma export artifacts:

<path d="M295.92 -167.388V135.732H-25.1996V-167.388H295.92Z..." fill="#0000FF"></path>


<path d="M159.12 -84.4991V134.421H-72.7998V-84.4991H159.12Z..." fill="#0000FF"></path>

These paths use coordinates far outside their 18×18 / 13×13 viewBoxes, so they don't render visibly — but they bloat every client that downloads the sprite and are incorrect SVG. Fix this →

2. JSDoc mismatch on InteractiveCoverProps.wideSrc

InteractiveCover.types.ts:8 says:

/** Wider artwork served to 1920px+ viewports via <picture> art direction. */

But the actual <source media="(min-width: 768px)"> in InteractiveCover.tsx:145 switches at 768px. The doc misleads future readers. Fix this →

3. Duplicate border-right in Object.module.scss:38-39

.border {
  .icon {
    border-right: 0;              // ← dead code, immediately overridden
    border-right: 1px solid var(--brown-border);
  }
}

The first declaration is never observed. Fix this →


Issues — Nice to Fix

4. Dead CSS rule in InteractiveCover.module.scss:117

@media (max-width: 768px) {
  .card { width: 60%; min-width: 0; }
}

The .card element only ever mounts inside the .layer div, which itself only renders when isWide is true (min-width: 768px). So this rule can never match a live element. It should be removed or, if cards are ever intended on smaller viewports in the future, the condition should be max-width: 1024px. Fix this →

5. Icon.tsx:85 — redundant fill attribute on the outer <svg>

fill={color !== 'currentColor' ? undefined : color}

When color === 'currentColor' this sets fill="currentColor" on the <svg> root, which has no effect since the <symbol> paths already declare fill="currentColor". When color is a custom value, fill={undefined} — the CSS color property set via style already propagates into the symbol paths through currentColor. The attribute is harmless but confusing. Consider dropping it and relying solely on style={{ color }}.

6. RatingBox.tsx:81openUpMaxWidth: 1920 always opens upward

const menuPos = useAnchoredPosition(triggerRef, isOpen, menuRef, {
  openUpMaxWidth: 1920,
});

This means the dropdown opens upward on every screen ≤1920px (i.e., practically always). The comment explains it avoids the first-paint jump, which is valid, but if a RatingBox ever sits near the top of a container, the menu will be clipped above it. Worth verifying this scenario doesn't occur in production placement.


Looks Good

  • Sprite inlining strategy (Icon.tsx:42–66): the module-level spritePromise singleton, the double-guard (getElementById before and after fetch), and the aria-hidden + position:absolute;width:0;height:0 container are all correct. The catch(() => { spritePromise = null }) retry path is sound.
  • useMatchMedia (InteractiveCover.tsx:21–33): starting false during SSR so markup is deterministic, then correcting post-hydration in useEffect, is exactly right.
  • Outside-click + Escape cleanup (InteractiveCover.tsx:116–138): the effect is properly gated on mode === 'click' && activeId and removes listeners on cleanup. No leak.
  • useAnchoredPosition equality guard (useAnchoredPosition.ts:66–74): bailing out when position hasn't changed prevents unnecessary re-renders.
  • Object.module.scss icon color fix: color: var(--gray-darkest) on the .icon wrapper is the minimal, correct fix — doesn't touch cover-card white icons since those set their own color.
  • Pagination gating (Home.tsx:191): {totalPages > 1 && correctly hides the control when there's only one page.
  • .gitignore addition: /dropped-images/ is a clean, self-documenting entry.

Not Production-Ready (Follow-up)

coverHotspots.ts uses lorem ipsum for all about fields and placeholder names ("John's Library", "Sarah's Library", etc.). Fine for this phase, but needs real content before the feature ships.

The hotspot layer (and its .card) only mounts at min-width:768px, so the
max-width:768px rule could never match a live element.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@MaryWylde MaryWylde merged commit 2235fa2 into dev Jun 17, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant