Skip to content

Commit

Permalink
RadioGroup: VR changes (#3968)
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielpereirapinheiro authored Feb 3, 2025
1 parent e2d7d02 commit 5e51b3e
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 8 deletions.
1 change: 0 additions & 1 deletion docs/docs-components/siteIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ const siteIndex: readonly [siteIndexType, ...siteIndexType[]] = [
'Popover',
'PopoverEducational',
'Pulsar',
'RadioButton',
'RadioGroup',
'SearchField',
'SearchGuide',
Expand Down
10 changes: 10 additions & 0 deletions packages/gestalt/src/Borders.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
:root {
--g-border-width: 1px;
--g-border-width-lg: 2px;
--g-border-width-lg-vr: 1px;
--g-border-width-lg-vr-hover: 1.5px;
}

/* Border lines */
Expand Down Expand Up @@ -119,6 +121,14 @@ html[dir="rtl"] .borderLeft {
border-width: var(--g-border-width-lg);
}

.sizeLgVR {
border-width: var(--g-border-width-lg-vr);
}

.sizeLgHoverVR {
border-width: var(--g-border-width-lg-vr-hover);
}

.solid {
border-style: solid;
}
Expand Down
32 changes: 32 additions & 0 deletions packages/gestalt/src/Fieldset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { ReactNode } from 'react';
import classnames from 'classnames';
import boxStyles from './Box.css';
import boxWhitespaceStyles from './boxWhitespace.css';
import VRFieldset from './Fieldset/VRFieldset';
import labelStyles from './Label/InternalLabel.css';
import formStyles from './sharedSubcomponents/FormElement.css';
import FormErrorMessage from './sharedSubcomponents/FormErrorMessage';
import FormHelperText from './sharedSubcomponents/FormHelperText';
import formLabelStyles from './sharedSubcomponents/FormLabel.css';
import Text from './Text';
import useInExperiment from './useInExperiment';
Expand All @@ -31,6 +33,11 @@ type Props = {
* Whether the legend should be visible or not. If `hidden`, the legend is still available for screen reader users, but does not appear visually. See the [legend visibility variant](https://gestalt.pinterest.systems#Legend-visibility) for more info.
*/
legendDisplay?: 'visible' | 'hidden';
/**
* Adds an help message below the group of radio buttons.
*
*/
helperText?: string;
};

/**
Expand All @@ -46,6 +53,7 @@ export default function Fieldset({
legend,
legendDisplay = 'visible',
children,
helperText,
}: Props) {
const isInVRExperiment = useInExperiment({
webExperimentName: 'web_gestalt_visualrefresh',
Expand All @@ -57,6 +65,20 @@ export default function Fieldset({
console.error('Please provide an id property to <Fieldset />');
}

if (isInVRExperiment) {
return (
<VRFieldset
errorMessage={errorMessage}
helperText={helperText}
id={id}
legend={legend}
legendDisplay={legendDisplay}
>
{children}
</VRFieldset>
);
}

return (
<fieldset
aria-describedby={errorMessage ? `${id}-error` : undefined}
Expand All @@ -76,6 +98,16 @@ export default function Fieldset({
<Text size="100">{legend}</Text>
</legend>
{children}
{helperText && (
<FormHelperText
disabled={false}
id={`${id}-helperText`}
marginTop
noPadding
text={helperText}
/>
)}

{errorMessage && <FormErrorMessage id={`${id}-error`} text={errorMessage} />}
</fieldset>
);
Expand Down
3 changes: 3 additions & 0 deletions packages/gestalt/src/Fieldset/VRFieldset.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.marginBottom {
margin-bottom: var(--sema-space-200);
}
91 changes: 91 additions & 0 deletions packages/gestalt/src/Fieldset/VRFieldset.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { ReactNode } from 'react';
import classnames from 'classnames';
import fieldsetStyles from './VRFieldset.css';
import boxStyles from '../Box.css';
import boxWhitespaceStyles from '../boxWhitespace.css';
import labelStyles from '../Label/InternalLabel.css';
import formStyles from '../sharedSubcomponents/FormElement.css';
import FormErrorMessage from '../sharedSubcomponents/FormErrorMessage';
import FormHelperText from '../sharedSubcomponents/FormHelperText';
import Text from '../Text';
import whitespaceStyles from '../Whitespace.css';

type Props = {
/**
* The content of Fieldset, typically [RadioButtons](https://gestalt.pinterest.systems/web/radiobutton), [Checkboxes](https://gestalt.pinterest.systems/web/checkbox) or [TextFields](https://gestalt.pinterest.systems/web/textfield).
*/
children: ReactNode;
/**
* A unique identifier for this Fieldset. `id` must be specified when an errorMessage is added.
*/
id?: string;
/**
* When needed, pass a string with a helpful error message (be sure to localize!).
*/
errorMessage?: string;
/**
* Caption that clearly and concisely describes the form elements grouped in the fieldset.
*/
legend: string;
/**
* Whether the legend should be visible or not. If `hidden`, the legend is still available for screen reader users, but does not appear visually. See the [legend visibility variant](https://gestalt.pinterest.systems#Legend-visibility) for more info.
*/
legendDisplay?: 'visible' | 'hidden';
/**
* Adds an help message below the group of radio buttons.
*/
helperText?: string;
};

/**
* [Fieldset](https://gestalt.pinterest.systems/web/fieldset) creates a fieldset and legend for a group of related form items, like [RadioButtons](https://gestalt.pinterest.systems/web/radiobutton) or [CheckBoxes](https://gestalt.pinterest.systems/web/checkbox), in order to clearly indicate related form items."
*
* ![Fieldset light mode](https://raw.githubusercontent.com/pinterest/gestalt/master/playwright/visual-test/Fieldset.spec.ts-snapshots/Fieldset-chromium-darwin.png)
* ![Fieldset dark mode](https://raw.githubusercontent.com/pinterest/gestalt/master/playwright/visual-test/Fieldset-dark.spec.ts-snapshots/Fieldset-dark-chromium-darwin.png)
*
*/
export default function VRFieldset({
id = '',
errorMessage,
legend,
legendDisplay = 'visible',
children,
helperText,
}: Props) {
if (errorMessage && id === '') {
// eslint-disable-next-line no-console
console.error('Please provide an id property to <Fieldset />');
}

return (
<fieldset
aria-describedby={errorMessage ? `${id}-error` : undefined}
className={classnames(formStyles.unstyled, whitespaceStyles.p0, whitespaceStyles.m0)}
>
<legend
className={classnames(
labelStyles.label,
fieldsetStyles.marginBottom,
boxWhitespaceStyles.paddingX0, // Needed to remove the default legend padding
{
[boxStyles.visuallyHidden]: legendDisplay === 'hidden',
},
)}
>
<Text size="100">{legend}</Text>
</legend>
{children}
{helperText && (
<FormHelperText
disabled={false}
id={`${id}-helperText`}
marginTop
noPadding
text={helperText}
/>
)}

{errorMessage && <FormErrorMessage id={`${id}-error`} marginTop text={errorMessage} />}
</fieldset>
);
}
12 changes: 12 additions & 0 deletions packages/gestalt/src/RadioButton.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,22 @@
composes: sizeLg from "./Borders.css";
}

.BorderUncheckedVR {
composes: sizeLgVR from "./Borders.css";
}

.BorderUncheckedHoverVR {
composes: sizeLgHoverVR from "./Borders.css";
}

.BgDisabled {
background-color: var(--color-background-formfield-disabled);
}

.BgDisabledVR {
background-color: var(--sema-color-background-disabled);
}

.BgEnabled {
background-color: var(--color-background-formfield-primary);
}
Expand Down
26 changes: 24 additions & 2 deletions packages/gestalt/src/RadioGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Fieldset from './Fieldset';
import Flex from './Flex';
import { RadioGroupContextProvider } from './RadioGroup/Context';
import RadioGroupButton from './RadioGroupButton';
import useInExperiment from './useInExperiment';

type Props = {
/**
Expand Down Expand Up @@ -36,6 +37,11 @@ type Props = {
*
*/
legendDisplay?: 'visible' | 'hidden';
/**
* Adds an help message below the group of radio buttons.
*
*/
helperText?: string;
};

/**
Expand All @@ -49,22 +55,38 @@ function RadioGroup({
id,
legend,
legendDisplay = 'visible',
helperText,
}: Props) {
// Consume GlobalEventsHandlerProvider
const { radioGroupHandlers } = useGlobalEventsHandlerContext() ?? {
radioGroupHandlers: undefined,
};

const isInVRExperiment = useInExperiment({
webExperimentName: 'web_gestalt_visualrefresh',
mwebExperimentName: 'web_gestalt_visualrefresh',
});

useEffect(() => {
if (radioGroupHandlers?.onRender) radioGroupHandlers?.onRender();
}, [radioGroupHandlers]);

return (
<RadioGroupContextProvider value={{ parentName: 'RadioGroup' }}>
<Fieldset errorMessage={errorMessage} id={id} legend={legend} legendDisplay={legendDisplay}>
<Fieldset
errorMessage={errorMessage}
helperText={helperText}
id={id}
legend={legend}
legendDisplay={legendDisplay}
>
<Flex
direction={direction}
gap={direction === 'row' ? { row: 4, column: 0 } : { column: 2, row: 0 }}
gap={
direction === 'row'
? { row: 4, column: 0 }
: { column: isInVRExperiment ? 3 : 2, row: 0 }
}
>
{children}
</Flex>
Expand Down
22 changes: 17 additions & 5 deletions packages/gestalt/src/RadioGroupButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@ const RadioGroupButtonWithForwardRef = forwardRef<HTMLInputElement, Props>(funct
borderColor = styles.BorderDisabledChecked;
} else if (!disabled && checked) {
borderColor = styles.BorderSelected;
} else if (!disabled && hovered) {
} else if (!disabled && hovered && !isInVRExperiment) {
borderColor = styles.BorderHovered;
}

let borderWidth = styles.BorderUnchecked;
let borderWidth = isInVRExperiment ? styles.BorderUncheckedVR : styles.BorderUnchecked;
if (disabled && !checked) {
borderWidth = styles.BorderDisabled;
} else if (checked && size === 'sm') {
Expand All @@ -140,11 +140,20 @@ const RadioGroupButtonWithForwardRef = forwardRef<HTMLInputElement, Props>(funct
borderWidth = styles.BorderCheckedMd;
}

const uncheckedBorderWidth = disabled ? styles.BorderDisabled : styles.BorderUnchecked;
let uncheckedBorderWidth = styles.BorderDisabled;

if (!isInVRExperiment) {
uncheckedBorderWidth = disabled ? styles.BorderDisabled : styles.BorderUnchecked;
} else {
uncheckedBorderWidth = !disabled ? styles.BorderUncheckedVR : uncheckedBorderWidth;
uncheckedBorderWidth =
hovered && !disabled ? styles.BorderUncheckedHoverVR : styles.BorderUncheckedVR;
}

const styleSize = size === 'sm' ? controlStyles.sizeSm : controlStyles.sizeMd;

const bgStyle = disabled && !checked ? styles.BgDisabled : styles.BgEnabled;
let bgStyle = disabled && !checked ? styles.BgDisabled : styles.BgEnabled;
bgStyle = isInVRExperiment && !checked ? styles.BgDisabledVR : bgStyle;

const { isFocusVisible } = useFocusVisible();

Expand Down Expand Up @@ -182,6 +191,9 @@ const RadioGroupButtonWithForwardRef = forwardRef<HTMLInputElement, Props>(funct
},
);

let margin = size === 'md' ? '2px' : '-1px';
margin = isInVRExperiment ? '0px' : margin;

return (
<Box alignItems="start" display="flex" justifyContent="start" marginEnd={-1} marginStart={-1}>
<Box paddingX={1}>
Expand Down Expand Up @@ -232,7 +244,7 @@ const RadioGroupButtonWithForwardRef = forwardRef<HTMLInputElement, Props>(funct
{/* marginTop: '-1px'/'2px' is needed to visually align the label text & radiobutton input */}
<Box
dangerouslySetInlineStyle={{
__style: { marginTop: size === 'md' ? '2px' : '-1px' },
__style: { marginTop: margin },
}}
paddingX={1}
>
Expand Down
3 changes: 3 additions & 0 deletions packages/gestalt/src/sharedSubcomponents/FormErrorMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ type Props = {
text?: ReactNode;
size?: SizeType;
noPadding?: boolean;
marginTop?: boolean;
};

export default function FormErrorMessage({
id,
size,
text = '',
noPadding: noStartPadding,
marginTop,
}: Props) {
const isInVRExperiment = useInExperiment({
webExperimentName: 'web_gestalt_visualrefresh',
Expand All @@ -31,6 +33,7 @@ export default function FormErrorMessage({
return (
<div
className={classnames({
[helperTextStyles.marginTop]: marginTop,
// none
[helperTextStyles.noStartPadding]: noStartPadding,
// sm
Expand Down
4 changes: 4 additions & 0 deletions packages/gestalt/src/sharedSubcomponents/FormHelperText.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
padding-right: var(--space-0);
}

.marginTop {
margin-top: var(--sema-space-300);
}

/* sm */

.sm_topPadding {
Expand Down
3 changes: 3 additions & 0 deletions packages/gestalt/src/sharedSubcomponents/FormHelperText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type Props = {
currentLength?: number;
size?: SizeType;
disabled?: boolean;
marginTop?: boolean;
};

export default function FormHelperText({
Expand All @@ -26,6 +27,7 @@ export default function FormHelperText({
maxLength,
size,
noPadding: noStartPadding,
marginTop,
}: Props) {
const isInVRExperiment = useInExperiment({
webExperimentName: 'web_gestalt_visualrefresh',
Expand All @@ -37,6 +39,7 @@ export default function FormHelperText({

<div
className={classnames({
[styles.marginTop]: marginTop,
// none
[styles.noStartPadding]: !isInVRExperiment && noStartPadding,
// sm
Expand Down

0 comments on commit 5e51b3e

Please sign in to comment.