Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add number type in value #6636

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion packages/@react-aria/radio/src/useRadioGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export function useRadioGroup(props: AriaRadioGroupProps, state: RadioGroupState
let {focusWithinProps} = useFocusWithin({
onBlurWithin(e) {
props.onBlur?.(e);
if (!state.selectedValue) {
if (state.selectedValue == null) {
state.setLastFocusedValue(null);
}
},
Expand Down
2 changes: 1 addition & 1 deletion packages/@react-spectrum/form/stories/Form.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ function render(props: any = {}) {
function FormWithControls(props: any = {}) {
let [firstName, setFirstName] = useState('hello');
let [isHunter, setIsHunter] = useState(true);
let [favoritePet, setFavoritePet] = useState('cats');
let [favoritePet, setFavoritePet] = useState<string | number>('cats');
let [favoriteColor, setFavoriteColor] = useState('green' as Key);
let [howIFeel, setHowIFeel] = useState('I feel good, o I feel so good!');
let [birthday, setBirthday] = useState(new CalendarDate(1732, 2, 22));
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-spectrum/label/stories/HelpText.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export let AriaLabelWithDynamicHelpText: HelpTextStory = {

function TextFieldWithValidationState(props: SpectrumTextFieldProps) {
let [value, setValue] = useState('');
let [valid, setValid] = useState<string | undefined>(undefined);
let [valid, setValid] = useState<string | number | undefined>(undefined);

let validState;
if (value.length) {
Expand Down Expand Up @@ -150,7 +150,7 @@ function TextFieldWithValidationState(props: SpectrumTextFieldProps) {

function TextFieldWithAriaLabelAndDynamicHelpText(props: SpectrumTextFieldProps) {
let [value, setValue] = useState('');

return (
<TextField
{...props}
Expand Down
6 changes: 3 additions & 3 deletions packages/@react-spectrum/radio/docs/RadioGroup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Alternatively, a controlled value can be provided using the `value` prop.

```tsx example
function Example() {
let [selected, setSelected] = React.useState('yes');
let [selected, setSelected] = React.useState<string | number>('yes');

return (
<Flex gap="size-300">
Expand Down Expand Up @@ -133,7 +133,7 @@ The example below uses `onChange` to log how the user is interacting with the co

```tsx example
function Example() {
let [selected, setSelected] = React.useState('');
let [selected, setSelected] = React.useState<string | number>('');

return (
<>
Expand Down Expand Up @@ -218,7 +218,7 @@ Both a description and an error message can be supplied to a RadioGroup. The des

```tsx example
function Example() {
let [selected, setSelected] = React.useState('dogs');
let [selected, setSelected] = React.useState<string | number>('dogs');
let isValid = selected === 'dogs';

return (
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-spectrum/radio/stories/Radio.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ function renderFormControl() {

function renderWithDescriptionErrorMessageAndValidation(props) {
function Example() {
let [selected, setSelected] = useState('dogs');
let [selected, setSelected] = useState<string | number>('dogs');
let isValid = selected === 'dogs';

return (
Expand Down Expand Up @@ -255,7 +255,7 @@ function renderWithDescriptionErrorMessageAndValidation(props) {
}

export const ControlledRovingTab = () => {
const [selected, setSelected] = useState('1');
const [selected, setSelected] = useState<string | number>('1');

return (
<Flex direction="column" gap="16px" alignItems="center" margin="16px">
Expand Down
2 changes: 1 addition & 1 deletion packages/@react-spectrum/table/stories/Table.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1836,7 +1836,7 @@ function EmptyState() {
}

function ZoomResizing(props) {
const [child, setChild] = useState('loader');
const [child, setChild] = useState<string | number>('loader');

return (
<div className="App" style={{height: '100vh'}}>
Expand Down
10 changes: 5 additions & 5 deletions packages/@react-stately/radio/src/useRadioGroupState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,16 @@ export interface RadioGroupState extends FormValidationState {
readonly isInvalid: boolean,

/** The currently selected value. */
readonly selectedValue: string | null,
readonly selectedValue: string | number | null,

/** Sets the selected value. */
setSelectedValue(value: string | null): void,
setSelectedValue(value: string | number | null): void,

/** The value of the last focused radio. */
readonly lastFocusedValue: string | null,
readonly lastFocusedValue: string | number | null,

/** Sets the last focused value. */
setLastFocusedValue(value: string | null): void
setLastFocusedValue(value: string | number | null): void
}

let instance = Math.round(Math.random() * 10000000000);
Expand All @@ -66,7 +66,7 @@ export function useRadioGroupState(props: RadioGroupProps): RadioGroupState {
// Preserved here for backward compatibility. React Aria now generates the name instead of stately.
let name = useMemo(() => props.name || `radio-group-${instance}-${++i}`, [props.name]);
let [selectedValue, setSelected] = useControlledState(props.value, props.defaultValue ?? null, props.onChange);
let [lastFocusedValue, setLastFocusedValue] = useState<string | null>(null);
let [lastFocusedValue, setLastFocusedValue] = useState<string | number | null>(null);

let validation = useFormValidationState({
...props,
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-types/radio/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
} from '@react-types/shared';
import {ReactElement, ReactNode} from 'react';

export interface RadioGroupProps extends ValueBase<string|null, string>, InputBase, InputDOMProps, Validation<string | null>, LabelableProps, HelpTextProps, FocusEvents {
export interface RadioGroupProps extends ValueBase<string | number | null, string | number>, InputBase, InputDOMProps, Validation<string | number | null>, LabelableProps, HelpTextProps, FocusEvents {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we can infer the type based on what is sent into RadioGroup since Radio's can declare their own value and you could have a mix of strings and numbers.

This leads to an interesting set of changes downstream though because people will now need to change their types from just 'string' to 'string | number' in any controlled usage. See stories I had to edit here.

Do we consider this just a bug fix or is it in the gray area of breaking change?

/**
* The axis the Radio Button(s) should align with.
* @default 'vertical'
Expand All @@ -42,7 +42,7 @@ export interface RadioProps extends FocusableProps {
* The value of the radio button, used when submitting an HTML form.
* See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio#Value).
*/
value: string,
value: string | number,
/**
* The label for the Radio. Accepts any renderable node.
*/
Expand Down
4 changes: 2 additions & 2 deletions packages/react-aria-components/stories/RadioGroup.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ export const RadioGroupExample = () => {
};

export const RadioGroupControlledExample = () => {
let [selected, setSelected] = useState<string|null>(null);
let [selected, setSelected] = useState<string | number | null>(null);

return (
<RadioGroup
data-testid="radio-group-example"
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
"./packages/@react-types/numberfield",
"./packages/@react-types/progress",
"./packages/@react-types/searchfield",
"./packages/@react-types/radio",
"./packages/@react-types/shared",
"./packages/@react-types/statuslight",
"./packages/@react-types/tabs",
Expand Down