forked from mui/material-ui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Joy] Add
Typography
component (mui#30489)
- Loading branch information
1 parent
b816ead
commit d753b60
Showing
19 changed files
with
559 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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', | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.