Skip to content

Commit

Permalink
feat(RadioButton): add slug prop (#15239)
Browse files Browse the repository at this point in the history
* feat(RadioButton): add slug to RadioButtonGroup

* feat(RadioButton): add slug to RadioButton

* test(snapshot): update snapshots

* docs(Storybook): update tests stories for RadioButton

* feat(Checkbox): add slug styles to Checkbox

* test(snapshot): update snapshots

* refactor(Slug): remove whitespace

* style(RadioButton): use larger slug size when inline
  • Loading branch information
tw15egan authored Nov 29, 2023
1 parent e8d477c commit 1567d46
Show file tree
Hide file tree
Showing 10 changed files with 338 additions and 6 deletions.
12 changes: 12 additions & 0 deletions packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,9 @@ Map {
"readOnly": Object {
"type": "bool",
},
"slug": Object {
"type": "node",
},
"title": Object {
"type": "string",
},
Expand Down Expand Up @@ -543,6 +546,9 @@ Map {
"readOnly": Object {
"type": "bool",
},
"slug": Object {
"type": "node",
},
"warn": Object {
"type": "bool",
},
Expand Down Expand Up @@ -6235,6 +6241,9 @@ Map {
"onClick": Object {
"type": "func",
},
"slug": Object {
"type": "node",
},
"value": Object {
"args": Array [
Array [
Expand Down Expand Up @@ -6316,6 +6325,9 @@ Map {
"readOnly": Object {
"type": "bool",
},
"slug": Object {
"type": "node",
},
"valueSelected": Object {
"args": Array [
Array [
Expand Down
78 changes: 78 additions & 0 deletions packages/react/src/components/Checkbox/Checkbox.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import React from 'react';
import { default as Checkbox, CheckboxSkeleton } from './';
import mdx from './Checkbox.mdx';
import CheckboxGroup from '../CheckboxGroup';
import { View, FolderOpen, Folders } from '@carbon/icons-react';
import { Slug, SlugContent, SlugActions } from '../Slug';
import { IconButton } from '../IconButton';
import { Button } from '../Button';

const checkboxEvents = {
className: 'some-class',
Expand Down Expand Up @@ -71,6 +75,80 @@ export const Single = () => {
);
};

export const SlugTest = () => {
const slug = (kind) => (
<Slug kind={kind} className="slug-container">
<SlugContent>
<div>
<p className="secondary">AI Explained</p>
<h1>84%</h1>
<p className="secondary bold">Confidence score</p>
<p className="secondary">
Lorem ipsum dolor sit amet, di os consectetur adipiscing elit, sed
do eiusmod tempor incididunt ut fsil labore et dolore magna aliqua.
</p>
<hr />
<p className="secondary">Model type</p>
<p className="bold">Foundation model</p>
</div>
<SlugActions>
<IconButton kind="ghost" label="View">
<View />
</IconButton>
<IconButton kind="ghost" label="Open Folder">
<FolderOpen />
</IconButton>
<IconButton kind="ghost" label="Folders">
<Folders />
</IconButton>
<Button>View literature</Button>
</SlugActions>
</SlugContent>
</Slug>
);

return (
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
<CheckboxGroup
legendText="Group Label"
slug={slug()}
style={{ flex: '1 1 auto' }}>
<Checkbox labelText={`Checkbox label`} id="checkbox-label-1" />
<Checkbox labelText={`Checkbox label`} id="checkbox-label-2" />
<Checkbox labelText={`Checkbox label`} id="checkbox-label-3" />
</CheckboxGroup>

<CheckboxGroup legendText="Group Label" style={{ flex: '1 1 auto' }}>
<Checkbox
labelText={`Checkbox label`}
id="checkbox-label-4"
slug={slug()}
/>
<Checkbox
labelText={`Checkbox label`}
id="checkbox-label-5"
slug={slug()}
/>
<Checkbox labelText={`Checkbox label`} id="checkbox-label-6" />
</CheckboxGroup>

<CheckboxGroup legendText="Group Label" style={{ flex: '1 1 auto' }}>
<Checkbox
labelText={`Checkbox label`}
id="checkbox-label-7"
slug={slug('inline')}
/>
<Checkbox
labelText={`Checkbox label`}
id="checkbox-label-8"
slug={slug('inline')}
/>
<Checkbox labelText={`Checkbox label`} id="checkbox-label-9" />
</CheckboxGroup>
</div>
);
};

export const Skeleton = () => <CheckboxSkeleton />;

export const Playground = (args) => (
Expand Down
25 changes: 24 additions & 1 deletion packages/react/src/components/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ export interface CheckboxProps
*/
invalidText?: React.ReactNode;

/**
* Provide a `Slug` component to be rendered inside the `Checkbox` component
*/
slug?: ReactNodeLike;

/**
* Specify whether the Checkbox is currently invalid
*/
Expand Down Expand Up @@ -112,6 +117,7 @@ const Checkbox = React.forwardRef(
title = '',
warn,
warnText,
slug,
...other
}: CheckboxProps,
ref
Expand Down Expand Up @@ -141,12 +147,21 @@ const Checkbox = React.forwardRef(
[`${prefix}--checkbox-wrapper--readonly`]: readOnly,
[`${prefix}--checkbox-wrapper--invalid`]: !readOnly && invalid,
[`${prefix}--checkbox-wrapper--warning`]: showWarning,
[`${prefix}--checkbox-wrapper--slug`]: slug,
}
);
const innerLabelClasses = classNames(`${prefix}--checkbox-label-text`, {
[`${prefix}--visually-hidden`]: hideLabel,
});

let normalizedSlug;
if (slug && React.isValidElement(slug)) {
const size = slug.props?.['kind'] === 'inline' ? 'md' : 'mini';
normalizedSlug = React.cloneElement(slug as React.ReactElement<any>, {
size,
});
}

return (
<div className={wrapperClasses}>
<input
Expand Down Expand Up @@ -188,7 +203,10 @@ const Checkbox = React.forwardRef(
htmlFor={id}
className={`${prefix}--checkbox-label`}
title={title}>
<Text className={innerLabelClasses}>{labelText}</Text>
<Text className={innerLabelClasses}>
{labelText}
{normalizedSlug}
</Text>
</label>
<div className={`${prefix}--checkbox__validation-msg`}>
{!readOnly && invalid && (
Expand Down Expand Up @@ -281,6 +299,11 @@ Checkbox.propTypes = {
*/
readOnly: PropTypes.bool,

/**
* Provide a `Slug` component to be rendered inside the `Checkbox` component
*/
slug: PropTypes.node,

/**
* Specify a title for the <label> node for the Checkbox
*/
Expand Down
17 changes: 17 additions & 0 deletions packages/react/src/components/CheckboxGroup/CheckboxGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ function CheckboxGroup({
readOnly,
warn,
warnText,
slug,
...rest
}) {
const prefix = usePrefix();
Expand All @@ -48,8 +49,18 @@ function CheckboxGroup({
[`${prefix}--checkbox-group--readonly`]: readOnly,
[`${prefix}--checkbox-group--invalid`]: !readOnly && invalid,
[`${prefix}--checkbox-group--warning`]: showWarning,
[`${prefix}--checkbox-group--slug`]: slug,
});

// Slug is always size `mini`
let normalizedSlug;
if (slug) {
normalizedSlug = React.cloneElement(slug, {
size: 'mini',
kind: 'default',
});
}

return (
<fieldset
className={fieldsetClasses}
Expand All @@ -62,6 +73,7 @@ function CheckboxGroup({
className={`${prefix}--label`}
id={legendId || rest['aria-labelledby']}>
{legendText}
{normalizedSlug}
</legend>
{children}
<div className={`${prefix}--checkbox-group__validation-msg`}>
Expand Down Expand Up @@ -127,6 +139,11 @@ CheckboxGroup.propTypes = {
*/
readOnly: PropTypes.bool,

/**
* Provide a `Slug` component to be rendered inside the `CheckboxGroup` component
*/
slug: PropTypes.node,

/**
* Specify whether the form group is currently in warning state
*/
Expand Down
114 changes: 112 additions & 2 deletions packages/react/src/components/RadioButton/RadioButton.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import RadioButtonGroup from '../RadioButtonGroup';
import RadioButtonSkeleton from './RadioButton.Skeleton';
import React from 'react';
import mdx from './RadioButton.mdx';
import { View, FolderOpen, Folders } from '@carbon/icons-react';
import { Slug, SlugContent, SlugActions } from '../Slug';
import { IconButton } from '../IconButton';
import { Button } from '../Button';

export default {
title: 'Components/RadioButton',
Expand Down Expand Up @@ -51,10 +55,116 @@ export const Default = () => {
);
};

export const Skeleton = () => {
return <RadioButtonSkeleton />;
export const SlugTest = () => {
const slug = (kind) => (
<Slug kind={kind} className="slug-container">
<SlugContent>
<div>
<p className="secondary">AI Explained</p>
<h1>84%</h1>
<p className="secondary bold">Confidence score</p>
<p className="secondary">
Lorem ipsum dolor sit amet, di os consectetur adipiscing elit, sed
do eiusmod tempor incididunt ut fsil labore et dolore magna aliqua.
</p>
<hr />
<p className="secondary">Model type</p>
<p className="bold">Foundation model</p>
</div>
<SlugActions>
<IconButton kind="ghost" label="View">
<View />
</IconButton>
<IconButton kind="ghost" label="Open Folder">
<FolderOpen />
</IconButton>
<IconButton kind="ghost" label="Folders">
<Folders />
</IconButton>
<Button>View literature</Button>
</SlugActions>
</SlugContent>
</Slug>
);

return (
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
<RadioButtonGroup
slug={slug('default')}
orientation="vertical"
legendText="Group label"
name="radio-button-group"
defaultSelected="radio-1">
<RadioButton
labelText="Radio button label"
value="radio-1"
id="radio-1"
/>
<RadioButton
labelText="Radio button label"
value="radio-2"
id="radio-2"
/>
<RadioButton
labelText="Radio button label"
value="radio-3"
id="radio-3"
/>
</RadioButtonGroup>

<RadioButtonGroup
orientation="vertical"
legendText="Group label"
name="radio-button-group-2"
defaultSelected="radio-4">
<RadioButton
labelText="Radio button label"
value="radio-4"
id="radio-4"
slug={slug()}
/>
<RadioButton
labelText="Radio button label"
value="radio-5"
id="radio-5"
slug={slug()}
/>
<RadioButton
labelText="Radio button label"
value="radio-6"
id="radio-6"
/>
</RadioButtonGroup>

<RadioButtonGroup
orientation="vertical"
legendText="Group label"
name="radio-button-group-3"
defaultSelected="radio-7">
<RadioButton
labelText="Radio button label"
value="radio-7"
id="radio-7"
slug={slug('inline')}
/>
<RadioButton
labelText="Radio button label"
value="radio-8"
id="radio-8"
slug={slug('inline')}
/>
<RadioButton
labelText="Radio button label"
value="radio-9"
id="radio-9"
/>
</RadioButtonGroup>
</div>
);
};

export const Skeleton = () => {};

export const Playground = (args) => {
return (
<RadioButtonGroup
Expand Down
Loading

0 comments on commit 1567d46

Please sign in to comment.