Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
20 changes: 20 additions & 0 deletions docs/pages/system/global-classes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs';
import { prepareMarkdown } from 'docs/src/modules/utils/parseMarkdown';

const pageFilename = 'system/global-classes';
const requireDemo = require.context('docs/src/pages/system/global-classes', false, /\.(js|tsx)$/);
const requireRaw = require.context(
'!raw-loader!../../src/pages/system/global-classes',
false,
/\.(js|md|tsx)$/,
);

export default function Page({ demos, docs }) {
return <MarkdownDocs demos={demos} docs={docs} requireDemo={requireDemo} />;
}

Page.getInitialProps = () => {
const { demos, docs } = prepareMarkdown({ pageFilename, requireRaw });
return { demos, docs };
};
1 change: 1 addition & 0 deletions docs/src/pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ const pages = [
{ pathname: '/system/screen-readers' },
{ pathname: '/system/typography' },
{ pathname: '/system/api', title: 'API' },
{ pathname: '/system/global-classes' },

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing the structure makes me think of how we don't explain well the value proposition of the helpers on the /basics page. http://material-ui.com/system/basics#real-world-use-case should be at the top like they did on https://tailwindcss.com/docs/utility-first. Or even https://chakra-ui.com/ on the homepage 😆

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was missing explanation a bit too to be honest..

],
},
{
Expand Down
53 changes: 53 additions & 0 deletions docs/src/pages/system/global-classes/Basics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Button from '@material-ui/core/Button';
import GlobalCss from './GlobalCss';

export default function App() {
return (
<div>
<GlobalCss />
<Button variant="contained" className="m-4 py-5">
Spacings
</Button>
<Button
variant="contained"
className="m-1 py-3 warning-light warning-dark--hover warning-contrastText--text"
>
Colors
</Button>
{Array.from(Array(24).keys()).map((val) => (
<Button className={`m-2 p-1 elevation-${val}`} key={val}>
Elevation {val}
</Button>
))}

{[
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'subtitle1',
'subtitle2',
'body1',
'body2',
'button',
'caption',
'overline',
].map((val) => (
<div className={`m2 p-1 text-${val}`}>Text {val}</div>
))}

<div className="d-inline mr-1">Inline</div>
<div className="d-inline d-print-none">Not visible when printed</div>
<div className="position-relative p-4 mb-16">
<div className="position-absolute p-4 top-4 left-0 grey-700 common-white--text">
Positioned
</div>
<div className="position-absolute p-4 top-14 left-5 zIndex-tooltip primary-light common-white--text">
zIndex tooltip
</div>
</div>
</div>
);
}
51 changes: 51 additions & 0 deletions docs/src/pages/system/global-classes/Basics.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Button from '@material-ui/core/Button';
import GlobalCss from './GlobalCss';

export default function App() {
return (
<div>
<GlobalCss />
<Button variant="contained" className="m-4 py-5">
Spacings
</Button>
<Button
variant="contained"
className="m-1 py-3 warning-light warning-dark--hover warning-contrastText--text"
>
Colors
</Button>
{Array.from(Array(24).keys()).map((val) => (
<Button className={`m-2 p-1 elevation-${val}`} key={val}>
Elevation {val}
</Button>
))}
{[
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'subtitle1',
'subtitle2',
'body1',
'body2',
'button',
'caption',
'overline',
].map((val) => (
<div className={`m2 p-1 text-${val}`}>Text {val}</div>
))}
<div className="d-inline mr-1">Inline</div>
<div className="d-inline d-print-none">Not visible when printed</div>
<div className="position-relative p-4 mb-16">
<div className="position-absolute p-4 top-4 left-0 grey-700 common-white--text">
Positioned
</div>
<div className="position-absolute p-4 top-14 left-5 zIndex-tooltip primary-light common-white--text">
zIndex tooltip
</div>
</div>
</div>
);
}
1 change: 1 addition & 0 deletions docs/src/pages/system/global-classes/GlobalCss.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function (): JSX.Element;
32 changes: 32 additions & 0 deletions docs/src/pages/system/global-classes/GlobalCss.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { withStyles } from '@material-ui/styles';
import spacings from './spacings';
import colors from './colors';
import elevations from './elevations';
import texts from './texts';
import positions from './positions';
import {
displays,
overflows,
textOverflows,
visibilities,
whiteSpaces,
} from './displays';

const GlobalCss = withStyles((theme) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we will need to look at

  1. the time it takes to build the styles
  2. how we can handle server-side rendering, if we trust https://tailwindcss.com/docs/controlling-file-size/, 144.5kb gzipped is no way for inlining critical CSS. In our current experimentation, we are at 4kb gzipped. https://www.nytimes.com/ is 210kB gzipped. Youtube.com is 56kb gzipped. Amazon.com is at 93kb gzipped. So I would say 40kB gzipped isn't too far from our limit.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, for 2. I remember emotion having some sort of critical extraction tool, to only include the required class names. Tailwind has something similar, if it's fast enough to be run at each server-side query, it could move the limitation to 1. only. On the server 1. can be cached.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For 1. I measure 1ms to build the object and 12ms for JSS to process the object before injection in the page. I have no idea how it scales. They might be way to bypass the plugins, speeding things up. We would also need to look at how long it makes with styled-components and emotion.

return {
'@global': {
...spacings(theme),
...colors(theme),
...elevations(theme),
...texts(theme),
...positions(theme),
...displays,
...overflows,
...textOverflows,
...visibilities,
...whiteSpaces,
},
};
})(() => null);

export default GlobalCss;
3 changes: 3 additions & 0 deletions docs/src/pages/system/global-classes/colors.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Theme } from '@material-ui/core/styles';

export default function (theme: Theme): object;
22 changes: 22 additions & 0 deletions docs/src/pages/system/global-classes/colors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const r = (val, accumulator, colors) => {
if (typeof val === 'string') {
colors[accumulator] = { backgroundColor: val };
colors[`${accumulator}--text`] = { color: val };
colors[`${accumulator}--hover`] = { '&:hover': { backgroundColor: val } };
colors[`${accumulator}--text--hover`] = { '&:hover': { color: val } };
} else if (typeof val === 'object' && val !== null) {
Object.keys(val).forEach((key) => {
r(
val[key],
`${accumulator}${accumulator.length > 1 ? '-' : ''}${key}`,
colors,
);
});
}
};

export default function colors(theme) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it would make sense to expose the Material Design colors https://material-ui.com/customization/color/#2014-material-design-color-palettes

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, I just exported only the ones that are in the palette inside the theme, thinking that if users will restrict that set or add new colors the classes would reflect that. On the other hand I don't see why we should not expose these colors too...

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have a doubt, we can wait to see if people ask for it

const colors = {};
r(theme.palette, '.', colors);
return colors;
}
5 changes: 5 additions & 0 deletions docs/src/pages/system/global-classes/displays.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const displays: object;
export const overflows: object;
export const textOverflows: object;
export const visibilities: object;
export const whiteSpaces: object;
101 changes: 101 additions & 0 deletions docs/src/pages/system/global-classes/displays.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
export const displays = {
'.d-inline': { display: 'inline' },
'.d-block': { display: 'block' },
'.d-contents': { display: 'contents' },
'.d-flex': { display: 'flex' },
'.d-grid': { display: 'grid' },
'.d-inline-block': { display: 'inline-block' },
'.d-inline-flex': { display: 'inline-flex' },
'.d-inline-grid': { display: 'inline-grid' },
'.d-inline-table': { display: 'inline-table' },
'.d-list-item': { display: 'list-item' },
'.d-run-in': { display: 'run-in' },
'.d-table': { display: 'table' },
'.d-table-caption': { display: 'table-caption' },
'.d-table-column-group': { display: 'table-column-group' },
'.d-table-header-group': { display: 'table-header-group' },
'.d-table-footer-group': { display: 'table-footer-group' },
'.d-table-row-group': { display: 'table-row-group' },
'.d-table-cell': { display: 'table-cell' },
'.d-table-column': { display: 'table-column' },
'.d-table-row': { display: 'table-row' },
'.d-none': { display: 'none' },
'.d-initial': { display: 'initial' },
'.d-inherit': { display: 'inherit' },
'.d-print-inline': { '@media print': { display: 'inline' } },

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we couldn't handle print as a custom breakpoint, as we would handle sm, or md.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I was thinking about was, whether we should include the breakpoints inside the class names (Vuetify has them), so that.. It could be useful I think

Copy link

@oliviertassinari oliviertassinari Jul 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it seems that being able to change the values based on the media query is a critical feature they all have. I also don't see how I could implement anything without it 😁. And yes, agree, to make it work, it has to be in the class names.

The question I see left is where? Should it be a prefix like Tailwind, or in the middle Like Bootstrap/Vuetify, or should it be at the end? I think that it's mostly about how you want to organize your code. Consider how the sx prop and our current system works, I would be leaning toward as a prefix sm:p-3, print:p-3. Thought?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hum, not sure actually, we document the following for the props API:

display={{ xs: 'none', sm: 'block' }}

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added breakpoints on all classes as prefix

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left print as is for now, mainly because it may be combined with other breakpoints...

'.d-print-block': { '@media print': { display: 'block' } },
'.d-print-contents': { '@media print': { display: 'contents' } },
'.d-print-flex': { '@media print': { display: 'flex' } },
'.d-print-grid': { '@media print': { display: 'grid' } },
'.d-print-inline-block': { '@media print': { display: 'inline-block' } },
'.d-print-inline-flex': { '@media print': { display: 'inline-flex' } },
'.d-print-inline-grid': { '@media print': { display: 'inline-grid' } },
'.d-print-inline-table': { '@media print': { display: 'inline-table' } },
'.d-print-list-item': { '@media print': { display: 'list-item' } },
'.d-print-run-in': { '@media print': { display: 'run-in' } },
'.d-print-table': { '@media print': { display: 'table' } },
'.d-print-table-caption': { '@media print': { display: 'table-caption' } },
'.d-print-table-column-group': {
'@media print': { display: 'table-column-group' },
},
'.d-print-table-header-group': {
'@media print': { display: 'table-header-group' },
},
'.d-print-table-footer-group': {
'@media print': { display: 'table-footer-group' },
},
'.d-print-table-row-group': {
'@media print': { display: 'table-row-group' },
},
'.d-print-table-cell': { '@media print': { display: 'table-cell' } },
'.d-print-table-column': { '@media print': { display: 'table-column' } },
'.d-print-table-row': { '@media print': { display: 'table-row' } },
'.d-print-none': { '@media print': { display: 'none' } },
'.d-print-initial': { '@media print': { display: 'initial' } },
'.d-print-inherit': { '@media print': { display: 'inherit' } },
'.d-sr-only': {
border: 0,
clip: 'rect(0 0 0 0)',
height: 1,
margin: -1,
overflow: 'hidden',
padding: 0,
position: 'absolute',
whiteSpace: 'nowrap',
width: 1,
},
};

export const overflows = {
'.overflow-visible': { overflow: 'visible' },
'.overflow-hidden': { overflow: 'hidden' },
'.overflow-scroll': { overflow: 'scroll' },
'.overflow-auto': { overflow: 'auto' },
'.overflow-initial': { overflow: 'initial' },
'.overflow-inherit': { overflow: 'inherit' },
};

export const textOverflows = {
'.text-overflow-clip': { textOverflow: 'clip' },
'.text-overflow-ellipsis': { textOverflow: 'ellipsis' },
'.text-overflow-initial': { textOverflow: 'initial' },
'.text-overflow-inherit': { textOverflow: 'inherit' },
};

export const visibilities = {
'.v-visible': { visibility: 'visible' },
'.v-hidden': { visibility: 'hidden' },
'.v-collapse': { visibility: 'collapse' },
'.v-initial': { visibility: 'initial' },
'.v-inherit': { visibility: 'inherit' },
};

export const whiteSpaces = {
'.ws-normal': { whiteSpace: 'normal' },
'.ws-nowrap': { whiteSpace: 'nowrap' },
'.ws-pre': { whiteSpace: 'pre' },
'.ws-pre-line': { whiteSpace: 'pre-line' },
'.ws-pre-wrap': { whiteSpace: 'pre-wrap' },
'.ws-initial': { whiteSpace: 'initial' },
'.ws-inherit': { whiteSpace: 'inherit' },
};
3 changes: 3 additions & 0 deletions docs/src/pages/system/global-classes/elevations.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Theme } from '@material-ui/core/styles';

export default function (theme: Theme): object;
9 changes: 9 additions & 0 deletions docs/src/pages/system/global-classes/elevations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default function elevations(theme) {
const elevations = {};

theme.shadows.forEach((shadow, idx) => {
elevations[`.elevation-${idx}`] = { boxShadow: shadow };
});

return elevations;
}
7 changes: 7 additions & 0 deletions docs/src/pages/system/global-classes/global-classes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Global classes

<p class="description">The global classes available allows users to use the system properties consistenlty on all components.</p>

## Basics

{{"demo": "pages/system/global-classes/Basics.js", "defaultCodeOpen": false}}
3 changes: 3 additions & 0 deletions docs/src/pages/system/global-classes/positions.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Theme } from '@material-ui/core/styles';

export default function (theme: Theme): object;
36 changes: 36 additions & 0 deletions docs/src/pages/system/global-classes/positions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const values = Array.from(Array(17).keys()); // 0..16

export default function positions(theme) {
const positions = {
'.position-static': { position: 'static' },
'.position-absolute': { position: 'absolute' },
'.position-fixed': { position: 'fixed' },
'.position-relative': { position: 'relative' },
'.position-sticky': { position: 'sticky' },
'.position-initial': { position: 'initial' },
'.position-inherit': { position: 'inherit' },
};

values.forEach((val) => {
positions[`.top-${val}`] = {
top: theme.spacing(val / 2),
};
positions[`.bottom-${val}`] = {
bottom: theme.spacing(val / 2),
};
positions[`.right-${val}`] = {
right: theme.spacing(val / 2),
};
positions[`.left-${val}`] = {
left: theme.spacing(val / 2),
};
});

Object.keys(theme.zIndex).forEach((key) => {
positions[`.zIndex-${key}`] = {
zIndex: theme.zIndex[key],
};
});

return positions;
}
5 changes: 5 additions & 0 deletions docs/src/pages/system/global-classes/spacings.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { object } from 'prop-types';

import { Theme } from '@material-ui/core/styles';

export default function (theme: Theme): object;
Loading