Skip to content

Commit

Permalink
fix: Enforce padding in CheckboxField and accept optional icon (#719)
Browse files Browse the repository at this point in the history
fix: Enforce padding in CheckboxField and accept optional icon
  • Loading branch information
engfragui authored Dec 7, 2022
1 parent f33334a commit 0fa2c99
Show file tree
Hide file tree
Showing 23 changed files with 104 additions and 23 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Reactist follows [semantic versioning](https://semver.org/) and doesn't introduce breaking changes (API-wise) in minor or patch releases. However, the appearance of a component might change in a minor or patch release so keep an eye on redesigns and make sure your app still looks and feels like you expect it.

# v17.3.0

- [Fix] Enforce standard padding in the `CheckboxField` component and accept an `icon` attribute

# v17.2.0

- [Feat] Add support for providing a class to a `Modal` overlay
Expand All @@ -13,7 +17,7 @@ Reactist follows [semantic versioning](https://semver.org/) and doesn't introduc

# v17.0.1

- [Fix] Enforce minimum width for the checkbox icon in the `CheckboxField` element
- [Fix] Enforce minimum width for the checkbox icon in the `CheckboxField` component

# v17.0.0

Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/iframe.html
Original file line number Diff line number Diff line change
Expand Up @@ -476,4 +476,4 @@



window['STORIES'] = [{"titlePrefix":"","directory":"./src","files":"**/*.stories.@(tsx|mdx)","importPathMatcher":"^\\.[\\\\/](?:src(?:\\/(?!\\.)(?:(?:(?!(?:^|\\/)\\.).)*?)\\/|\\/|$)(?!\\.)(?=.)[^/]*?\\.stories\\.(tsx|mdx))$"},{"titlePrefix":"","directory":"./stories","files":"**/*.stories.@(js|jsx|ts|tsx|mdx)","importPathMatcher":"^\\.[\\\\/](?:stories(?:\\/(?!\\.)(?:(?:(?!(?:^|\\/)\\.).)*?)\\/|\\/|$)(?!\\.)(?=.)[^/]*?\\.stories\\.(js|jsx|ts|tsx|mdx))$"}];</script><script src="runtime~main.ad83b813.iframe.bundle.js"></script><script src="vendors~main.e678bf96.iframe.bundle.js"></script><script src="main.73a4c9f4.iframe.bundle.js"></script></body></html>
window['STORIES'] = [{"titlePrefix":"","directory":"./src","files":"**/*.stories.@(tsx|mdx)","importPathMatcher":"^\\.[\\\\/](?:src(?:\\/(?!\\.)(?:(?:(?!(?:^|\\/)\\.).)*?)\\/|\\/|$)(?!\\.)(?=.)[^/]*?\\.stories\\.(tsx|mdx))$"},{"titlePrefix":"","directory":"./stories","files":"**/*.stories.@(js|jsx|ts|tsx|mdx)","importPathMatcher":"^\\.[\\\\/](?:stories(?:\\/(?!\\.)(?:(?:(?!(?:^|\\/)\\.).)*?)\\/|\\/|$)(?!\\.)(?=.)[^/]*?\\.stories\\.(js|jsx|ts|tsx|mdx))$"}];</script><script src="runtime~main.ad83b813.iframe.bundle.js"></script><script src="vendors~main.f897f34b.iframe.bundle.js"></script><script src="main.b7229dd3.iframe.bundle.js"></script></body></html>
2 changes: 1 addition & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@



window['DOCS_MODE'] = false;</script><script src="runtime~main.8edd0578480acee74f4f.manager.bundle.js"></script><script src="vendors~main.3f75a318ae1619ac6d77.manager.bundle.js"></script><script src="main.2300ffaa729e0a28c3b2.manager.bundle.js"></script></body></html>
window['DOCS_MODE'] = false;</script><script src="runtime~main.f123b7b40ad3b4f431b3.manager.bundle.js"></script><script src="vendors~main.112ab1ddbb7c3ba86e96.manager.bundle.js"></script><script src="main.2300ffaa729e0a28c3b2.manager.bundle.js"></script></body></html>
1 change: 0 additions & 1 deletion docs/main.73a4c9f4.iframe.bundle.js

This file was deleted.

1 change: 1 addition & 0 deletions docs/main.b7229dd3.iframe.bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/project.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"generatedAt":1670207489520,"builder":{"name":"webpack4"},"hasCustomBabel":false,"hasCustomWebpack":true,"hasStaticDirs":false,"hasStorybookEslint":false,"refCount":0,"packageManager":{"type":"npm","version":"8.18.0"},"typescriptOptions":{"check":true,"checkOptions":{},"reactDocgen":"react-docgen-typescript","reactDocgenTypescriptOptions":{"shouldExtractLiteralValuesFromEnum":true}},"storybookVersion":"^6.5.3","language":"typescript","storybookPackages":{"@storybook/addon-knobs":{"version":"6.3.1"},"@storybook/addon-links":{"version":"6.5.3"},"@storybook/addons":{"version":"6.5.3"},"@storybook/react":{"version":"6.5.3"}},"framework":{"name":"react"},"addons":{"@storybook/addon-postcss":{"version":"2.0.0"},"@storybook/addon-actions":{"version":"6.5.3"},"@storybook/addon-docs":{"options":{"configureJSX":true},"version":"6.5.3"},"@storybook/addon-controls":{"version":"6.5.3"},"@geometricpanda/storybook-addon-badges":{"version":"0.2.2"}}}
{"generatedAt":1670423498619,"builder":{"name":"webpack4"},"hasCustomBabel":false,"hasCustomWebpack":true,"hasStaticDirs":false,"hasStorybookEslint":false,"refCount":0,"packageManager":{"type":"npm","version":"8.15.0"},"typescriptOptions":{"check":true,"checkOptions":{},"reactDocgen":"react-docgen-typescript","reactDocgenTypescriptOptions":{"shouldExtractLiteralValuesFromEnum":true}},"storybookVersion":"^6.5.3","language":"typescript","storybookPackages":{"@storybook/addon-knobs":{"version":"6.3.1"},"@storybook/addon-links":{"version":"6.5.3"},"@storybook/addons":{"version":"6.5.3"},"@storybook/react":{"version":"6.5.3"}},"framework":{"name":"react"},"addons":{"@storybook/addon-postcss":{"version":"2.0.0"},"@storybook/addon-actions":{"version":"6.5.3"},"@storybook/addon-docs":{"options":{"configureJSX":true},"version":"6.5.3"},"@storybook/addon-controls":{"version":"6.5.3"},"@geometricpanda/storybook-addon-badges":{"version":"0.2.2"}}}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions docs/vendors~main.112ab1ddbb7c3ba86e96.manager.bundle.js

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions docs/vendors~main.3f75a318ae1619ac6d77.manager.bundle.js

This file was deleted.

1 change: 0 additions & 1 deletion docs/vendors~main.e678bf96.iframe.bundle.js.map

This file was deleted.

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/vendors~main.f897f34b.iframe.bundle.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@doist/reactist",
"description": "Open source React components by Doist",
"author": "Henning Muszynski <[email protected]> (http://doist.com)",
"version": "17.2.0",
"version": "17.3.0",
"license": "MIT",
"homepage": "https://github.com/Doist/reactist#readme",
"repository": "git+https://github.com/Doist/reactist.git",
Expand Down
8 changes: 8 additions & 0 deletions src/new-components/checkbox-field/checkbox-field.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,11 @@
.container.keyFocused svg {
border: 2px solid var(--reactist-actionable-primary-idle-fill);
}

.icon {
margin-left: 12px;
}

.label {
margin-left: 6px;
}
51 changes: 48 additions & 3 deletions src/new-components/checkbox-field/checkbox-field.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,52 @@ export const Template = ({
disabled,
indeterminate,
label,
icon,
'aria-controls': ariaControls,
'aria-describedby': ariaDescribedby,
'aria-label': ariaLabel,
'aria-labelledby': ariaLabelledby,
}) => <CheckboxField disabled={disabled} indeterminate={indeterminate} label={label} />
}) => <CheckboxField disabled={disabled} indeterminate={indeterminate} label={label} icon={icon} />

### Checkbox with icon

A checkbox field with an icon and a string. The icon is rendered to the left of the label.

#### Image as Icon

<Canvas>
<Story
parameters={{ docs: { source: { type: 'dynamic' } } }}
name="Image as icon"
args={{
label: 'Label with icon',
icon: '😄',
}}
>
{Template.bind({})}
</Story>
</Canvas>

#### ReactChild as Icon

In this example we are passing an SVG image as icon.

<Canvas>
<Story
parameters={{ docs: { source: { type: 'dynamic' } } }}
name="ReactChild as icon"
args={{
label: 'Label with icon',
icon: <Icon />,
}}
>
{Template.bind({})}
</Story>
</Canvas>

### ReactNode as Label

A checkbox field with an icon and a string for the built-in label element.
A checkbox field with a `ReactNode` as label.

<Canvas>
<Story
Expand All @@ -71,7 +108,7 @@ A checkbox field with an icon and a string for the built-in label element.
args={{
label: (
<>
<Icon /> Label with icon
Accept our <strong>terms of service</strong>
</>
),
}}
Expand All @@ -80,6 +117,14 @@ A checkbox field with an icon and a string for the built-in label element.
</Story>
</Canvas>

<CheckboxField
label={
<>
Accept our <strong>terms of service</strong>
</>
}
/>

### Indeterminate Example

<Canvas>
Expand Down
13 changes: 13 additions & 0 deletions src/new-components/checkbox-field/checkbox-field.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { render, screen } from '@testing-library/react'
import { CheckboxField } from '.'
import userEvent from '@testing-library/user-event'
import { axe } from 'jest-axe'
import { TestIcon } from '../test-helpers'

describe('CheckboxField', () => {
function IndeterminateTestCase({ initialState }: { initialState: boolean[] }) {
Expand Down Expand Up @@ -177,6 +178,18 @@ describe('CheckboxField', () => {
expect(screen.getByTestId('value')).toHaveTextContent('off')
})

it('renders an icon if icon is provided', () => {
render(<CheckboxField label="Smile" icon="😄" />)
expect(screen.getByText('😄')).toBeInTheDocument()
})

it('supports SVG icons if provided', () => {
render(
<CheckboxField data-testid="checkbox-field" label="Test label" icon={<TestIcon />} />,
)
expect(screen.getByTestId('test-icon')).toBeInTheDocument()
})

describe('indeterminate', () => {
function getCheckboxItem(index: number): HTMLElement {
const checkbox = screen.getAllByTestId('checkbox-item')[index]
Expand Down
15 changes: 13 additions & 2 deletions src/new-components/checkbox-field/checkbox-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ type CheckboxFieldProps = Omit<
disabled?: boolean
/** The label for the checkbox element. */
label?: React.ReactNode
/** The icon that should be added to the checkbox label. */
icon?: React.ReactChild
/** Defines whether or not the checkbox can be of a `mixed` state. */
indeterminate?: boolean
}

const CheckboxField = React.forwardRef<HTMLInputElement, CheckboxFieldProps>(function CheckboxField(
{ label, disabled, indeterminate, defaultChecked, onChange, ...props },
{ label, icon, disabled, indeterminate, defaultChecked, onChange, ...props },
ref,
) {
const isControlledComponent = typeof props.checked === 'boolean'
Expand Down Expand Up @@ -104,7 +106,16 @@ const CheckboxField = React.forwardRef<HTMLInputElement, CheckboxFieldProps>(fun
indeterminate={indeterminate}
aria-hidden
/>
{label ? <Text>{label}</Text> : null}
{icon ? (
<Box display="flex" className={styles.icon} aria-hidden>
{icon}
</Box>
) : null}
{label ? (
<Box display="flex" className={styles.label}>
<Text>{label}</Text>
</Box>
) : null}
</Box>
)
})
Expand Down

0 comments on commit 0fa2c99

Please sign in to comment.