|
1 | | -import type { Ref } from 'react'; |
2 | 1 | import type { LabelProps as AriaLabelProps, ContextValue } from 'react-aria-components'; |
3 | 2 |
|
4 | 3 | import { cva, cx } from 'class-variance-authority'; |
5 | | -import { createContext } from 'react'; |
| 4 | +import { createContext, type Ref } from 'react'; |
6 | 5 | import { Label as AriaLabel } from 'react-aria-components'; |
7 | 6 |
|
8 | 7 | import styles from './styles/Label.module.css'; |
9 | 8 | import { useLPContextProps } from './utils'; |
10 | 9 |
|
11 | | -const labelStyles = cva(styles.label); |
12 | | - |
13 | | -interface LabelProps extends AriaLabelProps { |
| 10 | +const labelStyles = cva(styles.label, { |
| 11 | + variants: { |
| 12 | + size: { |
| 13 | + small: styles.small, |
| 14 | + medium: styles.medium, |
| 15 | + }, |
| 16 | + }, |
| 17 | + defaultVariants: { |
| 18 | + size: 'medium', |
| 19 | + }, |
| 20 | +}); |
| 21 | + |
| 22 | +interface LabelProps extends Omit<AriaLabelProps, 'className'> { |
14 | 23 | ref?: Ref<HTMLLabelElement>; |
| 24 | + size?: 'small' | 'medium'; |
| 25 | + /** Maximum number of lines to display. Overflowing text will be truncated with an ellipsis. */ |
| 26 | + maxLines?: number; |
| 27 | + /** Optional CSS class name */ |
| 28 | + className?: AriaLabelProps['className']; |
15 | 29 | } |
16 | 30 |
|
17 | 31 | const LabelContext = createContext<ContextValue<LabelProps, HTMLLabelElement>>(null); |
18 | 32 |
|
19 | | -const Label = ({ ref, ...props }: LabelProps) => { |
20 | | - [props, ref] = useLPContextProps(props, ref, LabelContext); |
21 | | - const { className } = props; |
22 | | - |
23 | | - return <AriaLabel {...props} ref={ref} className={cx(labelStyles({ className }))} />; |
| 33 | +/** |
| 34 | + * A generic Label component for form labels. |
| 35 | + * |
| 36 | + * For body text, use `Text`. For headings, use `Heading` |
| 37 | + * |
| 38 | + * Built on top of [React Aria `Label` component](https://react-spectrum.adobe.com/react-spectrum/Label.html#label). |
| 39 | + */ |
| 40 | +const Label = ({ ref, maxLines, style, size, ...props }: LabelProps) => { |
| 41 | + const [contextProps, contextRef] = useLPContextProps(props, ref, LabelContext); |
| 42 | + const { className } = contextProps as any; |
| 43 | + |
| 44 | + return ( |
| 45 | + <AriaLabel |
| 46 | + {...contextProps} |
| 47 | + ref={contextRef} |
| 48 | + className={cx(labelStyles({ size }), maxLines && styles.truncate, className, props.className)} |
| 49 | + style={{ |
| 50 | + ...style, |
| 51 | + ...(maxLines && { |
| 52 | + WebkitLineClamp: maxLines, |
| 53 | + }), |
| 54 | + }} |
| 55 | + /> |
| 56 | + ); |
24 | 57 | }; |
25 | 58 |
|
| 59 | +Label.displayName = 'Label'; |
| 60 | + |
26 | 61 | export { Label, LabelContext, labelStyles }; |
27 | 62 | export type { LabelProps }; |
0 commit comments