diff --git a/public/content/documentation/web/component/range-slider.md b/public/content/documentation/web/component/range-slider.md
index 86d7edeb..bf711eb5 100644
--- a/public/content/documentation/web/component/range-slider.md
+++ b/public/content/documentation/web/component/range-slider.md
@@ -94,13 +94,8 @@ While there is a native HTML range input, it is **difficult to style reliably**
```html
-
-
+
+ 10
+
```
-
+
diff --git a/src/components/content-display/markdown-content/markdown-content.tsx b/src/components/content-display/markdown-content/markdown-content.tsx
index bfc04939..0dc0a529 100644
--- a/src/components/content-display/markdown-content/markdown-content.tsx
+++ b/src/components/content-display/markdown-content/markdown-content.tsx
@@ -56,6 +56,63 @@ const MarkdownContent: React.FC = ({
: `${assetBasePath}/${src}`;
return ;
},
+ input: (props) => {
+ const type = (props)?.type;
+
+ if (type !== 'range') {
+ return ;
+ }
+
+ 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) => fn(event)
+ : undefined;
+ const userOnChange =
+ typeof fn === 'function' && eventType === 'onChange'
+ ? (event: React.ChangeEvent) => fn(event)
+ : undefined;
+
+ const syncInputValue = (event: React.SyntheticEvent) => {
+ 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) => {
+ syncInputValue(e);
+ if (userOnInput) userOnInput(e);
+ };
+
+ const onChange = (e: React.ChangeEvent) => {
+ syncInputValue(e);
+ if (userOnChange) userOnChange(e);
+ };
+
+ return (
+
+ );
+ },
a: (props) => {
const fnKey = (props as any)['data-fn'];
const eventType = (props as any)['data-event'] || 'onClick';
diff --git a/src/shared/content.json b/src/shared/content.json
index 90eafeac..c2a96d3c 100644
--- a/src/shared/content.json
+++ b/src/shared/content.json
@@ -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
\n How much cowbell?\n
\n
\n
\n
\n
\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
\n \n \n
\n \n \n
\n
\n```\n\n"
+ "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
\n How much cowbell?\n
\n
\n
\n
\n
\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
\n \n 10\n
\n \n \n
\n \n
\n```\n\n\n
\n 10\n
\n \n \n
\n
\n"
},
{
"label": "Scrolling Container",
diff --git a/src/utils/markdownFunctions.ts b/src/utils/markdownFunctions.ts
index 4b5e6bc4..5b981079 100644
--- a/src/utils/markdownFunctions.ts
+++ b/src/utils/markdownFunctions.ts
@@ -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.
*
@@ -21,7 +21,7 @@ import { NavigateFunction } from 'react-router-dom';
*/
export const getMarkdownFunctionMap = (
navigate: NavigateFunction
-): Record) => void> => ({
+): Record void> => ({
showAlert: () => alert('This works with a keyboard and a mouse!'),
showAlertWhenDisabled: () =>
alert('This disabled button is still actionable for mouse and screen readers users!'),
@@ -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);
@@ -180,10 +180,10 @@ 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) {
@@ -191,7 +191,7 @@ export const getMarkdownFunctionMap = (
if (liveRegion) {
liveRegion.innerHTML = `Quantity updated, ${currentIndex}`;
-
+
setTimeout(() => {
liveRegion.innerHTML = '';
}, 2000);
@@ -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));
-
+
},