Skip to content

Commit

Permalink
[system] Add Container component and createContainer factory (#32263
Browse files Browse the repository at this point in the history
)
  • Loading branch information
mnajdova authored May 11, 2022
1 parent 7028a34 commit 41a5f13
Show file tree
Hide file tree
Showing 39 changed files with 781 additions and 138 deletions.
14 changes: 14 additions & 0 deletions docs/data/system/components/container/FixedContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as React from 'react';
import CssBaseline from '@mui/material/CssBaseline';
import { Box, Container } from '@mui/system';

export default function FixedContainer() {
return (
<React.Fragment>
<CssBaseline />
<Container fixed>
<Box sx={{ bgcolor: '#cfe8fc', height: '100vh' }} />
</Container>
</React.Fragment>
);
}
14 changes: 14 additions & 0 deletions docs/data/system/components/container/FixedContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as React from 'react';
import CssBaseline from '@mui/material/CssBaseline';
import { Box, Container } from '@mui/system';

export default function FixedContainer() {
return (
<React.Fragment>
<CssBaseline />
<Container fixed>
<Box sx={{ bgcolor: '#cfe8fc', height: '100vh' }} />
</Container>
</React.Fragment>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<React.Fragment>
<CssBaseline />
<Container fixed>
<Box sx={{ bgcolor: '#cfe8fc', height: '100vh' }} />
</Container>
</React.Fragment>
14 changes: 14 additions & 0 deletions docs/data/system/components/container/SimpleContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as React from 'react';
import CssBaseline from '@mui/material/CssBaseline';
import { Box, Container } from '@mui/system';

export default function SimpleContainer() {
return (
<React.Fragment>
<CssBaseline />
<Container maxWidth="sm">
<Box sx={{ bgcolor: '#cfe8fc', height: '100vh' }} />
</Container>
</React.Fragment>
);
}
14 changes: 14 additions & 0 deletions docs/data/system/components/container/SimpleContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as React from 'react';
import CssBaseline from '@mui/material/CssBaseline';
import { Box, Container } from '@mui/system';

export default function SimpleContainer() {
return (
<React.Fragment>
<CssBaseline />
<Container maxWidth="sm">
<Box sx={{ bgcolor: '#cfe8fc', height: '100vh' }} />
</Container>
</React.Fragment>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<React.Fragment>
<CssBaseline />
<Container maxWidth="sm">
<Box sx={{ bgcolor: '#cfe8fc', height: '100vh' }} />
</Container>
</React.Fragment>
35 changes: 35 additions & 0 deletions docs/data/system/components/container/container.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
product: system
title: React Container component
components: Container
githubLabel: 'component: Container'
---

# Container

<p class="description">The container centers your content horizontally. It's the most basic layout element.</p>

While containers can be nested, most layouts do not require a nested container.

{{"component": "modules/components/ComponentLinkHeader.js", "design": false}}

## Fluid

A fluid container width is bounded by the `maxWidth` prop value.

{{"demo": "SimpleContainer.js", "iframe": true, "defaultCodeOpen": false}}

```jsx
<Container maxWidth="sm">
```

## Fixed

If you prefer to design for a fixed set of sizes instead of trying to accommodate a fully fluid viewport, you can set the `fixed` prop.
The max-width matches the min-width of the current breakpoint.

{{"demo": "FixedContainer.js", "iframe": true, "defaultCodeOpen": false}}

```jsx
<Container fixed>
```
5 changes: 4 additions & 1 deletion docs/data/system/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ const pages = [
pathname: '/system/react-',
title: 'Components',
icon: 'ToggleOnIcon',
children: [{ pathname: '/system/react-box', title: 'Box' }],
children: [
{ pathname: '/system/react-box', title: 'Box' },
{ pathname: '/system/react-container', title: 'Container' },
],
},
{
title: 'Component API',
Expand Down
5 changes: 4 additions & 1 deletion docs/data/system/pagesApi.js
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
module.exports = [{ pathname: '/system/api/box' }];
module.exports = [
{ pathname: '/system/api/box' },
{ pathname: '/system/api/container' },
];
3 changes: 1 addition & 2 deletions docs/pages/material-ui/api/container.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
"type": {
"name": "union",
"description": "'xs'<br>&#124;&nbsp;'sm'<br>&#124;&nbsp;'md'<br>&#124;&nbsp;'lg'<br>&#124;&nbsp;'xl'<br>&#124;&nbsp;false<br>&#124;&nbsp;string"
},
"default": "'lg'"
}
},
"sx": {
"type": {
Expand Down
19 changes: 19 additions & 0 deletions docs/pages/system/api/container.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from 'react';
import ApiPage from 'docs/src/modules/components/ApiPage';
import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations';
import jsonPageContent from './container.json';

export default function Page(props) {
const { descriptions, pageContent } = props;
return <ApiPage descriptions={descriptions} pageContent={pageContent} />;
}

Page.getInitialProps = () => {
const req = require.context('docs/translations/api-docs/container', false, /container.*.json$/);
const descriptions = mapApiPageTranslations(req);

return {
descriptions,
pageContent: jsonPageContent,
};
};
41 changes: 41 additions & 0 deletions docs/pages/system/api/container.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"props": {
"classes": { "type": { "name": "object" } },
"component": { "type": { "name": "elementType" } },
"disableGutters": { "type": { "name": "bool" } },
"fixed": { "type": { "name": "bool" } },
"maxWidth": {
"type": {
"name": "union",
"description": "'xs'<br>&#124;&nbsp;'sm'<br>&#124;&nbsp;'md'<br>&#124;&nbsp;'lg'<br>&#124;&nbsp;'xl'<br>&#124;&nbsp;false<br>&#124;&nbsp;string"
}
},
"sx": {
"type": {
"name": "union",
"description": "Array&lt;func<br>&#124;&nbsp;object<br>&#124;&nbsp;bool&gt;<br>&#124;&nbsp;func<br>&#124;&nbsp;object"
}
}
},
"name": "Container",
"styles": {
"classes": [
"root",
"disableGutters",
"fixed",
"maxWidthXs",
"maxWidthSm",
"maxWidthMd",
"maxWidthLg",
"maxWidthXl"
],
"globalClasses": {},
"name": "MuiContainer"
},
"spread": true,
"forwardsRefTo": "HTMLElement",
"filename": "/packages/mui-system/src/Container/Container.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/material-ui/react-container/\">Container (Material UI)</a></li>\n<li><a href=\"/system/react-container/\">Container (MUI System)</a></li></ul>",
"cssComponent": false
}
11 changes: 11 additions & 0 deletions docs/pages/system/react-container.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as React from 'react';
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs';
import {
demos,
docs,
demoComponents,
} from 'docs/data/system/components/container/container.md?@mui/markdown';

export default function Page() {
return <MarkdownDocs demos={demos} docs={docs} demoComponents={demoComponents} />;
}
2 changes: 1 addition & 1 deletion docs/scripts/ApiBuilders/ComponentApiBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ const attachPropsTable = (reactApi: ReactApi) => {
reactApi.propsTable = componentProps;
};

const systemComponents = ['Box'];
const systemComponents = ['Container', 'Box'];

/**
* - Build react component (specified filename) api by lookup at its definition (.d.ts or ts)
Expand Down
1 change: 1 addition & 0 deletions docs/translations/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
"/system/styled": "styled",
"/system/react-": "Components",
"/system/react-box": "Box",
"/system/react-container": "Container",
"/system/styles": "Styles",
"/system/styles/basics": "Basics",
"/system/styles/advanced": "Advanced",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ const rule = {
const { customHooks = [] } = options;

function resolveUseThemePropsNameLiteral(node) {
if (!node.arguments[0].properties) {
return null;
}
const nameProperty = node.arguments[0].properties.find(
(property) => property.key.name === 'name',
);
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-joy/src/Box/Box.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import PropTypes from 'prop-types';
import { createBox } from '@mui/system';
import PropTypes from 'prop-types';
import { OverridableComponent } from '@mui/types';
import { unstable_ClassNameGenerator as ClassNameGenerator } from '../className';
import { BoxTypeMap } from './BoxProps';
Expand Down
33 changes: 33 additions & 0 deletions packages/mui-joy/src/Container/Container.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as React from 'react';
import { expect } from 'chai';
import { describeConformance, createRenderer } from 'test/utils';
import Container, { containerClasses as classes } from '@mui/joy/Container';

describe('<Container />', () => {
const { render } = createRenderer();

const defaultProps = {
children: <div />,
};

describeConformance(<Container {...defaultProps} />, () => ({
classes,
inheritComponent: 'div',
render,
refInstanceof: window.HTMLElement,
muiName: 'MuiContainer',
skip: ['componentsProp'],
testVariantProps: { fixed: true },
}));

describe('prop: maxWidth', () => {
it('should support different maxWidth values', () => {
const { container: firstContainer } = render(<Container {...defaultProps} />);
expect(firstContainer.firstChild).to.have.class(classes.maxWidthLg);
const { container: secondsContainre } = render(
<Container {...defaultProps} maxWidth={false} />,
);
expect(secondsContainre.firstChild).not.to.have.class(classes.maxWidthLg);
});
});
});
66 changes: 66 additions & 0 deletions packages/mui-joy/src/Container/Container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* eslint-disable material-ui/mui-name-matches-component-name */
import { createContainer } from '@mui/system';
import PropTypes from 'prop-types';
import { OverridableComponent } from '@mui/types';
import { ContainerTypeMap } from './ContainerProps';
import { Theme } from '../styles/types/theme';
import styled from '../styles/styled';
import { useThemeProps } from '../styles';

const Container = createContainer<Theme>({
createStyledComponent: styled('div', {
name: 'MuiContainer',
slot: 'Root',
overridesResolver: (props, styles) => styles.root,
}),
useThemeProps: (inProps) => useThemeProps({ props: inProps, name: 'MuiContainer' }),
}) as OverridableComponent<ContainerTypeMap>;

Container.propTypes /* remove-proptypes */ = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* @ignore
*/
children: PropTypes.node,
/**
* The component used for the root node.
* Either a string to use a HTML element or a component.
*/
component: PropTypes.elementType,
/**
* If `true`, the left and right padding is removed.
* @default false
*/
disableGutters: PropTypes.bool,
/**
* Set the max-width to match the min-width of the current breakpoint.
* This is useful if you'd prefer to design for a fixed set of sizes
* instead of trying to accommodate a fully fluid viewport.
* It's fluid by default.
* @default false
*/
fixed: PropTypes.bool,
/**
* Determine the max-width of the container.
* The container width grows with the size of the screen.
* Set to `false` to disable `maxWidth`.
* @default 'lg'
*/
maxWidth: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl', false]),
PropTypes.string,
]),
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])),
PropTypes.func,
PropTypes.object,
]),
} as any;

export default Container;
40 changes: 40 additions & 0 deletions packages/mui-joy/src/Container/ContainerProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as React from 'react';
import { OverrideProps } from '@mui/types';
import { Breakpoint } from '@mui/system';
import { SxProps } from '../styles/types';

export interface ContainerTypeMap<P = {}, D extends React.ElementType = 'div'> {
props: P & {
children?: React.ReactNode;
/**
* If `true`, the left and right padding is removed.
* @default false
*/
disableGutters?: boolean;
/**
* Set the max-width to match the min-width of the current breakpoint.
* This is useful if you'd prefer to design for a fixed set of sizes
* instead of trying to accommodate a fully fluid viewport.
* It's fluid by default.
* @default false
*/
fixed?: boolean;
/**
* Determine the max-width of the container.
* The container width grows with the size of the screen.
* Set to `false` to disable `maxWidth`.
* @default 'lg'
*/
maxWidth?: Breakpoint | false;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps;
};
defaultComponent: D;
}

export type ContainerProps<
D extends React.ElementType = ContainerTypeMap['defaultComponent'],
P = {},
> = OverrideProps<ContainerTypeMap<P, D>, D>;
Loading

0 comments on commit 41a5f13

Please sign in to comment.