Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
25 changes: 6 additions & 19 deletions public/content/documentation/web/component/range-slider.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,8 @@ While there is a native HTML range input, it is **difficult to style reliably**

```html
<div class="range-group">
<!-- Input hidden from the screen reader
and keyboard to avoid repetition -->
<input tabindex="-1"
value="10"
aria-hidden="true"
class="range-value"
id="cowbell-range-value">
<!-- Value display hidden from assistive tech to avoid repetition -->
<span aria-hidden="true" class="range-value" id="cowbell-range-value">10</span>
<div>
<label for="cowbell-range">
How much cowbell?
Expand All @@ -113,20 +108,13 @@ While there is a native HTML range input, it is **difficult to style reliably**
value="10"
step="1">
</div>

</div>
```

<!-- TODO: styling and js? need to be added to help this demo function!

<example>
<div class="range-group">
Input hidden from the screen reader (comment out later)
and keyboard to avoid repetition (comment out later)
<input tabindex="-1"
value="10"
aria-hidden="true"
class="range-value"
id="cowbell-range-value">
<span aria-hidden="true" class="range-value" id="cowbell-range-value">10</span>
<div>
<label for="cowbell-range">
How much cowbell?
Expand All @@ -135,9 +123,8 @@ While there is a native HTML range input, it is **difficult to style reliably**
id="cowbell-range"
name="cowbell"
min="0"
max="11"
value="10"
max="10"
step="1">
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

There's no styling here yet, but if the functionality checks out, I can spice it up.

</div>
</div>
</example> -->
</example>
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,63 @@ const MarkdownContent: React.FC<MarkdownContentProps> = ({
: `${assetBasePath}/${src}`;
return <source src={resolvedSrc} type={type} />;
},
input: (props) => {
const type = (props)?.type;

if (type !== 'range') {
return <input {...props} />;
}

const fnKey = (props as any)['data-fn'];
const eventType = (props as any)['data-event'] || 'onInput';
const fn = fnKey && markdownFunctionMap[fnKey];
const min = (props).min ?? 0;
const max = (props).max ?? 100;
const step = (props).step ?? 1;

const userOnInput =
typeof fn === 'function' && (eventType === 'onInput' || !eventType)
? (event: React.FormEvent<HTMLInputElement>) => fn(event)
: undefined;
const userOnChange =
typeof fn === 'function' && eventType === 'onChange'
? (event: React.ChangeEvent<HTMLInputElement>) => fn(event)
: undefined;

const syncInputValue = (event: React.SyntheticEvent<HTMLInputElement>) => {
const target = event.currentTarget as HTMLInputElement | null;
if (!target) return;
const group = (target as HTMLElement).closest('.range-group');
if (!group) return;
const valueEl = group.querySelector('.range-value') as HTMLElement | null;
if (!valueEl) return;

valueEl.textContent = target.value;
valueEl.setAttribute('data-value', target.value);
};

const onInput = (e: React.FormEvent<HTMLInputElement>) => {
syncInputValue(e);
if (userOnInput) userOnInput(e);
};

const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
syncInputValue(e);
if (userOnChange) userOnChange(e);
};

return (
<input
{...props}
type="range"
min={min}
max={max}
step={step}
onInput={onInput}
onChange={onChange}
/>
);
},
a: (props) => {
const fnKey = (props as any)['data-fn'];
const eventType = (props as any)['data-event'] || 'onClick';
Expand Down
2 changes: 1 addition & 1 deletion src/shared/content.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@
"videos": null,
"androidDeveloperNotes": null,
"iosDeveloperNotes": null,
"developerNotes": "## Code examples\n\nThis is one of the exceedingly rare instances where a custom element makes a lot of sense.\n\n### Use a custom element\n\n* Custom elements are **easier to style reliably** across browsers.\n* [Working slider pattern examples](https://www.w3.org/WAI/ARIA/apg/patterns/slider/)\n\n```html\n<div id=\"range-label\">\n How much cowbell?\n</div>\n<div class=\"track\">\n <div id=\"thumb\"\n role=\"slider\"\n tabindex=\"0\"\n aria-valuemin=\"0\"\n aria-valuenow=\"10\"\n aria-valuemax=\"11\"\n aria-labelledby=\"range-label\">\n </div>\n</div>\n```\n\n### Semantic HTML\n\nWhile there is a native HTML range input, it is **difficult to style reliably** across browsers.\n\n```html\n<div class=\"range-group\">\n <!-- Input hidden from the screen reader \n and keyboard to avoid repetition -->\n <input tabindex=\"-1\" \n value=\"10\" \n aria-hidden=\"true\"\n class=\"range-value\" \n id=\"cowbell-range-value\">\n <div>\n <label for=\"cowbell-range\">\n How much cowbell?\n </label>\n <input type=\"range\"\n id=\"cowbell-range\"\n name=\"cowbell\"\n min=\"0\"\n max=\"11\"\n value=\"10\"\n step=\"1\">\n </div>\n</div>\n```\n\n<!-- TODO: styling and js? need to be added to help this demo function! \n\n<example>\n<div class=\"range-group\">\n Input hidden from the screen reader (comment out later)\n and keyboard to avoid repetition (comment out later)\n <input tabindex=\"-1\" \n value=\"10\" \n aria-hidden=\"true\"\n class=\"range-value\" \n id=\"cowbell-range-value\">\n <div>\n <label for=\"cowbell-range\">\n How much cowbell?\n </label>\n <input type=\"range\"\n id=\"cowbell-range\"\n name=\"cowbell\"\n min=\"0\"\n max=\"11\"\n value=\"10\"\n step=\"1\">\n </div>\n</div>\n</example> -->"
"developerNotes": "## Code examples\n\nThis is one of the exceedingly rare instances where a custom element makes a lot of sense.\n\n### Use a custom element\n\n* Custom elements are **easier to style reliably** across browsers.\n* [Working slider pattern examples](https://www.w3.org/WAI/ARIA/apg/patterns/slider/)\n\n```html\n<div id=\"range-label\">\n How much cowbell?\n</div>\n<div class=\"track\">\n <div id=\"thumb\"\n role=\"slider\"\n tabindex=\"0\"\n aria-valuemin=\"0\"\n aria-valuenow=\"10\"\n aria-valuemax=\"11\"\n aria-labelledby=\"range-label\">\n </div>\n</div>\n```\n\n### Semantic HTML\n\nWhile there is a native HTML range input, it is **difficult to style reliably** across browsers.\n\n```html\n<div class=\"range-group\">\n <!-- Value display hidden from assistive tech to avoid repetition -->\n <span aria-hidden=\"true\" class=\"range-value\" id=\"cowbell-range-value\">10</span>\n <div>\n <label for=\"cowbell-range\">\n How much cowbell?\n </label>\n <input type=\"range\"\n id=\"cowbell-range\"\n name=\"cowbell\"\n min=\"0\"\n max=\"11\"\n value=\"10\"\n step=\"1\">\n </div>\n \n</div>\n```\n\n<example>\n<div class=\"range-group\">\n <span aria-hidden=\"true\" class=\"range-value\" id=\"cowbell-range-value\">10</span>\n <div>\n <label for=\"cowbell-range\">\n How much cowbell?\n </label>\n <input type=\"range\"\n id=\"cowbell-range\"\n name=\"cowbell\"\n min=\"0\"\n max=\"10\"\n step=\"1\">\n </div>\n</div>\n</example>"
},
{
"label": "Scrolling Container",
Expand Down
22 changes: 11 additions & 11 deletions src/utils/markdownFunctions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NavigateFunction } from 'react-router-dom';

import React from 'react';
/**
* A map of callable functions that can be referenced inside Markdown files rendered as HTML.
*
Expand All @@ -21,7 +21,7 @@ import { NavigateFunction } from 'react-router-dom';
*/
export const getMarkdownFunctionMap = (
navigate: NavigateFunction
): Record<string, (event: React.MouseEvent<Element>) => void> => ({
): Record<string, (event: React.SyntheticEvent) => void> => ({
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I changed MouseEvent to SyntheticEvent to generalize the Markdown function handler type to accept any React synthetic event. This allows buttons/links/divs (mouse events) and inputs (form/change events) are all supported consistently.

showAlert: () => alert('This works with a keyboard and a mouse!'),
showAlertWhenDisabled: () =>
alert('This disabled button is still actionable for mouse and screen readers users!'),
Expand Down Expand Up @@ -156,16 +156,16 @@ export const getMarkdownFunctionMap = (
if (!stepperSelect || stepperSelect.tagName.toLowerCase() !== 'select') {
return; // Exit if the provided element is not a select element
}

let currentIndex = stepperSelect.selectedIndex;
let nextIndex = currentIndex + 1;

if (nextIndex < stepperSelect.options.length) {
stepperSelect.selectedIndex = nextIndex;

if (liveRegion) {
liveRegion.innerHTML = `Quantity updated, ${nextIndex+1}`;

setTimeout(() => {
liveRegion.innerHTML = '';
}, 2000);
Expand All @@ -180,18 +180,18 @@ export const getMarkdownFunctionMap = (
if (!stepperSelect || stepperSelect.tagName.toLowerCase() !== 'select') {
return; // Exit if the provided element is not a select element
}

let currentIndex = stepperSelect.selectedIndex;
let nextIndex = currentIndex - 1;

if (currentIndex===0) {
return; // do nothing if at 0
} else if (nextIndex < stepperSelect.options.length) {
stepperSelect.selectedIndex = nextIndex;

if (liveRegion) {
liveRegion.innerHTML = `Quantity updated, ${currentIndex}`;

setTimeout(() => {
liveRegion.innerHTML = '';
}, 2000);
Expand Down Expand Up @@ -221,11 +221,11 @@ export const getMarkdownFunctionMap = (

// Get current state
const isExpanded = toggleButton.getAttribute('aria-expanded') === 'true';
// Toggle the state - use only aria-expanded attribute

// Toggle the state - use only aria-expanded attribute
const newExpandedState = !isExpanded;
toggleButton.setAttribute('aria-expanded', String(newExpandedState));

},


Expand Down