Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Toggle #69

Merged
merged 6 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions src/aria.css
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,63 @@
width: fit-content;
text-align: center;
}

label:has([role=switch]:last-child) {
display: flex;
gap: var(--gap);
justify-content: space-between;
}

label[for]:has(+ [role=switch]),
label[for] + [role=switch],
[role=switch]:has(+ label[for]),
[role=switch] + label[for] {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
label[for]:has(+ [role=switch]),
label[for] + [role=switch],
[role=switch]:has(+ label[for]),
[role=switch] + label[for] {
label[for]:has(+ &),
label[for] + &,
&:has(+ label[for]),
& + label[for] {

I don't particularly like that my solution involves specifying label selectors in the aria.css file, where all the other parent selectors are just [role=thing]. It would be nice if I could move them inside the [role=switch] block somehow (or not include them).

display: inline-block;
padding-block: calc(var(--gap) / 4);
}

[role=switch], [aria-pressed] {
--toggle-border-width: 0.15em;
all: unset;
appearance: none;
cursor: pointer;
display: grid !important;
grid-gap: 0;
transition: all 0.25s ease-in-out;
vertical-align: bottom;

&::before, &::after {
content: '';
display: inline-block;
height: var(--rhythm);
border: var(--toggle-border-width) solid var(--graphical-fg);
}
&::before {
width: calc(2 * var(--rhythm));
background-color: var(--bg);
border-radius: var(--rhythm);
grid-row: 1;
grid-column: 1 / 3;
}
&::after {
width: var(--rhythm);
background-color: var(--interactive-bg);
border-radius: 50%;
grid-row: 1;
grid-column: 1 / 2;
}
&:is(:checked, [aria-pressed=true]) {
&::before { background-color: var(--accent); }
&::after { grid-column: 2 / 3; }
}

&:is(:hover, :focus-visible) {
/* Reset button styles */
filter: unset;
box-shadow: none;
}
&:active {
box-shadow: none;
color: inherit;
}
}
2 changes: 1 addition & 1 deletion src/core/sanitize.css
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ button, input, select {
* Correct the inability to style buttons in iOS and Safari.
*/

button, [type="button"], [type="reset"], [type="submit"]) {
button, [type="button"], [type="reset"], [type="submit"] {
-webkit-appearance: button;
}

Expand Down
50 changes: 25 additions & 25 deletions src/js/19.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/**
* a DOM helper library.
* "1 US$ = 18.5842 TR₺ · Oct 16, 2022, 20:52 UTC"
*/
Expand Down Expand Up @@ -42,13 +42,13 @@
/**
* Creates a logging function.
* The {@link scope} will be prepended to each message logged.
*
*
* We usually use `ilog` as a name for the resulting function.
* It returns its last argument,
* which makes it easier to log intermediate values in an expression:
*
*
* const x = a + ilog("b:", b); // x = a + b
*
*
* @param {string} scope The name of the component/module/etc. that will use this logger.
* @returns {Logger} The `ilog` function.
*/
Expand Down Expand Up @@ -103,26 +103,26 @@ export function traverse(
? $(root, selector)
: $$(root, selector).at(-1);
}

if (!current) return wrapIt();

// Traverse left to right, bottom to top.
//
// (begin ascii art diagram)
// (R)
// / \
// / \
// (r) (4) <- return value
// / | \ / \
// current -> (1) (2) (3) (*) (*)
// (end diagram)
//
// In the diagram above, 1, 2, 3 are tested by the selector (assuming we
// start at 1). Then, having run out of siblings, we move up (as many times
// as needed) before advancing, ending up at 4.
// as needed) before advancing, ending up at 4.
//
// To "test" an element, ee call Element#matches, then if that returns false,
// querySelector. The querySelector call is how the items marked with
// asterisks can be checked.
// asterisks can be checked.
let cursor = current;
while (true) {
while (cursor[advance] === null) { // 3
Expand Down Expand Up @@ -169,7 +169,7 @@ export function $$(scope, sel) {
* @property {EventTarget} target
* @property {string} type
* @property {EventListener} listener
* @property {object} options
* @property {object} options
*/

/**
Expand Down Expand Up @@ -211,7 +211,7 @@ export function off({ target, type, listener, options }) {
/**
* "Halt" an event -- convenient wrapper for `preventDefault`, `stopPropagation`, and `stopImmediatePropagation`.
* @param {string} o - How to halt. Space-separated list of "default", "bubbling" and "propagation".
* @param {Event} e - The event.
* @param {Event} e - The event.
*/
export function halt(o, e) {
for (const t of o.split(" ")) {
Expand All @@ -226,7 +226,7 @@ export function halt(o, e) {

/**
* Decorator for any event listener to call {@link halt}.
*
*
* on(el, "click", halts("default", e => ...))
*
* @template {Event} T
Expand All @@ -251,13 +251,13 @@ export function dispatch(el, type, detail, options) {

/**
* Get, remove or set an attribute.
*
*
* - attr(el, "name") Get the attribute "name"
* - attr(el, "name", "value") Set the attribute "name" to "value"
* - attr(el, "name", null) Remove the attribute "name"
* - attr(el, [ nameA: "valueA", nameB: "valueB" ]) Set the attributes name-a to "valueA", name-b to "valueB"
*
* @param {Element} el
*
* @param {Element} el
* @param {string | Record<string, unknown>} name - The attribute name **or** a map of names to values.
* If an object is passed, camelCase attribute names will be converted to kebab-case.
* @param {unknown} value - The value of the attribute, when setting. Pass `null` to remove an attribute.
Expand Down Expand Up @@ -333,9 +333,9 @@ export function htmlescape(s) {
* Template literal that escapes HTML in interpolated values and returns a DocumentFragment.
* Can also be called with a string to parse it as HTML.
* To let trusted HTML through escaping, parse it first:
*
*
* html`<p>My trusted markup: ${html(trustedMarkup)}</p>`
*
*
* @param {TemplateStringsArray | string} str
* @param {...unknown} values
* @returns {DocumentFragment}
Expand Down Expand Up @@ -421,10 +421,10 @@ export function prev(root, selector, current, options = {}) {

/**
* Create a handler for keyboard events using a keyboard shortcut DSL.
*
*
* - "ArrowLeft"
* - "Ctrl+Alt+3"
*
*
* @param {Record<string, KeyboardEventListener>} hotkeys
* @returns KeyboardEventListener
*/
Expand All @@ -440,7 +440,7 @@ export function hotkey(hotkeys) {
const
tokens = hotkeySpec.split("+"), key = /** @type {string} */ (tokens.pop());
let modifiers = 0 | 0;
for (const token in tokens)
for (const token of tokens)
switch (token.toLowerCase()) {
case "alt": modifiers |= alt; break;
case "ctrl": modifiers |= ctrl; break;
Expand All @@ -460,8 +460,8 @@ export function hotkey(hotkeys) {

/**
* Debounce a function.
*
* @template {unknown[]} TArgs
*
* @template {unknown[]} TArgs
* @param {number} t The debounce time.
* @param {(...args: TArgs) => void} f The function.
* @param {object} [options]
Expand Down Expand Up @@ -507,13 +507,13 @@ export function behavior(selector, init) {
/**
* @template TData
* @typedef {object} Repeater
*
*
* @property {(datum: TData) => string} idOf
* Returns the HTML id for a given data value.
*
*
* @property {(datum: TData, ctx: { id: string }) => ChildNode} create
* Creates a an element for a data value.
*
*
* @property {(el: Element, datum: TData) => Element | null} update
* Update an element for a new data value.
*/
Expand Down
Loading