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

[Joy] Miscellaneous fixes #37274

Merged
merged 6 commits into from
May 15, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
61 changes: 61 additions & 0 deletions docs/data/joy/components/modal/ResponsiveModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import * as React from 'react';
import Box from '@mui/joy/Box';
import Button from '@mui/joy/Button';
import Modal from '@mui/joy/Modal';
import ModalDialog from '@mui/joy/ModalDialog';
import Typography from '@mui/joy/Typography';

export default function ResponsiveModal() {
const [open, setOpen] = React.useState(false);
return (
<React.Fragment>
<Button variant="outlined" color="neutral" onClick={() => setOpen(true)}>
Open modal
</Button>
<Modal open={open} onClose={() => setOpen(false)}>
<ModalDialog
aria-labelledby="nested-modal-title"
aria-describedby="nested-modal-description"
sx={(theme) => ({
[theme.breakpoints.only('xs')]: {
top: 'unset',
bottom: 0,
left: 0,
right: 0,
borderRadius: 0,
transform: 'none',
maxWidth: 'unset',
},
})}
>
<Typography id="nested-modal-title" component="h2">
Are you absolutely sure?
</Typography>
<Typography id="nested-modal-description" textColor="text.tertiary">
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
</Typography>
<Box
sx={{
mt: 1,
display: 'flex',
gap: 1,
flexDirection: { xs: 'column', sm: 'row-reverse' },
}}
>
<Button variant="solid" color="neutral" onClick={() => setOpen(false)}>
Continue
</Button>
<Button
variant="outlined"
color="neutral"
onClick={() => setOpen(false)}
>
Cancel
</Button>
</Box>
</ModalDialog>
</Modal>
</React.Fragment>
);
}
61 changes: 61 additions & 0 deletions docs/data/joy/components/modal/ResponsiveModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import * as React from 'react';
import Box from '@mui/joy/Box';
import Button from '@mui/joy/Button';
import Modal from '@mui/joy/Modal';
import ModalDialog from '@mui/joy/ModalDialog';
import Typography from '@mui/joy/Typography';

export default function ResponsiveModal() {
const [open, setOpen] = React.useState(false);
return (
<React.Fragment>
<Button variant="outlined" color="neutral" onClick={() => setOpen(true)}>
Open modal
</Button>
<Modal open={open} onClose={() => setOpen(false)}>
<ModalDialog
aria-labelledby="nested-modal-title"
aria-describedby="nested-modal-description"
sx={(theme) => ({
[theme.breakpoints.only('xs')]: {
top: 'unset',
bottom: 0,
left: 0,
right: 0,
borderRadius: 0,
transform: 'none',
maxWidth: 'unset',
},
})}
>
<Typography id="nested-modal-title" component="h2">
Are you absolutely sure?
</Typography>
<Typography id="nested-modal-description" textColor="text.tertiary">
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
</Typography>
<Box
sx={{
mt: 1,
display: 'flex',
gap: 1,
flexDirection: { xs: 'column', sm: 'row-reverse' },
}}
>
<Button variant="solid" color="neutral" onClick={() => setOpen(false)}>
Continue
</Button>
<Button
variant="outlined"
color="neutral"
onClick={() => setOpen(false)}
>
Cancel
</Button>
</Box>
</ModalDialog>
</Modal>
</React.Fragment>
);
}
8 changes: 8 additions & 0 deletions docs/data/joy/components/modal/modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,14 @@ Therefore, in order to display a modal rendered on the server, disable the porta

{{"demo": "ServerModal.js", "defaultCodeOpen": false}}

## Common examples

### Mobile modal

Use `sx` prop with `theme.breakpoints.only('xs')` to customize the styles of the modal dialog to stick at the bottom in mobile viewport.

{{"demo": "ResponsiveModal.js"}}

## Limitations

### Focus trap
Expand Down
21 changes: 20 additions & 1 deletion docs/data/joy/components/table/TableStickyHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,21 @@ const rows = [
createData('10', 356, 16.0, 49, 3.9),
];

function sum(column) {
return rows.reduce((acc, row) => acc + row[column], 0);
}

export default function TableStickyHeader() {
return (
<div>
<Typography level="body2" textAlign="center" sx={{ mb: 2 }}>
The table body is scrollable.
</Typography>
<Sheet sx={{ height: 200, overflow: 'auto' }}>
<Sheet sx={{ height: 300, overflow: 'auto' }}>
<Table
aria-label="table with sticky header"
stickyHeader
stickyFooter
stripe="odd"
hoverRow
>
Expand All @@ -52,6 +57,20 @@ export default function TableStickyHeader() {
</tr>
))}
</tbody>
<tfoot>
<tr>
<th scope="row">Totals</th>
<td>{sum('calories').toFixed(2)}</td>
<td>{sum('fat').toFixed(2)}</td>
<td>{sum('carbs').toFixed(2)}</td>
<td>{sum('protein').toFixed(2)}</td>
</tr>
<tr>
<td colSpan={5} style={{ textAlign: 'center' }}>
{sum('calories') + sum('fat') + sum('carbs') + sum('protein')} Kcal
</td>
</tr>
</tfoot>
</Table>
</Sheet>
</div>
Expand Down
20 changes: 19 additions & 1 deletion docs/data/joy/components/table/TableStickyHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,21 @@ const rows = [
createData('9', 305, 3.7, 67, 4.3),
createData('10', 356, 16.0, 49, 3.9),
];
function sum(column: 'calories' | 'fat' | 'carbs' | 'protein') {
return rows.reduce((acc, row) => acc + row[column], 0);
}

export default function TableStickyHeader() {
return (
<div>
<Typography level="body2" textAlign="center" sx={{ mb: 2 }}>
The table body is scrollable.
</Typography>
<Sheet sx={{ height: 200, overflow: 'auto' }}>
<Sheet sx={{ height: 300, overflow: 'auto' }}>
<Table
aria-label="table with sticky header"
stickyHeader
stickyFooter
stripe="odd"
hoverRow
>
Expand All @@ -58,6 +62,20 @@ export default function TableStickyHeader() {
</tr>
))}
</tbody>
<tfoot>
<tr>
<th scope="row">Totals</th>
<td>{sum('calories').toFixed(2)}</td>
<td>{sum('fat').toFixed(2)}</td>
<td>{sum('carbs').toFixed(2)}</td>
<td>{sum('protein').toFixed(2)}</td>
</tr>
<tr>
<td colSpan={5} style={{ textAlign: 'center' }}>
{sum('calories') + sum('fat') + sum('carbs') + sum('protein')} Kcal
</td>
</tr>
</tfoot>
</Table>
</Sheet>
</div>
Expand Down
106 changes: 61 additions & 45 deletions docs/data/joy/components/table/TableUsage.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,20 @@ export default function ButtonUsage() {
knob: 'switch',
defaultValue: false,
},
{
propName: 'stickyFooter',
knob: 'switch',
defaultValue: false,
},
{
propName: 'stripe',
knob: 'radio',
options: ['odd', 'even'],
},
]}
getCodeBlock={(code) => `<Sheet>
${code}
</Sheet>`}
renderDemo={(props) => (
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<Typography
Expand All @@ -54,51 +62,59 @@ export default function ButtonUsage() {
>
The table is scrollable.
</Typography>
<Sheet
variant="outlined"
sx={{
height: 200,
overflow: 'auto',
p: 2,
borderRadius: 'sm',
}}
>
<Table {...props}>
<thead>
<tr>
<th style={{ width: 64 }}>ID</th>
<th>Job Title</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Doctor</td>
<td>Chris Johnson</td>
</tr>
<tr>
<td>2</td>
<td>Electrician</td>
<td>Joseph Morris</td>
</tr>
<tr>
<td>3</td>
<td>Operator</td>
<td>Aiden Moreno</td>
</tr>
<tr>
<td>4</td>
<td>Baker</td>
<td>Mike Simmons</td>
</tr>
<tr>
<td>5</td>
<td>Clerk</td>
<td>Enoch Addison</td>
</tr>
</tbody>
</Table>
<Sheet variant="outlined" sx={{ p: 2, borderRadius: 'sm' }}>
<Sheet
sx={{
height: 200,
overflow: 'auto',
borderRadius: 0,
}}
>
<Table {...props}>
<thead>
<tr>
<th style={{ width: 64 }}>ID</th>
<th>Job Title</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Doctor</td>
<td>Chris Johnson</td>
</tr>
<tr>
<td>2</td>
<td>Electrician</td>
<td>Joseph Morris</td>
</tr>
<tr>
<td>3</td>
<td>Operator</td>
<td>Aiden Moreno</td>
</tr>
<tr>
<td>4</td>
<td>Baker</td>
<td>Mike Simmons</td>
</tr>
<tr>
<td>5</td>
<td>Clerk</td>
<td>Enoch Addison</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Total</td>
<td colSpan={2} style={{ textAlign: 'center' }}>
4 people
</td>
</tr>
</tfoot>
</Table>
</Sheet>
</Sheet>
</Box>
)}
Expand Down
8 changes: 5 additions & 3 deletions docs/data/joy/components/table/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,14 @@ declare module '@mui/joy/Table' {
}
```

### Sticky header
### Sticky header and footer

Set the `stickyHeader` prop to true to make the header follow the user as they scroll down the page.
Set the `stickyHeader` to true to always stick the header at the top as users scroll the table.

Set the `stickyFooter` to true to always stick the footer at the bottom of the table.

:::success
For `stickyHeader` to work correctly, the Table must be a child of a fixed-height element with overflow `auto` (or `scroll`).
For `stickyHeader` and `stickyFooter` to work correctly, the Table must be a child of a fixed-height element with overflow `auto` (or `scroll`).
We recommend wrapping your Table with [Sheet](/joy-ui/react-sheet/) for this purpose.
See [usage with Sheet](#usage-with-sheet) to learn more.
:::
Expand Down
2 changes: 2 additions & 0 deletions docs/pages/joy-ui/api/table.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"type": { "name": "shape", "description": "{ root?: elementType }" },
"default": "{}"
},
"stickyFooter": { "type": { "name": "bool" }, "default": "false" },
"stickyHeader": { "type": { "name": "bool" }, "default": "false" },
"stripe": {
"type": {
Expand Down Expand Up @@ -85,6 +86,7 @@
"sizeLg",
"sizeMd",
"sizeSm",
"stickyFooter",
"stickyHeader",
"variantOutlined",
"variantPlain",
Expand Down
Loading