fix: Making the hidden input on Checkbox and Switch only cover the indicator and not also the label#24638
Conversation
…dicator and not also the label.
There was a problem hiding this comment.
This change will also make it so the padding around the control, and the gap between the control and the label are dead zones, but they are required to be part of the hit target by the spec (and in general for usability).
Interactive content should probably be outside the label? But if it's necessary to do it this way, then we should consider refactoring Checkbox/Switch/Radio so that the <label> is the root element, wrapping the indicator and label text.
We should make sure that Radio also works the same way as Checkbox and Switch.
📊 Bundle size report
Unchanged fixtures
|
|
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit f2dac77:
|
Asset size changesSize Auditor did not detect a change in bundle size for any component! Baseline commit: 8f38bb63574e31bf2fa9f2f1d14b166d6c1a627f (build) |
Perf Analysis (
|
| Scenario | Render type | Master Ticks | PR Ticks | Iterations | Status |
|---|---|---|---|---|---|
| Avatar | mount | 1300 | 1257 | 5000 | |
| Button | mount | 939 | 934 | 5000 | |
| FluentProvider | mount | 1478 | 1510 | 5000 | |
| FluentProviderWithTheme | mount | 581 | 564 | 10 | |
| FluentProviderWithTheme | virtual-rerender | 544 | 540 | 10 | |
| FluentProviderWithTheme | virtual-rerender-with-unmount | 563 | 575 | 10 | |
| MakeStyles | mount | 1934 | 1975 | 50000 | |
| SpinButton | mount | 2324 | 2341 | 5000 |
|
re: @behowell's comment on dead zones -- I agree it'd be better if there weren't, though it doesn't concern me all that much, since the indicator itself combined with the label text itself should end up being a pretty big hit target. A wrapping label would be nice though :). I forget if there was a reason for not doing that originally for checkbox/switch. |
|
This pull request has been automatically marked as stale because it was marked as requiring author feedback but has not had any activity for 7 days. It will be closed if no further activity occurs within 5 days of this comment. Thank you for your contributions to Fluent UI! |
…heckboxSwitchInputOnlyCoversIndicator
packages/react-components/react-checkbox/src/components/Checkbox/useCheckboxStyles.ts
Show resolved
Hide resolved
| // Use a (negative) margin to account for the difference between the indicator's height and the label's line height, | ||
| // as well as accounting for the introduced padding for handling the "empty space" around the label. | ||
| // This prevents the label from expanding the height of the checkbox, but preserves line height if the label wraps. | ||
| medium: { | ||
| marginTop: `calc((${indicatorSizeMedium} - ${tokens.lineHeightBase300}) / 2)`, | ||
| marginBottom: `calc((${indicatorSizeMedium} - ${tokens.lineHeightBase300}) / 2)`, | ||
| marginTop: `calc(-1 * ${tokens.spacingVerticalS} + (${indicatorSizeMedium} - ${tokens.lineHeightBase300}) / 2)`, | ||
| marginBottom: `calc(-1 * ${tokens.spacingVerticalS} + (${indicatorSizeMedium} - ${tokens.lineHeightBase300}) / 2)`, | ||
| }, | ||
| large: { | ||
| marginTop: `calc((${indicatorSizeLarge} - ${tokens.lineHeightBase300}) / 2)`, | ||
| marginBottom: `calc((${indicatorSizeLarge} - ${tokens.lineHeightBase300}) / 2)`, | ||
| marginTop: `calc(-1 * ${tokens.spacingVerticalS} + (${indicatorSizeLarge} - ${tokens.lineHeightBase300}) / 2)`, | ||
| marginBottom: `calc(-1 * ${tokens.spacingVerticalS} + (${indicatorSizeLarge} - ${tokens.lineHeightBase300}) / 2)`, | ||
| }, |
There was a problem hiding this comment.
IMO it would be better to remove the padding from root and put it on the individual slots instead of adding padding to both the label AND the root, then adding a negative margin to overlap it.
packages/react-components/react-checkbox/src/components/Checkbox/useCheckboxStyles.ts
Show resolved
Hide resolved
…tive margins and adding RTL VR tests.
behowell
left a comment
There was a problem hiding this comment.
Looks good, thanks for making all of these changes to address my feedback!
| medium: { | ||
| width: `calc(${indicatorSizeMedium} + ${tokens.spacingHorizontalS})`, | ||
| }, | ||
| large: { | ||
| width: `calc(${indicatorSizeLarge} + ${tokens.spacingHorizontalS})`, | ||
| }, |
There was a problem hiding this comment.
I think you can get rid of spacingHorizontalS now that the label is using padding instead of margin for the gap, right?
| medium: { | |
| width: `calc(${indicatorSizeMedium} + ${tokens.spacingHorizontalS})`, | |
| }, | |
| large: { | |
| width: `calc(${indicatorSizeLarge} + ${tokens.spacingHorizontalS})`, | |
| }, | |
| medium: { | |
| width: indicatorSizeMedium, | |
| }, | |
| large: { | |
| width: indicatorSizeLarge, | |
| }, |
There was a problem hiding this comment.
No, that spacing is to account for the space on the left of the indicator (right if labelPosition is before). You can see that another tokens.spacingHorizontalM has been removed already that referred to the gap between the indicator and the label.
|
|
||
| // Calculate the width of the hidden input by taking into account the size of the indicator + the padding around it. | ||
| // This is done so that clicking on that "empty space" still toggles the switch. | ||
| width: `calc(${trackWidth}px + ${tokens.spacingHorizontalS})`, |
There was a problem hiding this comment.
I haven't read the switch styles in as much detail, but similar to my comment here in checkbox, does this still need spacingHorizontalS included in it?
| width: `calc(${trackWidth}px + ${tokens.spacingHorizontalS})`, | |
| width: `${trackWidth}px`, |
There was a problem hiding this comment.
Yup, similar reason to the one above.
| }, | ||
| above: { | ||
| bottom: 0, | ||
| height: `calc(${trackHeight}px + ${tokens.spacingVerticalS})`, |
There was a problem hiding this comment.
Ditto here too
| height: `calc(${trackHeight}px + ${tokens.spacingVerticalS})`, | |
| height: `${trackHeight}px`, |
|
@microsoft-github-policy-service agree [company="Microsoft"] |
|
@microsoft-github-policy-service agree company="Microsoft" |
…dicator and not also the label (microsoft#24638) * fix: Making the hidden input on Checkbox and Switch only cover the indicator and not also the label. * Adding change files. * Making empty space around indicator and label toggle checkbox when clicked. * Making empty space around indicator and label toggle switch when clicked. * Using indicator + label paddings instead of double paddings with negative margins and adding RTL VR tests. * Addressing cases where no label is provided for components. Co-authored-by: Humberto Makoto Morimoto Burgos <makotom@microsoft.com> Co-authored-by: KHMakoto <humberto_makoto@hotmail.com>

Current Behavior
The hidden input in the
CheckboxandSwitchcomponents covers both the indicator and the label, making any interactive elements within the label, like links, impossible to be clicked.Input
Label
New Behavior
The hidden input in the
CheckboxandSwitchcomponents now covers only the indicator and its surrounding space, not the label. This makes any interactive elements within the label, like links, possible to be clicked. We verified that clicking on the label still toggles the state of the component. We also expanded the size of the label so it covers the empty space around it that was previously being covered by the hidden input.We verified that hover and pressed styling still works as expected and we have added visual regression tests that check for RTL to work correctly as well.
Input
Label
Related Issue(s)
Fixes #24330