Skip to content

Add <ol-carousel> Lit web component - #13077

Merged
lokesh merged 7 commits into
internetarchive:masterfrom
lokesh:feat/ol-carousel-component
Jul 1, 2026
Merged

Add <ol-carousel> Lit web component#13077
lokesh merged 7 commits into
internetarchive:masterfrom
lokesh:feat/ol-carousel-component

Conversation

@lokesh

@lokesh lokesh commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Related to #13062 — the first extracted, independently-reviewable slice of that (too-large) subject-page redesign draft.

carousel.mp4

[feature] Adds the <ol-carousel> Lit web component — a paged, transform-based horizontal carousel — registers it, and demos it on the developer design page.

Why it matters. Carousels are everywhere on the site (home, subject, author, list pages), and today every one is powered by slick-carousel 1.6.0 — an unmaintained jQuery plugin (archived upstream; pinned to a ~2016 build). <ol-carousel> is a single accessible, framework-agnostic primitive the site can converge on, and the first step toward removing slick-carousel + jQuery from a core UI pattern — done incrementally behind an opt-in flag (a later PR) so there's no big-bang swap.

Slick carousel (today) <ol-carousel>
Dependencies jQuery + slick-carousel 1.6.0 none beyond the already-loaded Lit bundle
Maintenance unmaintained (archived, 2016 build) maintained in-repo
Accessibility offscreen slides stay focusable / screen-reader-visible offscreen items inert + aria-hidden; region/tablist roles
Integration API jQuery events + imperative slide add/remove native ol-carousel-page-change event + attributes

Technical

Foundation only, so low-risk: the component is registered but has no production consumer — nothing on the live site renders it; it appears only on /developers/design. The change is purely additive (no existing component, template, or route is modified — index.js gains one export line). A follow-up PR threads an opt-in web_component flag through the carousel macros to render real book rails with it.

Testing

  • npm run lint clean; Lit bundle builds; existing JS suite unaffected (this PR adds no JS tests — see below).
  • Manual: make lit-components && docker compose restart web, then /developers/designCarousel — arrows page the rail, hide-indicators drops the bar, the page-change demo updates, and arrows scale down on press.

No unit tests here by design. The component's value is its interaction (paging, the page-change event, animation, drag), which a jsdom unit test can't exercise — that coverage belongs in a browser-based (Playwright) suite and will land alongside the first real consumer in the follow-up PR, rather than bolting a repo-wide Jest/Lit test-harness change onto this foundation PR.

Stakeholders

@mekarpeles @cdrini

@lokesh lokesh changed the title Add <ol-carousel> Lit web component (foundation) Add <ol-carousel> Lit web component Jul 1, 2026
@lokesh
lokesh force-pushed the feat/ol-carousel-component branch from 255af84 to 80d4f89 Compare July 1, 2026 05:08
@lokesh
lokesh requested a review from RayBB July 1, 2026 05:11
@lokesh lokesh added the Affects: UI Issues with the web site's user interface. [managed] label Jul 1, 2026
@lokesh
lokesh marked this pull request as ready for review July 1, 2026 05:13
lokesh and others added 6 commits July 1, 2026 01:44
Ports the transform-based OlCarousel web component into the Lit bundle
and registers it, as a reusable foundation for rendering book carousels
without the legacy Slick dependency.

- OlCarousel.js: paged, transform-based horizontal carousel with
  keyboard/pointer paging, inert offscreen items, and an
  ol-carousel-page-change event for incremental loading. Debug console
  logging stripped.
- Export it from components/lit/index.js (importing registers the
  <ol-carousel> custom element).
- Regenerate custom-elements.json to include the component.

No consumer yet — carousels opt in via a later change; the rest of the
site is untouched.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_011xofHmwP8tooS5FMshu1DJ
Surfaces the component on /developers/design alongside the other Lit
components:

- design.html: a "Carousel" nav entry and a demo article with basic
  usage, hide-indicators, and page-change-event examples.
- Document the default slot and the --ol-carousel-* CSS custom
  properties with @slot/@cssprop JSDoc so the auto-generated API tables
  (built from the Custom Elements Manifest in design.py) list them;
  regenerate custom-elements.json.
- page-design.css: a placeholder card style for the demo items.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_011xofHmwP8tooS5FMshu1DJ
Add a tactile press-down (transform: scale(0.92)) to the prev/next arrow
buttons on :active, matching the existing pattern in ol-button, ol-chip,
ol-pagination, and ol-toast. Snaps with no transition, like the others.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_011xofHmwP8tooS5FMshu1DJ
Match the design-page convention: move the inline <ol-carousel> demo
article into design/carousel.html and render it via
render_template("design/carousel", ...), like tooltip/popover/button/etc.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_011xofHmwP8tooS5FMshu1DJ
Rename the ol-carousel hideIndicators prop to showIndicators so page
indicators are hidden by default and opt-in via the show-indicators
attribute. Update the design-page demo and regenerate the manifest.
@RayBB
RayBB force-pushed the feat/ol-carousel-component branch from cd76b9c to 34a33da Compare July 1, 2026 10:16

@RayBB RayBB left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rebased from master and pushed up some small tweaks to use the new jinja templates.

Tested this on my computer and phone and it works beautifully on both.

AI seems to think scroll-snap can get us most of this with less code but I'm guessing you already considered that and there's something we're losing?

The only bug I see is this:

Image

… total

- Clear _draggedPastThreshold in _onPointerUp so a stale flag no longer
  eats the next arrow/indicator click after an off-element or touch
  drag-release (deferred in rAF so the drag's own click stays suppressed).
- Use --focus-width/--color-focus-ring tokens for focus outlines instead
  of a hardcoded hex, matching sibling components.
- Correct documented peek/gap defaults (0.03/8) in JSDoc + manifest.
- Expose page/totalPages getters and seed the demo's page counter on
  updateComplete so it shows the real total instead of '?'.
@lokesh

lokesh commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator Author

Fixed the page number ? bug.
We didn't expose the current page or total pages number from the component as an always available property, thought you could read it from the payload of the fired events like page ol-carousel-page-change. Updated the component to expose as public getters.

CSS scroll-snap
It would get us 80% of the way, but to really dial in the fluid motion, we need to use our own spring animations. This also gives us complete control, so we can take care of a11y, paging math, etc exactly the way we want.

@lokesh
lokesh merged commit 7108b23 into internetarchive:master Jul 1, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Affects: UI Issues with the web site's user interface. [managed]

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants