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

Add screener tests for react-checkbox #21011

Merged
merged 15 commits into from
Dec 16, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/vr-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@fluentui/react-badge": "9.0.0-beta.4",
"@fluentui/react-button": "9.0.0-beta.5",
"@fluentui/react-card": "9.0.0-beta.5",
"@fluentui/react-checkbox": "^9.0.0-beta.5",
"@fluentui/react-divider": "9.0.0-beta.4",
"@fluentui/react-experiments": "^8.4.7",
"@fluentui/react-hooks": "^8.3.7",
Expand Down
78 changes: 78 additions & 0 deletions apps/vr-tests/src/stories/CheckboxConverged.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import * as React from 'react';
import Screener, { Steps } from 'screener-storybook/src/screener';
import { storiesOf } from '@storybook/react';
import { Checkbox } from '@fluentui/react-checkbox';
import { TestWrapperDecoratorFixedWidth } from '../utilities/TestWrapperDecorator';

storiesOf('Checkbox Converged', module)
.addDecorator(TestWrapperDecoratorFixedWidth)
.addDecorator(story => (
<Screener
steps={new Steps()
.snapshot('rest', { cropTo: '.testWrapper' })
.hover('input')
.snapshot('hover', { cropTo: '.testWrapper' })
.mouseDown('input')
.snapshot('active', { cropTo: '.testWrapper' })
.end()}
>
{story()}
</Screener>
))
.addStory('unchecked', () => <Checkbox label="Unchecked" />)
.addStory('checked', () => <Checkbox checked label="Checked" />)
.addStory('mixed', () => <Checkbox checked="mixed" label="Mixed" />)
.addStory('disabled', () => <Checkbox disabled label="Disabled" />);

storiesOf('Checkbox Converged', module)
.addDecorator(TestWrapperDecoratorFixedWidth)
behowell marked this conversation as resolved.
Show resolved Hide resolved
.addDecorator(story => (
<Screener steps={new Steps().snapshot('rest', { cropTo: '.testWrapper' }).end()}>
{story()}
</Screener>
))
.addStory('disabled checked', () => <Checkbox disabled checked label="Disabled checked" />)
.addStory('disabled mixed', () => <Checkbox disabled checked="mixed" label="Disabled mixed" />)
.addStory('no-label', () => <Checkbox />)
.addStory('label-before', () => <Checkbox labelPosition="before" label="Label before" />)
.addStory('label-wrapping', () => (
<Checkbox
label={
<>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua
</>
}
/>
))
.addStory('required', () => <Checkbox required label="Required" />)
.addStory('required label-before', () => (
<Checkbox required labelPosition="before" label="Required with label before" />
))
.addStory('circular', () => <Checkbox circular label="Circular" />)
.addStory('circular checked', () => <Checkbox circular checked label="Circular checked" />)
.addStory('circular mixed', () => <Checkbox circular checked="mixed" label="Circular mixed" />)
//
// large variants
//
.addStory('large', () => <Checkbox size="large" label="Large" />)
.addStory('large checked', () => <Checkbox size="large" checked label="Large checked" />)
.addStory('large mixed', () => <Checkbox size="large" checked="mixed" label="Large mixed" />)
.addStory('large circular', () => <Checkbox size="large" circular label="Large circular" />)
.addStory('large circular checked', () => (
<Checkbox size="large" circular checked label="Large circular checked" />
))
.addStory('large circular mixed', () => (
<Checkbox size="large" circular checked="mixed" label="Large circular mixed" />
))
.addStory('large label-wrapping', () => (
<Checkbox
size="large"
label={
<>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua
</>
}
/>
));
15 changes: 15 additions & 0 deletions packages/react-checkbox/src/CheckboxMixed.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,22 @@ export const Mixed = () => {

return (
<>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, auto)', gridAutoFlow: 'row' }}>
<Checkbox />
<Checkbox checked />
<Checkbox checked="mixed" />
<Checkbox size="large" />
<Checkbox size="large" checked />
<Checkbox size="large" checked="mixed" />
<Checkbox circular />
<Checkbox circular checked />
<Checkbox circular checked="mixed" />
<Checkbox size="large" circular />
<Checkbox size="large" circular checked />
<Checkbox size="large" circular checked="mixed" />
</div>
<Checkbox
circular
checked={option1 && option2 && option3 ? true : !(option1 || option2 || option3) ? false : 'mixed'}
onChange={(_ev, data) => {
setOption1(!!data.checked);
Expand Down
37 changes: 37 additions & 0 deletions packages/react-checkbox/src/components/Checkbox/Checkmark.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as React from 'react';

export type CheckmarkProps = {
/**
* The width and height of the checkmark.
*
* @defaultvalue 8
*/
size?: number;

/**
* Whether the checkmark is in a mixed/indeterminate state.
*
* @defaultvalue false
*/
mixed?: boolean;

/**
* Whether the checkmark is in a circular checkbox. Only affects the mixed state.
*
* @defaultvalue false
*/
circular?: boolean;
};

/**
* The default checkmark icon for Checkbox
*/
export const Checkmark = ({ size = 8, mixed, circular }: CheckmarkProps) => (
<svg width={size} height={size} viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
behowell marked this conversation as resolved.
Show resolved Hide resolved
{mixed ? (
<rect width="100%" height="100%" rx={circular ? '50%' : 0} />
) : (
<path d="M471 137 187 421C170 438 143 438 127 421L13 307C-4 291-4 264 13 247 29 230 56 230 73 247L157 331 411 77C428 60 454 60 471 77 488 93 488 120 471 137Z" />
)}
</svg>
);

This file was deleted.

21 changes: 5 additions & 16 deletions packages/react-checkbox/src/components/Checkbox/useCheckbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
useMergedRefs,
} from '@fluentui/react-utilities';
import { CheckboxProps, CheckboxState } from './Checkbox.types';
import { Mixed12Regular, Mixed16Regular, Checkmark12Regular, Checkmark16Regular } from './DefaultIcons';
import { Checkmark } from './Checkmark';
import { Label } from '@fluentui/react-label';

/**
Expand All @@ -36,6 +36,7 @@ export const useCheckbox = (props: CheckboxProps, ref: React.Ref<HTMLInputElemen
excludedPropNames: ['checked', 'defaultChecked', 'size'],
});

const mixed = checked === 'mixed';
const id = useId('checkbox-', nativeProps.primary.id);

const state: CheckboxState = {
Expand Down Expand Up @@ -76,18 +77,7 @@ export const useCheckbox = (props: CheckboxProps, ref: React.Ref<HTMLInputElemen
required: true,
defaultProps: {
'aria-hidden': true,
children:
size === 'large' ? (
checked === 'mixed' ? (
<Mixed16Regular />
) : (
<Checkmark16Regular />
)
) : checked === 'mixed' ? (
<Mixed12Regular />
) : (
<Checkmark12Regular />
),
children: <Checkmark size={size === 'large' ? 10 : 8} mixed={mixed} circular={circular} />,
},
}),
};
Expand All @@ -106,12 +96,11 @@ export const useCheckbox = (props: CheckboxProps, ref: React.Ref<HTMLInputElemen

// Set the <input> element's checked and indeterminate properties based on our tri-state property.
// Since indeterminate can only be set via javascript, it has to be done in a layout effect.
const indeterminate = checked === 'mixed';
useIsomorphicLayoutEffect(() => {
if (inputRef.current) {
inputRef.current.indeterminate = indeterminate;
inputRef.current.indeterminate = mixed;
}
}, [inputRef, indeterminate]);
}, [inputRef, mixed]);

return state;
};
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const useRootStyles = makeStyles({
},
},

':active': {
':active:hover': {
color: theme.colorNeutralForeground1,
[`& .${indicatorClassName}`]: {
borderColor: theme.colorNeutralStrokeAccessiblePressed,
Expand All @@ -59,18 +59,20 @@ const useRootStyles = makeStyles({
[`& .${indicatorClassName}`]: {
backgroundColor: theme.colorCompoundBrandBackground,
color: theme.colorNeutralForegroundOnBrand,
borderColor: theme.colorBrandBackground,
borderColor: theme.colorCompoundBrandBackground,
},

':active': {
':hover': {
[`& .${indicatorClassName}`]: {
backgroundColor: theme.colorCompoundBrandBackgroundPressed,
backgroundColor: theme.colorCompoundBrandBackgroundHover,
borderColor: theme.colorCompoundBrandBackgroundHover,
},
},

':hover': {
':active:hover': {
[`& .${indicatorClassName}`]: {
backgroundColor: theme.colorCompoundBrandBackgroundHover,
backgroundColor: theme.colorCompoundBrandBackgroundPressed,
borderColor: theme.colorCompoundBrandBackgroundPressed,
},
},
}),
Expand All @@ -82,17 +84,17 @@ const useRootStyles = makeStyles({
color: theme.colorCompoundBrandForeground1,
},

':active': {
':hover': {
[`& .${indicatorClassName}`]: {
borderColor: theme.colorCompoundBrandStrokePressed,
color: theme.colorCompoundBrandForeground1Pressed,
borderColor: theme.colorCompoundBrandStrokeHover,
color: theme.colorCompoundBrandForeground1Hover,
},
},

':hover': {
':active:hover': {
[`& .${indicatorClassName}`]: {
borderColor: theme.colorCompoundBrandStrokeHover,
color: theme.colorCompoundBrandForeground1Hover,
borderColor: theme.colorCompoundBrandStrokePressed,
color: theme.colorCompoundBrandForeground1Pressed,
},
},
}),
Expand All @@ -102,7 +104,6 @@ const useRootStyles = makeStyles({
[`& .${indicatorClassName}`]: {
borderColor: theme.colorNeutralStrokeDisabled,
color: theme.colorNeutralForegroundDisabled,
backgroundColor: theme.colorNeutralBackground1,
},
}),
});
Expand Down Expand Up @@ -187,7 +188,7 @@ export const useCheckboxStyles = (state: CheckboxState): CheckboxState => {
rootStyles.base,
rootStyles.focusIndicator,
state.input.disabled && rootStyles.disabled,
// Use exactly one of the color classes, depending on `disabled` and `checked`
// Pick exactly one of the color classes, based on `disabled` and `checked`
state.input.disabled
? rootStyles.disabledColors
: state.checked === 'mixed'
Expand Down