Skip to content

Commit

Permalink
[Joy] Add Typography component (mui#30489)
Browse files Browse the repository at this point in the history
  • Loading branch information
siriwatknp authored and wladimirguerra committed Feb 2, 2022
1 parent b816ead commit d753b60
Show file tree
Hide file tree
Showing 19 changed files with 559 additions and 37 deletions.
12 changes: 6 additions & 6 deletions docs/pages/experiments/joy/style-guide.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import {
styled,
ColorPaletteProp,
TypographySystem,
createGetThemeVar,
createGetCssVar,
} from '@mui/joy/styles';

const getThemeVar = createGetThemeVar();
const getCssVar = createGetCssVar();

const rgb2hex = (rgb: string) =>
`#${(rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/) || [])
Expand All @@ -26,7 +26,7 @@ const Typography = styled('p', {
({ theme, level = 'body1', color }) => [
{ margin: 0 },
theme.typography[level],
color && color !== 'context' && { color: getThemeVar(`palette-${color}-textColor`) },
color && color !== 'context' && { color: getCssVar(`palette-${color}-textColor`) },
],
);

Expand Down Expand Up @@ -85,12 +85,12 @@ const ColorToken = ({ name, value }: { name: string; value: string }) => {
<Box
ref={ref}
sx={(theme) => ({
borderRadius: `calc(${theme.getThemeVar('radius-md')} / 2)`,
borderRadius: `calc(${theme.getCssVar('radius-md')} / 2)`,
bgcolor: value,
width: 64,
height: 64,
mb: 1,
boxShadow: theme.getThemeVar('shadow-sm'),
boxShadow: theme.getCssVar('shadow-sm'),
})}
/>
<Typography level="body3">{name}</Typography>
Expand Down Expand Up @@ -118,7 +118,7 @@ const PaletteTokens = () => {
<summary
style={{
marginBottom: '0.5rem',
fontFamily: getThemeVar('fontFamily-body'),
fontFamily: getCssVar('fontFamily-body'),
cursor: 'pointer',
}}
>
Expand Down
101 changes: 101 additions & 0 deletions docs/pages/experiments/joy/typography.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import * as React from 'react';
// @ts-ignore
import { jsx as _jsx } from 'react/jsx-runtime';
import { CssVarsProvider, styled, useColorScheme, FontSize } from '@mui/joy/styles';
import Box from '@mui/joy/Box';
import Button from '@mui/joy/Button';
import Typography from '@mui/joy/Typography';

export const SvgIcon = styled('svg', {
shouldForwardProp: (prop) => prop !== 'fontSize' && prop !== 'sx',
})<{
fontSize: keyof FontSize | 'inherit';
}>(({ theme, fontSize }) => ({
userSelect: 'none',
width: '1em',
height: '1em',
display: 'inline-block',
fill: 'currentColor',
flexShrink: 0,
...(fontSize && {
fontSize: fontSize === 'inherit' ? 'inherit' : theme.vars.fontSize[fontSize],
}),
}));

function createSvgIcon(path: any, displayName: any, initialProps?: any) {
const Component = (props: any, ref: any) =>
(
<SvgIcon
data-testid={`${displayName}Icon`}
ref={ref}
viewBox="0 0 24 24"
fontSize="xl"
{...initialProps}
{...props}
sx={{ ...initialProps?.sx, ...props.sx }}
>
{path}
</SvgIcon>
) as unknown as typeof SvgIcon;

// @ts-ignore
return React.memo(React.forwardRef(Component));
}

export const Moon = createSvgIcon(
_jsx('path', {
d: 'M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z',
}),
'DarkMode',
);

export const Sun = createSvgIcon(
_jsx('path', {
d: 'M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zM2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1zm18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1zM11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1zm0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zM5.99 4.58c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41L5.99 4.58zm12.37 12.37c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0 .39-.39.39-1.03 0-1.41l-1.06-1.06zm1.06-10.96c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06zM7.05 18.36c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06z',
}),
'LightMode',
);

const ColorSchemePicker = () => {
const { mode, setMode } = useColorScheme();
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => {
setMounted(true);
}, []);
if (!mounted) {
return null;
}

return (
<Button
variant="outlined"
onClick={() => {
if (mode === 'light') {
setMode('dark');
} else {
setMode('light');
}
}}
sx={{ minWidth: 40, p: '0.25rem' }}
>
{mode === 'light' ? <Moon /> : <Sun />}
</Button>
);
};

export default function JoyTypography() {
return (
<CssVarsProvider>
<Box sx={{ py: 5, maxWidth: { md: 1152, xl: 1536 }, mx: 'auto' }}>
<Box sx={{ px: 3, pb: 4 }}>
<ColorSchemePicker />
</Box>
{(['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'body1', 'body2', 'body3'] as const).map((level) => (
<Typography gutterBottom level={level} key={level}>
{`${level} - typography`}
</Typography>
))}
</Box>
</CssVarsProvider>
);
}
18 changes: 18 additions & 0 deletions packages/mui-joy/src/Typography/Typography.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from 'react';
import Typography from '@mui/joy/Typography';

<Typography component="a" href="/">
Text
</Typography>;

function Link(props: JSX.IntrinsicElements['a']) {
return <a {...props} />;
}
<Typography component={Link} href="/">
Text
</Typography>;

// @ts-expect-error href is not exist in div
<Typography component="div" href="/">
Text
</Typography>;
88 changes: 88 additions & 0 deletions packages/mui-joy/src/Typography/Typography.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import * as React from 'react';
import { expect } from 'chai';
import { createRenderer, describeConformance } from 'test/utils';
import Typography, { typographyClasses as classes } from '@mui/joy/Typography';
import { ThemeProvider } from '@mui/joy/styles';

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

describeConformance(<Typography />, () => ({
classes,
inheritComponent: 'p',
ThemeProvider,
render,
refInstanceof: window.HTMLParagraphElement,
muiName: 'MuiTypography',
testStateOverrides: { prop: 'level', value: 'h2', styleKey: 'h2' },
skip: ['componentsProp', 'classesRoot', 'themeVariants'],
}));

it('should render the text', () => {
const { container } = render(<Typography>Hello</Typography>);
expect(container.firstChild).to.have.text('Hello');
});

it('should render body1 root by default', () => {
const { container } = render(<Typography>Hello</Typography>);

expect(container.firstChild).to.have.class(classes.body1);
expect(container.firstChild).to.have.class(classes.root);
});

['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'body1', 'body2', 'body3'].forEach((level) => {
it(`should render ${level} text`, () => {
const { container } = render(<Typography level={level}>Hello</Typography>);

expect(classes).to.have.property(level);

expect(container.firstChild).to.have.class(classes[level]);
});
});

describe('headline', () => {
it('should render the mapped headline', () => {
const { getByText } = render(<Typography level="h6">Hello</Typography>);

expect(getByText(/hello/i).tagName).to.equal('H6');
});

it('should render a h1', () => {
const { getByText } = render(<Typography component="h1">Hello</Typography>);

expect(getByText(/hello/i).tagName).to.equal('H1');
});
});

describe('prop: levelMapping', () => {
it('should work with a single value', () => {
const { getByText } = render(
<Typography level="h6" levelMapping={{ h6: 'aside' }}>
Hello
</Typography>,
);

expect(getByText(/hello/i).tagName).to.equal('ASIDE');
});

it('should work even with an empty mapping', () => {
const { getByText } = render(
<Typography level="h6" levelMapping={{}}>
Hello
</Typography>,
);

expect(getByText(/hello/i).tagName).to.equal('H6');
});
});

it('combines system properties with the sx prop', () => {
const { container } = render(<Typography mt={2} mr={1} sx={{ marginRight: 5, mb: 2 }} />);

expect(container.firstChild).toHaveComputedStyle({
marginTop: '16px',
marginRight: '40px',
marginBottom: '16px',
});
});
});
Loading

0 comments on commit d753b60

Please sign in to comment.