Skip to content

Commit 97424eb

Browse files
fix(mosaic): forward refs from Select.Group and Select.GroupLabel
1 parent 0fc8cc2 commit 97424eb

2 files changed

Lines changed: 33 additions & 16 deletions

File tree

‎packages/mosaic/src/primitives/select/__tests__/select.test.tsx‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,19 @@ describe('Select.Group', () => {
10271027
expect(await axe(document.body, { rules: { region: { enabled: false } } })).toHaveNoViolations();
10281028
});
10291029

1030+
it('forwards refs to the group and its label', () => {
1031+
const groupRef = createRef<HTMLDivElement>();
1032+
const labelRef = createRef<HTMLDivElement>();
1033+
render(
1034+
<Select.Group ref={groupRef}>
1035+
<Select.GroupLabel ref={labelRef}>Pome</Select.GroupLabel>
1036+
</Select.Group>,
1037+
);
1038+
1039+
expect(groupRef.current).toBe(screen.getByRole('group', { name: 'Pome' }));
1040+
expect(labelRef.current).toHaveTextContent('Pome');
1041+
});
1042+
10301043
it('throws when the label is used outside <Select.Group>', () => {
10311044
vi.spyOn(console, 'error').mockImplementation(() => {});
10321045
expect(() => render(<Select.GroupLabel>Fruits</Select.GroupLabel>)).toThrow(/within <Select.Group>/);
Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import { createContext, useContext, useId } from 'react';
3+
import React, { createContext, useContext, useId } from 'react';
44

55
import { type ComponentProps, mergeProps, useRender } from '../utils';
66

@@ -9,7 +9,7 @@ const SelectGroupContext = createContext<string | undefined>(undefined);
99
export type SelectGroupProps = ComponentProps<'div'>;
1010

1111
/** A labelled set of options in the listbox, named by the `Select.GroupLabel` inside it. */
12-
export function SelectGroup(props: SelectGroupProps) {
12+
export const SelectGroup = React.forwardRef<HTMLDivElement, SelectGroupProps>(function SelectGroup(props, ref) {
1313
const { render, ...otherProps } = props;
1414
const labelId = useId();
1515

@@ -23,25 +23,29 @@ export function SelectGroup(props: SelectGroupProps) {
2323
{useRender({
2424
defaultTagName: 'div',
2525
render,
26+
ref,
2627
props: mergeProps<'div'>(defaultProps, otherProps),
2728
})}
2829
</SelectGroupContext.Provider>
2930
);
30-
}
31+
});
3132

3233
export type SelectGroupLabelProps = ComponentProps<'div'>;
3334

3435
/** Names the `Select.Group` it sits in. Throws outside one. */
35-
export function SelectGroupLabel(props: SelectGroupLabelProps) {
36-
const { render, ...otherProps } = props;
37-
const labelId = useContext(SelectGroupContext);
38-
if (labelId === undefined) {
39-
throw new Error('Select.GroupLabel must be used within <Select.Group>');
40-
}
41-
42-
return useRender({
43-
defaultTagName: 'div',
44-
render,
45-
props: mergeProps<'div'>({ id: labelId }, otherProps),
46-
});
47-
}
36+
export const SelectGroupLabel = React.forwardRef<HTMLDivElement, SelectGroupLabelProps>(
37+
function SelectGroupLabel(props, ref) {
38+
const { render, ...otherProps } = props;
39+
const labelId = useContext(SelectGroupContext);
40+
if (labelId === undefined) {
41+
throw new Error('Select.GroupLabel must be used within <Select.Group>');
42+
}
43+
44+
return useRender({
45+
defaultTagName: 'div',
46+
render,
47+
ref,
48+
props: mergeProps<'div'>({ id: labelId }, otherProps),
49+
});
50+
},
51+
);

0 commit comments

Comments
 (0)