Skip to content

Commit

Permalink
[Joy] Miscellaneous fixes and docs improvement (mui#37026)
Browse files Browse the repository at this point in the history
  • Loading branch information
siriwatknp authored and binh1298 committed May 17, 2023
1 parent 7f34732 commit 16e4475
Show file tree
Hide file tree
Showing 22 changed files with 330 additions and 25 deletions.
37 changes: 37 additions & 0 deletions docs/data/joy/components/aspect-ratio/IconWrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as React from 'react';
import AspectRatio from '@mui/joy/AspectRatio';
import Stack from '@mui/joy/Stack';
import Favorite from '@mui/icons-material/Favorite';

export default function IconWrapper() {
return (
<Stack direction="row" spacing={2}>
<AspectRatio ratio="1" variant="solid" color="primary" sx={{ minWidth: 40 }}>
{/* an extra div is required to make the icon center */}
<div>
<Favorite />
</div>
</AspectRatio>
<AspectRatio
ratio="1"
variant="outlined"
color="success"
sx={{ minWidth: 40, borderRadius: 'sm' }}
>
<div>
<Favorite />
</div>
</AspectRatio>
<AspectRatio
ratio="1"
variant="soft"
color="danger"
sx={{ minWidth: 40, borderRadius: '50%' }}
>
<div>
<Favorite />
</div>
</AspectRatio>
</Stack>
);
}
37 changes: 37 additions & 0 deletions docs/data/joy/components/aspect-ratio/IconWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as React from 'react';
import AspectRatio from '@mui/joy/AspectRatio';
import Stack from '@mui/joy/Stack';
import Favorite from '@mui/icons-material/Favorite';

export default function IconWrapper() {
return (
<Stack direction="row" spacing={2}>
<AspectRatio ratio="1" variant="solid" color="primary" sx={{ minWidth: 40 }}>
{/* an extra div is required to make the icon center */}
<div>
<Favorite />
</div>
</AspectRatio>
<AspectRatio
ratio="1"
variant="outlined"
color="success"
sx={{ minWidth: 40, borderRadius: 'sm' }}
>
<div>
<Favorite />
</div>
</AspectRatio>
<AspectRatio
ratio="1"
variant="soft"
color="danger"
sx={{ minWidth: 40, borderRadius: '50%' }}
>
<div>
<Favorite />
</div>
</AspectRatio>
</Stack>
);
}
12 changes: 10 additions & 2 deletions docs/data/joy/components/aspect-ratio/aspect-ratio.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ This is useful when the Aspect Ratio component wraps dynamic-width content, as s

{{"demo": "MinMaxRatio.js"}}

## Usage inside a flex row
## Using inside a flex row

When the Aspect Ratio component is a child of a flexbox `row` container, use `flex-basis` to set the ideal width of the content:

{{"demo": "FlexRowRatio.js"}}

## Usage with Next.js Image
## Using with Next.js Image

The Aspect Ratio component can be used with a [Next.js Image](https://nextjs.org/docs/basic-features/image-optimization) component as a child.
The Image should always include the `layout="fill"` property—otherwise it requires `height` and `width` values, which would defeat the purpose of the Aspect Ratio component.
Expand All @@ -102,6 +102,14 @@ function App() {
}
```

## Using with an icon

The Aspect Ratio component can be a handy tool for creating a square container for an icon.

The example below show

{{"demo": "IconWrapper.js"}}

## Common examples

### Mobile carousel
Expand Down
2 changes: 1 addition & 1 deletion docs/data/joy/components/grid/SpacingGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default function SpacingGrid() {
<Grid container>
<Grid>
<FormControl>
<FormLabel sx={{ mb: 1.5 }}>spacing</FormLabel>
<FormLabel>spacing</FormLabel>
<RadioGroup
name="spacing"
aria-label="spacing"
Expand Down
2 changes: 1 addition & 1 deletion docs/data/joy/components/grid/SpacingGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default function SpacingGrid() {
<Grid container>
<Grid>
<FormControl>
<FormLabel sx={{ mb: 1.5 }}>spacing</FormLabel>
<FormLabel>spacing</FormLabel>
<RadioGroup
name="spacing"
aria-label="spacing"
Expand Down
51 changes: 51 additions & 0 deletions docs/data/joy/components/select/ControlledOpenSelect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as React from 'react';
import Stack from '@mui/joy/Stack';
import Select from '@mui/joy/Select';
import Option from '@mui/joy/Option';
import Button from '@mui/joy/Button';

export default function ControlledOpenSelect() {
const [age, setAge] = React.useState('');
const [open, setOpen] = React.useState(false);
const skipRef = React.useRef(false);

const handleChange = (event, newValue) => {
setAge(newValue);
};

return (
<Stack spacing={2} useFlexGap>
<Button
variant="soft"
onMouseDown={() => {
skipRef.current = true;
}}
onClick={() => {
skipRef.current = false;
setOpen((bool) => !bool);
}}
>
Open the select
</Button>
<div>
<Select
listboxOpen={open}
onListboxOpenChange={(isOpen) => {
if (!skipRef.current) {
setOpen(isOpen);
}
}}
value={age}
onChange={handleChange}
>
<Option value="">
<em>None</em>
</Option>
<Option value={10}>Ten</Option>
<Option value={20}>Twenty</Option>
<Option value={30}>Thirty</Option>
</Select>
</div>
</Stack>
);
}
54 changes: 54 additions & 0 deletions docs/data/joy/components/select/ControlledOpenSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as React from 'react';
import Stack from '@mui/joy/Stack';
import Select from '@mui/joy/Select';
import Option from '@mui/joy/Option';
import Button from '@mui/joy/Button';

export default function ControlledOpenSelect() {
const [age, setAge] = React.useState('');
const [open, setOpen] = React.useState(false);
const skipRef = React.useRef(false);

const handleChange = (
event: React.SyntheticEvent | null,
newValue: string | null,
) => {
setAge(newValue!);
};

return (
<Stack spacing={2} useFlexGap>
<Button
variant="soft"
onMouseDown={() => {
skipRef.current = true;
}}
onClick={() => {
skipRef.current = false;
setOpen((bool) => !bool);
}}
>
Open the select
</Button>
<div>
<Select
listboxOpen={open}
onListboxOpenChange={(isOpen) => {
if (!skipRef.current) {
setOpen(isOpen);
}
}}
value={age}
onChange={handleChange}
>
<Option value="">
<em>None</em>
</Option>
<Option value={10}>Ten</Option>
<Option value={20}>Twenty</Option>
<Option value={30}>Thirty</Option>
</Select>
</div>
</Stack>
);
}
5 changes: 4 additions & 1 deletion docs/data/joy/components/select/SelectBasic.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import Select from '@mui/joy/Select';
import Option from '@mui/joy/Option';

export default function SelectBasic() {
const handleChange = (event, newValue) => {
alert(`You chose "${newValue}"`);
};
return (
<Select defaultValue="dog">
<Select defaultValue="dog" onChange={handleChange}>
<Option value="dog">Dog</Option>
<Option value="cat">Cat</Option>
<Option value="fish">Fish</Option>
Expand Down
8 changes: 7 additions & 1 deletion docs/data/joy/components/select/SelectBasic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@ import Select from '@mui/joy/Select';
import Option from '@mui/joy/Option';

export default function SelectBasic() {
const handleChange = (
event: React.SyntheticEvent | null,
newValue: string | null,
) => {
alert(`You chose "${newValue}"`);
};
return (
<Select defaultValue="dog">
<Select defaultValue="dog" onChange={handleChange}>
<Option value="dog">Dog</Option>
<Option value="cat">Cat</Option>
<Option value="fish">Fish</Option>
Expand Down
2 changes: 1 addition & 1 deletion docs/data/joy/components/select/SelectBasic.tsx.preview
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Select defaultValue="dog">
<Select defaultValue="dog" onChange={handleChange}>
<Option value="dog">Dog</Option>
<Option value="cat">Cat</Option>
<Option value="fish">Fish</Option>
Expand Down
6 changes: 6 additions & 0 deletions docs/data/joy/components/select/select.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ To control the placement of the listbox, use `placement`:
:::
#### Controlling the open state
You can control the open state of the select with the `listboxOpen` prop. Alternatively, it is also possible to set the initial (uncontrolled) open state of the component with the `defaultListboxOpen` prop.
{{"demo": "ControlledOpenSelect.js"}}
### `Option` component
The `Option` component is used for the choosable options within the select.
Expand Down
2 changes: 1 addition & 1 deletion docs/data/joy/components/switch/SwitchUsage.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function SwitchUsage() {
options: ['sm', 'md', 'lg'],
defaultValue: 'md',
},
{ propName: 'checked', knob: 'switch', defaultValue: false },
{ propName: 'checked', knob: 'controlled' },
{ propName: 'disabled', knob: 'switch' },
]}
renderDemo={(props) => <Switch {...props} />}
Expand Down
26 changes: 26 additions & 0 deletions docs/data/joy/guides/using-icon-libraries/using-icon-libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,29 @@ Here is a collection of well-known icon libraries that you can use with Joy UI.
allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
></iframe>
### Iconify

- [Browse icons](https://icon-sets.iconify.design/)
- [Installation—React](https://docs.iconify.design/icon-components/react/)
- [Installation—Web component](https://docs.iconify.design/iconify-icon/)
- [Figma plugin](https://docs.iconify.design/design/figma/)

<iframe src="https://codesandbox.io/embed/joy-ui-iconify-r8fjrm?fontsize=12&hidenavigation=1&module=%2Fdemo.tsx&theme=dark"
style="width:100%; height:250px; border:0; border-radius: 12px; overflow:hidden;"
title="joy-ui-iconify"
allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
></iframe>
### Lucide

- [Browse icons](https://icon-sets.iconify.design/)
- [Installation—React](https://lucide.dev/docs/lucide-react)

<iframe src="https://codesandbox.io/embed/joy-ui-lucide-sy7hio?fontsize=12&hidenavigation=1&module=%2Fdemo.tsx&theme=dark"
style="width:100%; height:250px; border:0; border-radius: 12px; overflow:hidden;"
title="joy-ui-lucide"
allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
></iframe>
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default function InputIntegration() {
placeholder="Password"
type="password"
endDecorator={
<IconButton color="neutral" size="sm">
<IconButton color="neutral">
<VisibilityRoundedIcon />
</IconButton>
}
Expand All @@ -24,7 +24,7 @@ export default function InputIntegration() {
placeholder="Password"
type="password"
endDecorator={
<IconButton color="neutral" size="sm">
<IconButton color="neutral">
<VisibilityRoundedIcon />
</IconButton>
}
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-joy/src/AspectRatio/AspectRatio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const AspectRatioContent = styled('div', {
position: 'relative',
borderRadius: 'inherit',
height: 0,
paddingBottom: 'var(--AspectRatio-paddingBottom)',
paddingBottom: 'calc(var(--AspectRatio-paddingBottom) - 2 * var(--variant-borderWidth, 0px))',
overflow: 'hidden',
// use data-attribute instead of :first-child to support zero config SSR (emotion)
// use nested selector for integrating with nextjs image `fill` layout (spans are inserted on top of the img)
Expand Down
33 changes: 30 additions & 3 deletions packages/mui-joy/src/FormControl/FormControl.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -300,11 +300,12 @@ describe('<FormControl />', () => {
});

it('works with radio buttons', () => {
const { getByLabelText, getByRole, getByText } = render(
const { getByLabelText, getByRole, getByText, getAllByRole } = render(
<FormControl>
<FormLabel>label</FormLabel>
<RadioGroup>
<Radio />
<Radio value="1" />
<Radio value="2" />
</RadioGroup>
<FormHelperText>helper text</FormHelperText>
</FormControl>,
Expand All @@ -313,11 +314,37 @@ describe('<FormControl />', () => {
const label = getByText('label');
const helperText = getByText('helper text');

expect(getByRole('radio')).toBeVisible();
expect(getAllByRole('radio')).to.have.length(2);
expect(getByLabelText('label')).to.have.attribute('role', 'radiogroup');
expect(getByRole('radiogroup')).to.have.attribute('aria-labelledby', label.id);
expect(getByRole('radiogroup')).to.have.attribute('aria-describedby', helperText.id);
});

it('radio buttons should inherit size from the FormControl', () => {
const { getByTestId } = render(
<FormControl size="sm">
<FormLabel>label</FormLabel>
<RadioGroup>
<Radio value="1" data-testid="radio1" />
</RadioGroup>
<FormHelperText>helper text</FormHelperText>
</FormControl>,
);
expect(getByTestId('radio1')).to.have.class(radioClasses.sizeSm);
});

it('radio buttons should inherit size from the RadioGroup', () => {
const { getByTestId } = render(
<FormControl size="sm">
<FormLabel>label</FormLabel>
<RadioGroup size="md">
<Radio value="1" data-testid="radio1" />
</RadioGroup>
<FormHelperText>helper text</FormHelperText>
</FormControl>,
);
expect(getByTestId('radio1')).to.have.class(radioClasses.sizeMd);
});
});

describe('Radio', () => {
Expand Down

0 comments on commit 16e4475

Please sign in to comment.