Skip to content

Commit 48c1691

Browse files
authored
feat(react-label): add useLabelBase_unstable hook (#35905)
1 parent 5016229 commit 48c1691

8 files changed

Lines changed: 65 additions & 16 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "minor",
3+
"comment": "feat: add useLabelBase_unstable hook",
4+
"packageName": "@fluentui/react-label",
5+
"email": "dmytrokirpa@microsoft.com",
6+
"dependentChangeType": "patch"
7+
}

packages/react-components/react-label/library/etc/react-label.api.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ import type { SlotClassNames } from '@fluentui/react-utilities';
1515
// @public
1616
export const Label: ForwardRefComponent<LabelProps>;
1717

18+
// @public
19+
export type LabelBaseProps = Omit<LabelProps, 'size' | 'weight'>;
20+
21+
// @public
22+
export type LabelBaseState = Omit<LabelState, 'size' | 'weight'>;
23+
1824
// @public (undocumented)
1925
export const labelClassNames: SlotClassNames<LabelSlots>;
2026

@@ -36,11 +42,14 @@ export type LabelSlots = {
3642
export type LabelState = ComponentState<LabelSlots> & Required<Pick<LabelProps, 'disabled' | 'size' | 'weight'>>;
3743

3844
// @public
39-
export const renderLabel_unstable: (state: LabelState) => JSXElement;
45+
export const renderLabel_unstable: (state: LabelBaseState) => JSXElement;
4046

4147
// @public
4248
export const useLabel_unstable: (props: LabelProps, ref: React_2.Ref<HTMLElement>) => LabelState;
4349

50+
// @public
51+
export const useLabelBase_unstable: (props: LabelBaseProps, ref: React_2.Ref<HTMLLabelElement>) => LabelBaseState;
52+
4453
// @public
4554
export const useLabelStyles_unstable: (state: LabelState) => LabelState;
4655

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
export type { LabelProps, LabelSlots, LabelState } from './components/Label/index';
1+
export type { LabelBaseProps, LabelBaseState, LabelProps, LabelSlots, LabelState } from './components/Label/index';
22
export {
33
Label,
44
labelClassNames,
55
renderLabel_unstable,
66
useLabelStyles_unstable,
77
useLabel_unstable,
8+
useLabelBase_unstable,
89
} from './components/Label/index';

packages/react-components/react-label/library/src/components/Label/Label.types.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,14 @@ export type LabelSlots = {
3939
* State used in rendering Label
4040
*/
4141
export type LabelState = ComponentState<LabelSlots> & Required<Pick<LabelProps, 'disabled' | 'size' | 'weight'>>;
42+
43+
/**
44+
* Label props without design-specific props (size, weight).
45+
* Use this when building a label that is unstyled or uses a custom design system.
46+
*/
47+
export type LabelBaseProps = Omit<LabelProps, 'size' | 'weight'>;
48+
49+
/**
50+
* Label state without design-specific state (size, weight).
51+
*/
52+
export type LabelBaseState = Omit<LabelState, 'size' | 'weight'>;
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export { Label } from './Label';
2-
export type { LabelProps, LabelSlots, LabelState } from './Label.types';
2+
export type { LabelBaseProps, LabelBaseState, LabelProps, LabelSlots, LabelState } from './Label.types';
33
export { renderLabel_unstable } from './renderLabel';
4-
export { useLabel_unstable } from './useLabel';
4+
export { useLabel_unstable, useLabelBase_unstable } from './useLabel';
55
export { labelClassNames, useLabelStyles_unstable } from './useLabelStyles.styles';

packages/react-components/react-label/library/src/components/Label/renderLabel.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33

44
import { assertSlots } from '@fluentui/react-utilities';
55
import type { JSXElement } from '@fluentui/react-utilities';
6-
import type { LabelState, LabelSlots } from './Label.types';
6+
import type { LabelBaseState, LabelSlots } from './Label.types';
77

88
/**
99
* Render the final JSX of Label
1010
*/
11-
export const renderLabel_unstable = (state: LabelState): JSXElement => {
11+
export const renderLabel_unstable = (state: LabelBaseState): JSXElement => {
1212
assertSlots<LabelSlots>(state);
1313

1414
return (

packages/react-components/react-label/library/src/components/Label/useLabel.tsx

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
'use client';
2+
13
import * as React from 'react';
24
import { getIntrinsicElementProps, slot } from '@fluentui/react-utilities';
3-
import type { LabelProps, LabelState } from './Label.types';
5+
import type { LabelBaseProps, LabelBaseState, LabelProps, LabelState } from './Label.types';
46

57
/**
68
* Create the state required to render Label.
@@ -12,23 +14,35 @@ import type { LabelProps, LabelState } from './Label.types';
1214
* @param ref - reference to root HTMLElement of Label
1315
*/
1416
export const useLabel_unstable = (props: LabelProps, ref: React.Ref<HTMLElement>): LabelState => {
15-
const { disabled = false, required = false, weight = 'regular', size = 'medium' } = props;
17+
const { weight = 'regular', size = 'medium', ...baseProps } = props;
18+
const state = useLabelBase_unstable(baseProps, ref as React.Ref<HTMLLabelElement>);
19+
20+
return {
21+
weight,
22+
size,
23+
...state,
24+
};
25+
};
26+
27+
/**
28+
* Create the base state required to render Label, without design-specific props (size, weight).
29+
*
30+
* @param props - props from this instance of Label
31+
* @param ref - reference to root HTMLElement of Label
32+
*/
33+
export const useLabelBase_unstable = (props: LabelBaseProps, ref: React.Ref<HTMLLabelElement>): LabelBaseState => {
34+
const { disabled = false, required = false, ...rest } = props;
1635
return {
1736
disabled,
1837
required: slot.optional(required === true ? '*' : required || undefined, {
1938
defaultProps: { 'aria-hidden': 'true' },
2039
elementType: 'span',
2140
}),
22-
weight,
23-
size,
2441
components: { root: 'label', required: 'span' },
2542
root: slot.always(
2643
getIntrinsicElementProps('label', {
27-
// FIXME:
28-
// `ref` is wrongly assigned to be `HTMLElement` instead of `HTMLLabelElement`
29-
// but since it would be a breaking change to fix it, we are casting ref to it's proper type
3044
ref: ref as React.Ref<HTMLLabelElement>,
31-
...props,
45+
...rest,
3246
}),
3347
{ elementType: 'label' },
3448
),
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
1-
export { Label, labelClassNames, renderLabel_unstable, useLabelStyles_unstable, useLabel_unstable } from './Label';
2-
export type { LabelProps, LabelSlots, LabelState } from './Label';
1+
export {
2+
Label,
3+
labelClassNames,
4+
renderLabel_unstable,
5+
useLabelStyles_unstable,
6+
useLabel_unstable,
7+
useLabelBase_unstable,
8+
} from './Label';
9+
export type { LabelBaseProps, LabelBaseState, LabelProps, LabelSlots, LabelState } from './Label';

0 commit comments

Comments
 (0)