Skip to content

Commit

Permalink
Merge branch 'main' into fix-radio-focus
Browse files Browse the repository at this point in the history
  • Loading branch information
sebald committed Dec 15, 2022
2 parents b346454 + 1bfe10c commit 1bcfcf8
Show file tree
Hide file tree
Showing 20 changed files with 237 additions and 254 deletions.
8 changes: 8 additions & 0 deletions .changeset/real-papayas-leave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@marigold/docs": minor
"@marigold/components": minor
"@marigold/theme-b2b": minor
"@marigold/theme-unicorn": minor
---

feat: add <Fieldbase> to <RadioGroup> and <CheckboxGroup> to support errorMessage and helptext
6 changes: 5 additions & 1 deletion docs/src/demos/components/Checkbox/checkbox-group.demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ export const CheckboxGroupoDemo = () => {
const [selected, setSelected] = useState<string[]>([]);
return (
<>
<CheckboxGroup label="Choose your toppings:" onChange={setSelected}>
<CheckboxGroup
label="Choose your toppings:"
onChange={setSelected}
description="Just click on the options"
>
<Checkbox value="ham">🐖 Ham</Checkbox>
<Checkbox value="beef" disabled>
🐄 Beef (out of stock)
Expand Down
1 change: 1 addition & 0 deletions docs/src/demos/components/Radio/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './radio.demo';
export * from './radio-disabled.demo';
export * from './radio-required.demo';
export * from './radio-error.demo';
16 changes: 16 additions & 0 deletions docs/src/demos/components/Radio/radio-error.demo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Radio } from '@marigold/components';

export const ErrorRadio = () => (
<Radio.Group
label="Radio Group"
error
errorMessage="Oh no! An error occured."
>
<Radio value="1">Option 1</Radio>
<Radio value="2">Option 2</Radio>
<Radio value="3" disabled>
Option 3
</Radio>
<Radio value="4">Option 4</Radio>
</Radio.Group>
);
14 changes: 13 additions & 1 deletion docs/src/pages/components/checkbox.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,18 @@ import { Checkbox, CheckboxGroup } from '@marigold/components';
type: '(value: string[]) => void',
description: 'Handler that is called when the checkbox value changes.',
default: 'none',
},
{
property: 'description',
type: 'string',
description: 'Sets a helptext for the group.',
default: 'none',
},
{
property: 'errorMessage',
type: 'string',
description: 'Sets a error message for the group if a error occured.',
default: 'none',
}

]}
Expand All @@ -175,7 +187,7 @@ Use indeterminate state when it represents both selected and not selected values

### Group checkboxes

In this example the `<Checkbox>` are wrapped within the `<CheckboxGroup>`. You see that the `onChange` property is also set.
In this example the `<Checkbox>` are wrapped within the `<CheckboxGroup>`. You see that the `onChange` property is also set. It has also a helptext within which you can set with the `description` property for the `<CheckboxGroup>`.

```tsx preview file=components/Checkbox/checkbox-group.demo.tsx

Expand Down
22 changes: 21 additions & 1 deletion docs/src/pages/components/radio.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,18 @@ import { Radio } from '@marigold/components';
description: 'Set the radio group disabled.',
default: 'false',
},
{
property: 'description',
type: 'string',
description: 'Set the radio group helptext.',
default: 'none',
},
{
property: 'errorMessage',
type: 'string',
description: 'Set the radio group error message if an error occures.',
default: 'none',
},
]}
/>

Expand All @@ -138,10 +150,18 @@ Here you can see a complete disabled `<Radio.Group>`. You can also just disable

```

### Required radio with horizontal orientation
### Required Radio with horizontal orientation

In this example the `<Radio.Group>` is required and the `orientation` is set to `horizontal`. With these props you can determine the direction of the `<Radio>` options.

```tsx preview file=components/Radio/radio-required.demo.tsx

```

### Error Radio

In this example you can see how an `errorMessage` would look on a `<RadioGroup>`.

```tsx preview file=components/Radio/radio-error.demo.tsx

```
4 changes: 2 additions & 2 deletions packages/components/src/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
const styles = useComponentStyles(
'Checkbox',
{
variant: groupState?.variant || variant,
size: groupState?.size || size,
variant,
size,
},
{ parts: ['container', 'label', 'checkbox'] }
);
Expand Down
32 changes: 31 additions & 1 deletion packages/components/src/Checkbox/CheckboxGroup.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,37 @@ export const Basic: ComponentStory<typeof CheckboxGroup> = args => {
const [selected, setSelected] = React.useState<string[]>([]);
return (
<>
<CheckboxGroup {...args} onChange={setSelected}>
<CheckboxGroup
{...args}
onChange={setSelected}
description="Choose your Options"
errorMessage="Oh no"
>
<Checkbox value="ham">Ham</Checkbox>
<Checkbox value="salami" disabled>
Salami
</Checkbox>
<Checkbox value="cheese">Cheese</Checkbox>
<Checkbox value="tomato">Tomate</Checkbox>
<Checkbox value="cucumber">Cucumber</Checkbox>
<Checkbox value="onions">Onions</Checkbox>
</CheckboxGroup>
<hr />
<pre>Selected values: {selected.join(', ')}</pre>
</>
);
};

export const Error: ComponentStory<typeof CheckboxGroup> = args => {
const [selected, setSelected] = React.useState<string[]>([]);
return (
<>
<CheckboxGroup
onChange={setSelected}
error
errorMessage="This is an error"
{...args}
>
<Checkbox value="ham">Ham</Checkbox>
<Checkbox value="salami" disabled>
Salami
Expand Down
103 changes: 36 additions & 67 deletions packages/components/src/Checkbox/CheckboxGroup.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,73 +97,6 @@ test('label is optional (can use aria-label instead)', () => {
expect(screen.getByText('three')).toBeInTheDocument();
});

test('allows styling container via theme', () => {
render(
<ThemeProvider theme={theme}>
<CheckboxGroup label="Group of Checkboxes">
<Checkbox value="one" data-testid="one">
one
</Checkbox>
<Checkbox value="two" data-testid="two">
two
</Checkbox>
</CheckboxGroup>
</ThemeProvider>
);

const container = screen.getByRole('group');
expect(container).toHaveStyle(`background: ${theme.colors.gray}`);

const group = screen.getByRole('presentation');
expect(group).toHaveStyle(`font-style: italic`);
});

test('supports styling via variant and size', () => {
render(
<ThemeProvider theme={theme}>
<CheckboxGroup label="Group of Checkboxes" variant="teal" size="large">
<Checkbox value="one" data-testid="one">
one
</Checkbox>
<Checkbox value="two" data-testid="two">
two
</Checkbox>
</CheckboxGroup>
</ThemeProvider>
);

const container = screen.getByRole('group');
expect(container).toHaveStyle(`background: ${theme.colors.teal}`);

const group = screen.getByRole('presentation');
expect(group).toHaveStyle(`font-size: ${theme.fontSizes['large-1']}px`);
});

test('passed down variant and size to checkboxes', () => {
render(
<ThemeProvider theme={theme}>
<CheckboxGroup label="Group of Checkboxes" variant="teal" size="large">
<Checkbox value="one" data-testid="one">
one
</Checkbox>
<Checkbox value="two" data-testid="two">
two
</Checkbox>
</CheckboxGroup>
</ThemeProvider>
);

expect(screen.getByText('one')).toHaveStyle(`color: ${theme.colors.teal}`);
expect(screen.getByText('one')).toHaveStyle(
`font-size: ${theme.fontSizes['small-1']}px`
);

expect(screen.getByText('two')).toHaveStyle(`color: ${theme.colors.teal}`);
expect(screen.getByText('two')).toHaveStyle(
`font-size: ${theme.fontSizes['small-1']}px`
);
});

test('passes down "disabled" to checkboxes', () => {
render(
<CheckboxGroup label="Group of Checkboxes" disabled>
Expand Down Expand Up @@ -260,3 +193,39 @@ test('controlled', () => {
fireEvent.click(screen.getByTestId('three'));
expect(onChange).toHaveBeenCalledWith(['one', 'two']);
});

test('accepts description', () => {
render(
<CheckboxGroup label="Group of Checkboxes" description="My description">
<Checkbox value="one" data-testid="one">
one
</Checkbox>
<Checkbox value="two" data-testid="two">
two
</Checkbox>
<Checkbox value="three" data-testid="three">
three
</Checkbox>
</CheckboxGroup>
);

expect(screen.getByText('My description')).toBeInTheDocument();
});

test('accepts error message', () => {
render(
<CheckboxGroup label="Group of Checkboxes" error errorMessage="My Error">
<Checkbox value="one" data-testid="one">
one
</Checkbox>
<Checkbox value="two" data-testid="two">
two
</Checkbox>
<Checkbox value="three" data-testid="three">
three
</Checkbox>
</CheckboxGroup>
);

expect(screen.getByText('My Error')).toBeInTheDocument();
});
56 changes: 24 additions & 32 deletions packages/components/src/Checkbox/CheckboxGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,15 @@ import {
} from '@react-stately/checkbox';
import { AriaCheckboxGroupProps } from '@react-types/checkbox';

import {
Box,
ThemeExtensionsWithParts,
useComponentStyles,
} from '@marigold/system';
import { Box, useStateProps } from '@marigold/system';
import { ComponentProps } from '@marigold/types';

import { Label } from '../Label';
import { FieldBase } from '../FieldBase';

// Context
// ---------------
export interface CheckboxGroupContextProps extends CheckboxGroupState {
error?: boolean;
variant?: string;
size?: string;
}

/**
Expand All @@ -32,11 +26,6 @@ export const CheckboxGroupContext = createContext<CheckboxGroupContextProps>(
);
export const useCheckboxGroupContext = () => useContext(CheckboxGroupContext);

// Theme Extension
// ---------------
export interface CheckboxGroupThemeExtension
extends ThemeExtensionsWithParts<'CheckboxGroup', ['container', 'group']> {}

// Props
// ---------------
interface CheckboxGroupProps
Expand All @@ -59,8 +48,6 @@ interface CheckboxGroupProps
// ---------------
export const CheckboxGroup = ({
children,
variant,
size,
required,
disabled,
readOnly,
Expand All @@ -76,36 +63,41 @@ export const CheckboxGroup = ({
} as const;

const state = useCheckboxGroupState(props);
const { groupProps, labelProps } = useCheckboxGroup(props, state);
const { groupProps, labelProps, descriptionProps, errorMessageProps } =
useCheckboxGroup(props, state);

const styles = useComponentStyles(
'CheckboxGroup',
{ variant, size },
{ parts: ['container', 'group'] }
);
const stateProps = useStateProps({
disabled,
readOnly,
error,
});

return (
<Box {...groupProps} css={styles.container}>
{props.label && (
<Label as="span" required={required} {...labelProps}>
{props.label}
</Label>
)}
<FieldBase
label={props.label}
labelProps={{ as: 'span', ...labelProps }}
description={props.description}
descriptionProps={descriptionProps}
error={error}
errorMessage={props.errorMessage}
errorMessageProps={errorMessageProps}
disabled={disabled}
stateProps={stateProps}
required={required}
{...groupProps}
>
<Box
role="presentation"
__baseCSS={{
display: 'flex',
flexDirection: 'column',
alignItems: 'start',
}}
css={styles.group}
>
<CheckboxGroupContext.Provider
value={{ variant, size, error, ...state }}
>
<CheckboxGroupContext.Provider value={{ error, ...state }}>
{children}
</CheckboxGroupContext.Provider>
</Box>
</Box>
</FieldBase>
);
};
13 changes: 12 additions & 1 deletion packages/components/src/Radio/Radio.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,18 @@ export default {
} as Meta;

export const Basic: ComponentStory<typeof Radio.Group> = args => (
<Radio.Group {...args}>
<Radio.Group {...args} description="Hier steht ein HelpText">
<Radio value="1">Option 1</Radio>
<Radio value="2">Option 2</Radio>
<Radio value="3" disabled>
Option 3
</Radio>
<Radio value="4">Option 4</Radio>
</Radio.Group>
);

export const Error: ComponentStory<typeof Radio.Group> = args => (
<Radio.Group errorMessage="Das ist ein Error" error {...args}>
<Radio value="1">Option 1</Radio>
<Radio value="2">Option 2</Radio>
<Radio value="3" disabled>
Expand Down
Loading

0 comments on commit 1bcfcf8

Please sign in to comment.