Refactor/mobile home2 - #666
Conversation
bfalling
left a comment
There was a problem hiding this comment.
First half reviewed. Just one blocker.
| $:render_template("home/custom_ia_carousel", title="You might also like", key="related-subjects-carousel", work_id=work.key, _type="subjects", limit=42, min_books=1) | ||
| $:render_template("home/custom_ia_carousel", title="More by %s" % (authors or "by this author"), key="related-authors-carousel", work_id=work.key, _type="authors", limit=42, min_books=1) | ||
| $:render_template("home/custom_ia_carousel", title="You might also like", key="related-subjects-carousel", work_id=work.key, _type="subjects", limit=42, min_books=1, slick=False) | ||
| $:render_template("home/custom_ia_carousel", title="More by %s" % (authors or "by this author"), key="related-authors-carousel", work_id=work.key, _type="authors", limit=42, min_books=1, slick=False) |
There was a problem hiding this comment.
BLOCKER: If "by this author", looks like "by" will be doubled.
| return formatted_books | ||
|
|
||
| def get_featured_subjects(): | ||
| # web.ctx must be initialized as it won't be avaiable to the background thread. |
| @@ -1,3 +1,60 @@ | |||
| var Carousel = { | |||
| add: function(selector, a, b, c, d, e, f) { | |||
There was a problem hiding this comment.
Fine for them to be concise, fine for them to have number suffixes, but we need better parameter names than "a, b, c, d, e, f" :) (...unless this signature is being dictated from elsewhere, in which case a comment would be helpful to explain)
| @@ -0,0 +1,38 @@ | |||
| $def with(books=None, title="", url="", key="", min_books=6, cta="Borrow", test=False) | |||
|
|
|||
| $if test or (books and len(books) >= min_books): | |||
There was a problem hiding this comment.
Is this at the right indentation level, given the def above?
| <div class="carousel-container carousel-container-decorated"> | ||
| <div class="carousel carousel-$key"> | ||
| $for book in (books or []): | ||
| $ byline = (' by ' + ', '.join([author.name for author in book.authors])) if book.get('authors') else '' |
There was a problem hiding this comment.
I assume there's no significant performance penalty in calling book.authors twice? Not a network call, right?
There was a problem hiding this comment.
that's right, book is an obj which is already fetched, it's just an access of the dict
| <span class="book-authors">$:byline_links</span> | ||
| </h2> | ||
| </div> | ||
| --> |
There was a problem hiding this comment.
Remove this commented out code?
| </h3> | ||
| <p id="home-about-mission-desc"> | ||
| Just like Wikipedia, you can contribute new information or corrections to the catalog. | ||
| You can browse by <a href="/subjects">subject</a>, <a href="/authors">author</a> or |
There was a problem hiding this comment.
Should "subject" and "author" be plural to match "lists"?
| $ presentable_subject_name = subject_name.replace('_', ' ').title() | ||
| <div class="category-item"> | ||
| <a class="category-nostyle" data-ol-link-track="CarouselCategories" | ||
| href="/subjects/$(subject_name)#sort=date_published&ebooks=true"> |
There was a problem hiding this comment.
Technically, shouldn't "&" be "& a m p ;"?
bfalling
left a comment
There was a problem hiding this comment.
Part 2 complete. Suggestions. No blockers.
| $:render_template("home/custom_ia_carousel", title="Thrillers", key="thrillers", query="preset:thrillers", sorts=["downloads+desc"], limit=42, test=test) | ||
|
|
||
| $:render_template("home/custom_ia_carousel", title="Thrillers", key="thrillers", query="preset:thrillers", sorts=["downloads+desc"], limit=42, test=test) | ||
| $:render_template("home/custom_ia_carousel", title="Textbooks", key="textbooks", subject="textbooks", sorts=["loans__status__last_loan_date+desc"], limit=36, test=test) |
There was a problem hiding this comment.
Why is this one not using the query attribute?
There was a problem hiding this comment.
It could be -- subject is an alternative to query. But really we should deprecate subject and just have a query of e.g. openlibrary_subject:textbooks
| <h2 class="inline">Around the Library</h2> | ||
| <p class="inline sansserif large collapse"> Here's what's happened over the last 28 days. More <a href="/recentchanges">recent changes</a>.</p> | ||
| </div> | ||
| </div> |
There was a problem hiding this comment.
Looks like there's a net addition of +1 open <div> tag, but I don't immediately see an added closing tag. Maybe verify tags are balanced. (Oh, HAML, where art thou?!?)
There was a problem hiding this comment.
It's closed below on line 44
| <div class="chartShow" onClick="window.location.href='//archive.org/stats';" title="See all visitors to OpenLibrary.org"> | ||
| <div id="home-stats-charts"> | ||
| <div class="statschart"> | ||
| <div class="chartShow" onClick="window.location.href='//archive.org/stats';" title="See all visitors to OpenLibrary.org"> |
There was a problem hiding this comment.
The above 3 lines use 3 different word break formats: hyphen, smash-together, and camel case. Definitely not a big deal, but consistency would be nice.
Also, inline onClick handlers are a little ick. (I know they're legacy.)
| \$().ready(setupSearch); | ||
| \$().ready(linkbuttons); | ||
| </script> | ||
| --> |
| <br style="clear: both"/> | ||
|
|
||
| <div class="hidden" id="debug-stats" style="padding: 10px 20px 20px; background: #eee; margin-bottom: 20px;"> | ||
| <div class="hidden" id="debug-stats"> |
There was a problem hiding this comment.
Thanks for removing those inline styles!
| div#abuse a span { | ||
| display:block; | ||
| margin: 5px 0px 5px 30px; | ||
| width:32px;height:32px;background-repeat:no-repeat;background-image:url(/images/icons/icons_sprite.png);background-position: -576px 0;} |
There was a problem hiding this comment.
Break into separate lines.
|
|
||
| #home-stats { | ||
|
|
||
| } |
There was a problem hiding this comment.
Remove empty selector set?
|
I'm puzzled why this carousel now needs to be accessed via the archive.org domain (which remains problematic on many networks) vice the openlibrary.org domain. In what way is that helpful? |
|
@LeadSongDog this query is being done from the Open Library server (which is within our internal network) in order to fetch books which are available (because Open Library doesn't have an accurate picture of what books are currently available. It shouldn't impact the end user. Essentially how it works is
Another time internet archive may be used is in cases where open library bookcovers aren't available, but we're working to make it so these bookcovers just get added to openlibrary. |
|
@mekarpeles Could this somehow be done between OL and IA only, that is, without requiring the browser to have access to archive.org? |
The sprite shipped on every page but nothing outside /developers/design referenced it — $:macros.icon() had no production callers, and the glyphs patrons actually saw were hand-copied paths, <img> icons that could not inherit color, and a second icon vocabulary. Deduped 20 hand-copied glyphs. Six Lit components now import from icons.generated.js rather than carrying their own path data; the chevron-down path alone existed verbatim in four files. Converted 22 <img> icons to sprite references: all 12 right-chevron sites, the password-visibility eye (password-toggle.js now repoints <use href> instead of swapping img.src), signup's success check, the language globe, search-inside, the barcode scanner, the edition nav arrows and the hamburger. As images these could not inherit currentColor — two of them hardcoded internetarchive#666/#8a7f71 and ignored the theme outright. Retired the second vocabulary: PreviewSearchInside drew three Material Symbols glyphs (viewBox="0 -960 960 960", filled, one with a hardcoded fill) next to Lucide stroke icons in the same row on the book page. Supporting changes: - The macro emits a fixed class list, which blocked nearly every call site — they carry load-bearing hooks (.down-arrow's rotation, .sas-avatar__icon's sizing, .search-icon). Added an `extra_class` passthrough, mirrored in the Jinja global, so adopting the system does not mean rewriting CSS at each site. - icon_link() takes an icon name instead of an image src. Migrating only its share icon would have left a stroke glyph between two 700pt filled illustrations, so Review and Notes moved with it. - Four new glyphs, taken from lucide-static rather than redrawn: share-2, scan-barcode, message-square-text, sticky-note. - Dropped three shape-describing alt strings from the catalog ("right chevron", "search inside icon", "Search Inside Icon"). layout_options.html deliberately keeps its inline glyphs, with a comment saying why: ol-segmented-control harvests each segment's innerHTML and re-renders it inside its shadow root, where a same-document <use> resolves to nothing. Glyphs drawn through the macro take the sprite's baked stroke-width of 2, so the browse chevron goes from 2.5 to 2. The Lit components keep their own wrapper stroke-width and are unchanged. Twelve image assets are now unreferenced and left in place for a separate cleanup pass alongside the 30 that were already dead. Claude-Session: https://claude.ai/code/session_01XfFpmRvFnGA4zTwUpokNzW
* Add unified icon system: <ol-icon>, $:icon() macro, build-time sprite
One curated set on a 24x24 / 2px / currentColor grid, replacing the ad-hoc
mix of PNG sprites, file SVGs, and inline-SVG-in-JS.
Source of truth: static/icons/src/{lucide,custom}/. scripts/build_icon_sprite.mjs
(make icons) emits three outputs from it:
- static/build/icons/sprite.svg - <symbol> sheet for the document/light DOM
- static/icons/manifest.json - committed icon-name list (gallery + lint)
- openlibrary/components/lit/icons.generated.js - committed Lit svg fragments
for shadow-DOM components (which can't reach the document sprite via <use>)
Delivery:
- $:icon(name, size, label) Templetor macro for server templates
- <ol-icon> Lit component (light DOM) for JS/light-DOM contexts
Both use a same-document <use href="#name">; the sprite is inlined once per page
via the icon_sprite() helper (footer), since external <use href="file.svg#id">
is unreliable on the Safari/iOS versions in our browserslist.
Shadow-DOM components inline glyphs imported from icons.generated.js instead;
ol-dialog's close icon is migrated as the first example.
Also: icon-size tokens (sm/md/lg), shared ol-icon.css, an icon gallery with
copy-to-clipboard at /developers/design#icons, and a pre-commit/npm check that
the generated sprite/manifest/module stay in sync with the sources.
* Migrate Lit component icons to shared icons.generated.js module
Replace inline SVG glyphs with imports from the generated icon module:
- OLMarkdownEditor: all 19 toolbar glyphs (wrapped in the editor's <svg> shell
so toolbar CSS still governs size/stroke-width)
- Close (X) icon deduped across OLChip, OlBanner, OlToast, and SearchModal to
the canonical `x` glyph (removes four hand-written copies)
Geometry is unchanged (the icon set was harvested from these components), so the
rendered output is identical. Verified in-browser: editor toolbar, dialog/chip/
banner/toast/search-modal close icons all render as real SVG elements.
* Reserve <ol-icon> host box to prevent layout shift on upgrade
Size the ol-icon host element from its size attribute in render-blocking CSS
(a plain `ol-icon` selector, so it applies before and after the component
upgrades). The box is held from first paint, so no surrounding content reflows
when the Lit bundle runs. The glyph still appears on upgrade — server-rendered
templates that need instant, JS-free icons should use the $:icon() macro.
* Document icon technique choice (macro vs fragment vs element) on design page
Add a 'which technique to use' comparison table, usage examples for all three
paths, and a 'what you control' section spelling out sizing (sm/md/lg tokens +
numeric escape hatch) and color (currentColor — set color on any ancestor).
* Fix <ol-icon> API docs: attach JSDoc to the class so cem captures @prop
A const declaration sat between the JSDoc block and the class, so the analyzer
attached the @prop descriptions to the const instead of OlIcon — leaving the
design-page API table empty. Move it above the doc comment so the table renders
name/size/label with their descriptions.
* Style icon gallery as a bordered grid
* Make icon build dependency-free (drop svgo) so the freshness check runs anywhere
The icons-generated pre-commit hook ran the generator, which imported svgo — a
devDependency absent in CI/containers/fresh checkouts, so the hook failed with
ERR_MODULE_NOT_FOUND. The source SVGs are authored clean, so svgo was only
merging paths; the generator already keeps just the attributes it needs. Drop
svgo from the generator (pure Node built-ins now) and remove the unused sprite
SVGO config. Glyph geometry is unchanged (paths are simply no longer merged).
* feat(design): icon system, design-system docs rebuild, and web component foundations
A broad snapshot of in-flight design-system work on this branch.
- Icons: unified <ol-icon> / $:icon() sprite system over static/icons/src,
with a build-time sprite plus generated fragment module for shadow DOM.
- Design docs: /developers/design rebuilt into Foundations / Components /
Icons / Playground, with tokens and component APIs derived rather than
hand-maintained. Icon size presets now document their pixel values
(sm 16px, md 20px, lg 24px) and that the 2px grid stroke scales with them.
- Web components: focus/tabbing utilities, FocusableHostMixin,
FormAssociatedMixin, keyboard-nav helpers, new OlMenuPopover and
OlSegmentedControl, and a11y tests across the Lit layer.
- Tokens/CSS: token contrast tooling and wide stylesheet updates.
- Also carries subject-page macros, results-toolbar sort work, and assorted
plugin/template changes.
Claude-Session: https://claude.ai/code/session_01XfFpmRvFnGA4zTwUpokNzW
* fix(design): drop inline style from the icon color example
djLint H021 flagged the Color demo's inline `style="color: ..."`, which was
the last lint failure on the icons page. Swap it for a .ds-demo-danger class
alongside the other ds-demo-* helpers, and show the reader the CSS rule in
the blurb so the snippet teaches the real technique rather than an inline
style nobody should copy.
Claude-Session: https://claude.ai/code/session_01XfFpmRvFnGA4zTwUpokNzW
* fix(icons): correct macro call form, namespace sprite ids, inline sprite early
Review follow-ups on the icon system:
- Docs and the gallery's copy button taught `$:icon("search")`, which is not a
global — Templetor exposes disk macros only as `$:macros.icon(...)`, so every
documented snippet raised NameError when pasted into a template.
- Sprite <symbol> ids were unprefixed, putting document-global ids like #search
and #code on every page. Any colliding id earlier in the document won <use>
resolution and the icon silently rendered blank. Namespaced to icon-<name>;
the names callers pass and manifest.json are unchanged.
- The sprite was inlined just before </body>, so icons above the fold had
nothing to resolve against until the response finished streaming. It is now
the first thing in the body (~1.5KB gzipped).
- <ol-icon size="32"> styled the inner <svg> but not the host, painting a 32px
glyph inside a 20px box. Raw pixel sizes are gone; a one-off is a CSS job,
which also gets the box right before the component upgrades.
- The macro emitted 18 leading newlines, one per comment line above its output;
its docs now sit below it.
- The drift-check hook matched a path that does not exist and did not guard the
generated outputs it exists to protect.
- The build script now rejects icon names that are not kebab-case or that
collide as JS identifiers, naming the offending source file rather than
failing later inside a generated one.
Claude-Session: https://claude.ai/code/session_01XnwG8xofUcTkTSyUaz7fu7
* feat(icons): expose the icon macro as a Jinja global
Jinja templates are the preferred target for new code but had no way to
draw an icon: Infogami exposes disk macros only through Templetor's
`macros` namespace, so the design page had to hand `icon=macros.icon` to
render_jinja_template as a kwarg, and any other template would have had
to do the same.
Registers `icon` in the Jinja env instead, wrapping the same macro and
returning Markup so it survives autoescape. Templates now write
`{{ icon("search") }}` against the same sprite the Templetor macro uses.
The design page drops its per-call-site shim and documents both forms.
Claude-Session: https://claude.ai/code/session_01XnwG8xofUcTkTSyUaz7fu7
* feat(icons): adopt the icon system across user-facing pages
The sprite shipped on every page but nothing outside /developers/design
referenced it — $:macros.icon() had no production callers, and the glyphs
patrons actually saw were hand-copied paths, <img> icons that could not
inherit color, and a second icon vocabulary.
Deduped 20 hand-copied glyphs. Six Lit components now import from
icons.generated.js rather than carrying their own path data; the
chevron-down path alone existed verbatim in four files.
Converted 22 <img> icons to sprite references: all 12 right-chevron sites,
the password-visibility eye (password-toggle.js now repoints <use href>
instead of swapping img.src), signup's success check, the language globe,
search-inside, the barcode scanner, the edition nav arrows and the
hamburger. As images these could not inherit currentColor — two of them
hardcoded #666/#8a7f71 and ignored the theme outright.
Retired the second vocabulary: PreviewSearchInside drew three Material
Symbols glyphs (viewBox="0 -960 960 960", filled, one with a hardcoded
fill) next to Lucide stroke icons in the same row on the book page.
Supporting changes:
- The macro emits a fixed class list, which blocked nearly every call site
— they carry load-bearing hooks (.down-arrow's rotation, .sas-avatar__icon's
sizing, .search-icon). Added an `extra_class` passthrough, mirrored in the
Jinja global, so adopting the system does not mean rewriting CSS at each
site.
- icon_link() takes an icon name instead of an image src. Migrating only its
share icon would have left a stroke glyph between two 700pt filled
illustrations, so Review and Notes moved with it.
- Four new glyphs, taken from lucide-static rather than redrawn:
share-2, scan-barcode, message-square-text, sticky-note.
- Dropped three shape-describing alt strings from the catalog
("right chevron", "search inside icon", "Search Inside Icon").
layout_options.html deliberately keeps its inline glyphs, with a comment
saying why: ol-segmented-control harvests each segment's innerHTML and
re-renders it inside its shadow root, where a same-document <use> resolves
to nothing.
Glyphs drawn through the macro take the sprite's baked stroke-width of 2,
so the browse chevron goes from 2.5 to 2. The Lit components keep their own
wrapper stroke-width and are unchanged.
Twelve image assets are now unreferenced and left in place for a separate
cleanup pass alongside the 30 that were already dead.
Claude-Session: https://claude.ai/code/session_01XfFpmRvFnGA4zTwUpokNzW
* fix(icons): position PURE annotations where Rolldown can honor them
Rolldown (Vite 8) only honors /*#__PURE__*/ before a call or new
expression - before a tagged template it warns INVALID_ANNOTATION and
keeps unused glyphs in the bundle. Wrap each glyph in an IIFE so the
annotation precedes a real call; terser understands the same form, so
the webpack build keeps its tree-shaking hint too.
Claude-Session: https://claude.ai/code/session_01V312UXw8oNocbu5SkC1A42
* feat(icons): serve the sprite as a hashed asset instead of inlining it
The sprite was inlined into every page body; now it's one external
content-hashed file cached sitewide. icon_sprite() becomes
icon_sprite_url(), the macro and <ol-icon> reference
<use href="{sprite}#icon-name">, and client JS picks the URL up from a
<meta name="ol-icon-sprite"> tag in site/head.
Also: delete the legacy one-off SVGs now replaced by the sprite, drop
the unused chevron-up glyph, thicken the scan-barcode icon and match its
header color to the search magnifier, and trim the language-dropdown
labels to the native name only.
Claude-Session: https://claude.ai/code/session_01RjCpiDb519vwQx4yDAKpra
* chore(icons): delete long-dead images from static/images/icons
These 28 files were unreferenced before the icon-system branch — no
template, CSS, JS, or Python mentions them, nothing constructs their
paths dynamically, and the service worker caches by URL pattern rather
than a file list.
Claude-Session: https://claude.ai/code/session_01V312UXw8oNocbu5SkC1A42
* feat(icons): move the editions table off its PNG-era DataTables chrome
Replace the last PNG sprite consumers with the icon system: sort state
in the editions table header now renders arrow-up-down /
arrow-up-narrow-wide / arrow-down-wide-narrow glyphs driven purely by
DataTables' sorting classes, and the full_numbers pager is dropped from
the `dom` string in favor of an <ol-pagination> synced to the table's
paging state. The nine legacy sort/paginate PNGs and their CSS are
deleted, along with the hand-rolled arrow-toggling jQuery.
Along the way:
- Add per-size stroke tokens (--icon-stroke-sm/md/lg); the sprite build
now strips stroke-width from each <symbol> so the weight inherits from
the referencing <svg>, letting `lg` pull back to 1.75px instead of a
full 2px.
- Auto-discover source groups under static/icons/src/ instead of
hardcoding lucide/custom, and rename LICENSE-lucide.md to
ATTRIBUTION.md to match the library-agnostic framing.
- Swap the ✏️ emoji on the subject-edit button for the pencil glyph.
- Document stroke behavior and glyph provenance on /developers/design.
Claude-Session: https://claude.ai/code/session_01RjCpiDb519vwQx4yDAKpra
* docs(icons): add an "Adding an icon" recipe to /developers/design
Pull the how-to out of the provenance blurb into its own numbered
section: author in the canonical form, drop the kebab-case file in the
folder matching its source, run `make icons`, commit the two generated
files alongside it.
Claude-Session: https://claude.ai/code/session_01RjCpiDb519vwQx4yDAKpra
* docs(icons): condense the icon system's code comments
Several comment blocks on this branch had grown to explain more than the
code needs — the sprite build's module header ran 27 lines, <ol-icon>'s
class JSDoc 22. Trim each to the fact you can't recover by reading the
code (why stroke-width is stripped from the symbol, why the sprite meta
isn't a rel=preload, why the segmented control's glyphs stay inline, why
the IIFE wraps the PURE annotation) and drop the restatement around it.
Regenerates icons.generated.js, whose header the build script emits.
The /developers/design prose is untouched — that's the documentation
itself, not commentary on code.
Claude-Session: https://claude.ai/code/session_01AzJjBQ55TN5JbSkaCiLFUt
* feat(icons): give the gallery a usage popover instead of a silent copy
Clicking a glyph used to copy the Templetor macro with no hint that it
had. Now it opens a shared top-layer panel (native Popover API) showing
all four usage forms — Templetor, Jinja, Lit import, <ol-icon> — each in
a recessed well that copies on click anywhere in it, with a copy glyph
that flips to a check. Browsers without the Popover API keep the old
copy-on-click. Adds Lucide's `copy` icon to the set for the wells.
Claude-Session: https://claude.ai/code/session_01V312UXw8oNocbu5SkC1A42
* fix(icons): re-center the breadcrumb dropdown chevron
The svg chevron was still carrying two PNG-era pixel nudges
(.icon-link__image's top: 3px plus a 6px top margin), landing it ~9px
low. Center it with flex on .dropdown instead; the scoped selector is
needed because mybooks.css loads later and would re-apply the nudge.
Claude-Session: https://claude.ai/code/session_01V312UXw8oNocbu5SkC1A42
* fix(icons): keep the editions sort arrows hidden before the table upgrades
The three sort glyphs are server-rendered and .ol-icon gives them
display: inline-block from render-blocking CSS, but the rule hiding the
inactive ones lived in legacy-datatables.css — which webpack bundles into
the lazily-imported editions-table chunk. Every work page showed three
stacked arrows in both headers until that chunk landed, and permanently
with JS off. Move the .sort-indicator rules into components/editions.css,
which page-book.css already pulls in.
Also exclude icons.generated.js from the custom elements analyzer: it
matches the glob and would otherwise add 43 spurious variable
declarations to the manifest. Its config docstring still described the
manifest as committed, which stopped being true when it moved to
.gitignore.
Claude-Session: https://claude.ai/code/session_01Q4tARNX7XcdQoXHABNDpSc
* refactor(design): drop the CSS coverage report, add an Icon row
The "Not yet documented" section claimed everything it listed was a
genuine gap, which stopped being true: only two registry rows ever set
css_files, so documented components like ol-banner and ol-icon showed up
as gaps. Rather than backfill a field that can only ever apply to the
handful of light-DOM components, remove the report — the two
hand-maintained exclusion sets, css_files, the context field, its CSS,
and the tests that policed the sets for staleness.
Icons now have a row on the Components page so someone scanning the list
finds them instead of concluding there is nothing. It is a pointer: the
tag, a lead naming all three techniques, and one live example. The API
table stays in the Icons section alone, via a new api_table flag on the
registry row.
Also correct the module docstring, which still described three sections
before Icons was added.
Claude-Session: https://claude.ai/code/session_01Q4tARNX7XcdQoXHABNDpSc
* ci: guard the icon system's committed generated files
static/icons/manifest.json and icons.generated.js are built from
static/icons/src but committed, so editing a source and skipping the
build leaves them stale with nothing to catch it. `npm run check:icons`
already rebuilds and diffs them; run it in the JS workflow.
The path filter needs the icon sources and the build script too — a new
.svg alone matched none of the existing patterns, so the one change most
likely to cause drift wouldn't have triggered the workflow.
Claude-Session: https://claude.ai/code/session_01Q4tARNX7XcdQoXHABNDpSc
* Commit the icon sprite instead of building it
The sprite was the only one of the build script's three outputs left
uncommitted, so a checkout that hadn't run `make icons` rendered blank
icons everywhere. That is what happens on testing.openlibrary.org: patch
deploys apply a diff and restart, they never run a build, so the sprite
404s and every glyph draws empty.
Committing it removes the state where the code is present but the asset
isn't — testing, fresh clones and local dev all work with no build step.
The manifest and the Lit glyph module were already committed, so this
makes the three outputs consistent rather than introducing a new idea.
It moves to static/icons/ because static/build/ is gitignored wholesale
and `make clean` does `rm -rf $(BUILD)`, which would delete a committed
file. All four icon artifacts now live in one directory.
Knock-on simplifications: icon_sprite_url() loses the fallback that
existed only for the missing-sprite case, the Makefile target loses the
atomic-swap dance that kept a half-written sprite from being served, and
--out loses its only caller. Symbols are now one per line so the
committed file diffs readably and conflicts can be resolved by rebuild.
check:icons and the pre-commit hook both gained the sprite path — with
the file committed, drift is now possible and those guards are what
catch it.
Claude-Session: https://claude.ai/code/session_01Lv9GuFfV3JRG7hmKGmN1t4
* Defer the legacy image deletions to a follow-up
These 50 files are the only binary content in the PR, and GitHub's .diff
omits binary data — so `git apply` aborts the entire patch unless the
deploy passes --exclude=static/images/*. That one flag was the last thing
standing between this branch and an ordinary patch deploy to testing.
The deletions don't need to ship here. 29 of these have been dead for
years; the other 21 stop being referenced as soon as this PR's call sites
move to the macro. Unreferenced files on disk hurt nothing, so they move
to a follow-up that never has to reach testing.
Also drops the PR from 170 files to 120.
Claude-Session: https://claude.ai/code/session_01Lv9GuFfV3JRG7hmKGmN1t4
* refactor(icons): render every Lit glyph through <ol-icon>
The Lit components each imported a named glyph from icons.generated.js and
hand-wrote the <svg> wrapper around it — a third icon path alongside the
macro and the element, with the wrapper's attributes duplicated at every
call site and free to drift.
They now use <ol-icon name="..."> instead. OlIcon renders the glyph inside
its own shadow root, so it works where <use> can't reach the sprite, and
each host sizes it with plain width/height rules. Stroke weight, where a
component wanted a non-default, moves to --ol-icon-stroke-width.
Drops the lit-import snippet from the design page's icon gallery: with the
glyph module no longer imported by hand, only three usage forms remain.
* build(icons): generate the icon outputs instead of committing them
Committing the sprite, the manifest, and the Lit glyph module bought a
checkout that renders icons with no build, and cost a freshness check in
both CI and pre-commit, plus a merge conflict on every concurrent icon PR.
The build is a dependency-free Node script that runs in well under a
second, so paying it is cheaper than policing the outputs.
`make icons` now writes only the sprite and the glyph module, both
gitignored. `make lit-components` depends on it, so the bundle can't be
built from a stale module, and a pretest:js hook covers the JS tests that
import it. The freshness check and its CI step and pre-commit hook are
gone. The sprite is written to a temp file and renamed, since a rebuild
under a running server would otherwise serve a half-written one.
The manifest existed only to list icon names for the design page's
gallery, which now globs static/icons/src/ — one less generated file, and
a list that can't drift from the sources. icon_sprite_url() falls back to
the unhashed path when the sprite is missing, so a checkout that never ran
`make icons` draws blank icons rather than 500ing every page with one.
* docs(icons): add JSDoc types to build_icon_sprite helpers
Every helper now documents its params and return shape, and parseAttrs and
collectIcons get real descriptions — collectIcons in particular explains why
it enforces both name and identifier uniqueness (the sprite keys on the id,
the Lit module on the export name).
Claude-Session: https://claude.ai/code/session_01MKQA4KK4i8E3osyV98359T
* refactor(icons): fold the macro's two svg branches into one
Only the a11y attributes differed between the labeled and decorative
branches; the conditional now sits inside the tag instead of duplicating
the whole element.
Claude-Session: https://claude.ai/code/session_01LhQSynuMDhyeBxHv96LyCS
* feat(icons): draw segmented-control icons with <ol-icon>
The layout switcher and the component's docs hand-wrote their glyphs
because the control re-renders each segment inside its shadow root,
where a sprite <use> can't resolve. <ol-icon> inlines its glyph, so it
works there — which leaves no inline SVG in the segment call sites.
Adds lucide/layout-grid for the grid segment, and sizes .segment ol-icon
alongside .segment svg (an outer-tree rule beats <ol-icon>'s :host).
Claude-Session: https://claude.ai/code/session_01LhQSynuMDhyeBxHv96LyCS
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Update openlibrary/components/lit/OlIcon.js
Co-authored-by: Drini Cami <[email protected]>
---------
Co-authored-by: Raymond Berger <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Drini Cami <[email protected]>
Makes the OL homepage (only) mobile responsive and uses latest jquery + slick.js