nicolium: use aria-labelledby and describedby
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
@ -36,6 +36,8 @@ const ListItem: React.FC<IListItem> = ({
|
||||
...rest
|
||||
}) => {
|
||||
const [domId] = useState(`list-group-${crypto.randomUUID()}`);
|
||||
const labelId = `${domId}-label`;
|
||||
const hintId = `${domId}-hint`;
|
||||
|
||||
const onKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter') {
|
||||
@ -50,10 +52,22 @@ const ListItem: React.FC<IListItem> = ({
|
||||
React.Children.map(children, (child) => {
|
||||
if (React.isValidElement(child)) {
|
||||
const isSelect = child.type === SelectDropdown || child.type === Select;
|
||||
const childLabelledBy = child.props['aria-labelledby'];
|
||||
const childDescribedBy = child.props['aria-describedby'];
|
||||
const ariaLabelledBy = childLabelledBy ? `${childLabelledBy} ${labelId}` : labelId;
|
||||
const ariaDescribedBy = hint
|
||||
? childDescribedBy
|
||||
? `${childDescribedBy} ${hintId}`
|
||||
: hintId
|
||||
: childDescribedBy;
|
||||
|
||||
return React.cloneElement(child, {
|
||||
// @ts-ignore
|
||||
id: domId,
|
||||
// @ts-ignore
|
||||
'aria-labelledby': ariaLabelledBy,
|
||||
// @ts-ignore
|
||||
'aria-describedby': ariaDescribedBy,
|
||||
className: clsx(
|
||||
{
|
||||
'w-auto': isSelect,
|
||||
@ -65,7 +79,7 @@ const ListItem: React.FC<IListItem> = ({
|
||||
|
||||
return null;
|
||||
}),
|
||||
[children, domId],
|
||||
[children, domId, labelId, hint, hintId],
|
||||
);
|
||||
|
||||
const classNames = clsx('⁂-list-item', className, {
|
||||
@ -76,9 +90,15 @@ const ListItem: React.FC<IListItem> = ({
|
||||
const body = (
|
||||
<>
|
||||
<div className='⁂-list-item__label'>
|
||||
<LabelComp htmlFor={domId}>{label}</LabelComp>
|
||||
<LabelComp id={labelId} {...(LabelComp === 'label' ? { htmlFor: domId } : {})}>
|
||||
{label}
|
||||
</LabelComp>
|
||||
|
||||
{hint ? <span className='⁂-list-item__hint'>{hint}</span> : null}
|
||||
{hint ? (
|
||||
<span id={hintId} className='⁂-list-item__hint'>
|
||||
{hint}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{'to' in rest || href || onClick ? (
|
||||
|
||||
@ -6,6 +6,8 @@ import { getPointerPosition } from '@/features/video';
|
||||
|
||||
interface ISlider {
|
||||
id?: string;
|
||||
'aria-labelledby'?: string;
|
||||
'aria-describedby'?: string;
|
||||
/** Value between 0 and 1. */
|
||||
value: number;
|
||||
/** Callback when the value changes. */
|
||||
@ -13,7 +15,13 @@ interface ISlider {
|
||||
}
|
||||
|
||||
/** Draggable slider component. */
|
||||
const Slider: React.FC<ISlider> = ({ id, value, onChange }) => {
|
||||
const Slider: React.FC<ISlider> = ({
|
||||
id,
|
||||
value,
|
||||
onChange,
|
||||
'aria-labelledby': ariaLabelledby,
|
||||
'aria-describedby': ariaDescribedby,
|
||||
}) => {
|
||||
const node = useRef<HTMLDivElement>(null);
|
||||
const keyboardAnimationTimeout = useRef<number | null>(null);
|
||||
const [animateKeyboardInput, setAnimateKeyboardInput] = useState<boolean>(false);
|
||||
@ -154,6 +162,8 @@ const Slider: React.FC<ISlider> = ({ id, value, onChange }) => {
|
||||
aria-valuemax={1}
|
||||
aria-valuenow={value}
|
||||
aria-orientation='horizontal'
|
||||
aria-labelledby={ariaLabelledby}
|
||||
aria-describedby={ariaDescribedby}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -5,6 +5,8 @@ import { getPointerPosition } from '@/features/video';
|
||||
|
||||
interface IStepSlider {
|
||||
id?: string;
|
||||
'aria-labelledby'?: string;
|
||||
'aria-describedby'?: string;
|
||||
/** Value between 0 and the amount of steps minus one. */
|
||||
value: number;
|
||||
/** Steps available in the slider. */
|
||||
@ -14,7 +16,14 @@ interface IStepSlider {
|
||||
}
|
||||
|
||||
/** Slider allowing selecting integers in a given range. */
|
||||
const StepSlider: React.FC<IStepSlider> = ({ id, value, steps, onChange }) => {
|
||||
const StepSlider: React.FC<IStepSlider> = ({
|
||||
id,
|
||||
value,
|
||||
steps,
|
||||
onChange,
|
||||
'aria-labelledby': ariaLabelledby,
|
||||
'aria-describedby': ariaDescribedby,
|
||||
}) => {
|
||||
const node = useRef<HTMLDivElement>(null);
|
||||
|
||||
const handleMouseDown: React.MouseEventHandler = (e) => {
|
||||
@ -121,6 +130,8 @@ const StepSlider: React.FC<IStepSlider> = ({ id, value, steps, onChange }) => {
|
||||
aria-valuemax={steps - 1}
|
||||
aria-valuenow={value}
|
||||
aria-orientation='horizontal'
|
||||
aria-labelledby={ariaLabelledby}
|
||||
aria-describedby={ariaDescribedby}
|
||||
onKeyDown={handleKeyDown}
|
||||
style={{ left: `calc(${(value / (steps - 1)) * 100}% + 0.125rem)` }}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user