1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
import {
forwardRef,
type ReactNode,
type ForwardRefRenderFunction,
type HTMLAttributes,
useId,
} from 'react';
import styles from './figure.module.scss';
export type FigureProps = Omit<HTMLAttributes<HTMLElement>, 'children'> & {
/**
* The contents (ie. an image, illustration, diagram, code snippet, etc.).
*/
children?: ReactNode;
/**
* A figure caption.
*/
caption?: ReactNode;
/**
* Should we wrap the contents with borders?
*/
hasBorders?: boolean;
};
const FigureWithRef: ForwardRefRenderFunction<HTMLElement, FigureProps> = (
{
'aria-labelledby': ariaLabelledBy,
caption,
children,
className = '',
hasBorders,
...props
},
ref
) => {
const captionId = useId();
const bordersModifier = hasBorders ? styles['wrapper--has-borders'] : '';
const figureClass = `${styles.wrapper} ${bordersModifier} ${className}`;
/**
* We need to ensure that the figcaption is used as an accessible name for the
* figure. In Testing Library, it is not automatically associated, it could
* also be the case in some browsers. However if the consumer provide its own
* `aria-labelled-by` attribute, it should be used instead of the caption (we
* could combine them but we cannot know which order is the more logical).
*/
const figureLabelledBy =
caption && !ariaLabelledBy ? captionId : ariaLabelledBy;
return (
<figure
{...props}
aria-labelledby={figureLabelledBy}
className={figureClass}
ref={ref}
>
{children}
{caption ? (
<figcaption className={styles.caption} id={captionId}>
{caption}
</figcaption>
) : null}
</figure>
);
};
/**
* Figure component
*
* Render a responsive image wrapped in a figure element.
*/
export const Figure = forwardRef(FigureWithRef);
|