tabatkins / css-toggle

Proposal for a CSS Toggle spec
Creative Commons Zero v1.0 Universal
28 stars 1 forks source link

Toggles for "slideshow"-style usage #47

Open tabatkins opened 1 year ago

tabatkins commented 1 year ago

Toggles seem reasonable fit to represent slideshows as well - each slide has a toggle, with a group on the root ensuring that only one is displayed at a time, and each using toggle-visibility to hide it when it's inactive (but allowing a deeplink to immediately reveal the correct slide, per toggle-visibility activation behavior). And once we get focus/tabbing effects ironed out, it could even navigate properly automatically, so long as the slide is focused - hitting arrows would switch between tabs, just like they switch between radio buttons in a group today.

However, it ends up being incredibly annoying to have an on-screen next/prev button. Since these need to activate the neighboring toggles, you have to do some very awkward placement of them in the DOM, with manual positioning of the appropriate ones from the preceding and following slide.

Alternately, you can abandon the grouped toggles altogether and just use a single toggle with N values, associating each slide with one of the values. This loses a lot of the implicit structure we'll want to capture with our a11y heuristics, and also requires a bunch of funky CSS written per slide, since we can't automatically associate toggle values with element indexes. Very awkward all around.


My proposal to fix this is to let toggle-trigger target toggle groups instead of just toggles. With a group keyword, like toggle-trigger: group --slide next;, you instead find the nearest group of that name, and activate the next toggle in the group after the currently activated one. (Or prev, or Nth, with the 0th value being "all inactive".) (Essentially, pretend the group is a toggle with N active values, one per sub-toggle.)

Then the markup and CSS would just be:

<body>
    <div class=slide>...</div>
    <div class=slide>...</div>
    <button id=next-slide>Next</button>
    <button id=prev-slide>Prev</button>
</body>
<style>
body {
    toggle-group: --slide;
}
.slide {
    toggle-root: --slide;
    toggle-visibility: toggle --slide;
}
.slide:first-child {
    toggle-root: --slide 1 of 1;
}
#next-slide {
    toggle-trigger: group --slide next;
    position: absolute;
    inset: auto 0 0 auto;
}
#prev-slide {
    toggle-trigger: group --slide prev;
    position: absolute;
    inset: 0 auto auto 0;
}
</style>

The most obvious use of this is as described - just cycling thru the toggles and activating them by setting to the first active state. Maybe I could opt into a "next state" mode as well, where we advance the currently-active toggle to its next state, and if it's currently at the end of its state list instead activate the next toggle? I'd probably want to gather some real-world use-cases before I made this a thing, but the syntax as written allows for adding this later.

dbaron commented 1 year ago

Yeah, I think letting toggle-trigger activate groups as well is a reasonably straightforward enhancement that helps with use cases like this. +1 to this idea.

Also cc @bramus since this has some similarities to his proposal.

bramus commented 1 year ago

My proposal to fix this is to let toggle-trigger target toggle groups instead of just toggles. With a group keyword, like toggle-trigger: group --slide next; […] The most obvious use of this is as described - just cycling thru the toggles and activating them by setting to the first active state.

I like this. The code looks much nicer now.

Maybe I could opt into a "next state" mode as well, where we advance the currently-active toggle to its next state, and if it's currently at the end of its state list instead activate the next toggle? I'd probably want to gather some real-world use-cases before I made this a thing, but the syntax as written allows for adding this later.

These would be values for <trigger-action>? E.g. next-state and prev-state?

tabatkins commented 1 year ago

These would be values for <trigger-action>? E.g. next-state and prev-state?

Yup!