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

[theme] Allow custom typography variants #22257

Closed
andyfangaf opened this issue Aug 17, 2020 · 23 comments · Fixed by #24088
Closed

[theme] Allow custom typography variants #22257

andyfangaf opened this issue Aug 17, 2020 · 23 comments · Fixed by #24088
Labels
docs Improvements or additions to the documentation new feature New feature or request priority: important This change can make a difference
Milestone

Comments

@andyfangaf
Copy link

andyfangaf commented Aug 17, 2020

MUI allows you to add custom keys to the theme configuration. However, there is no way to expand the design system unless you create a whole new component. Allowing MUI components to reference custom theme keys would bring customization to a whole nother level.

createMuiTheme({
  typography: {
    poster: {
     fontSize: '5.8rem'
    },
  },
});

Usage:

<Typography variant="poster">Super big headline</Typography>
@andyfangaf andyfangaf added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Aug 17, 2020
@andyfangaf andyfangaf changed the title Custom variants for typography Allow components like Typography to reference custom theme keys Aug 17, 2020
@mbrookes
Copy link
Member

mbrookes commented Aug 17, 2020

Resolved in #21648 / #22006

@mbrookes mbrookes removed the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Aug 17, 2020
@andyfangaf
Copy link
Author

Ah I was on an older version. Will check this out. Sorry for the dup!

@oliviertassinari oliviertassinari added the new feature New feature or request label Aug 18, 2020
@oliviertassinari
Copy link
Member

oliviertassinari commented Aug 18, 2020

#22006 doesn't directly address the problem of @Fandy. With #22006, what people can do is in v5.0.0-alpha.8:

const theme = createMuiTheme({
  typography: {
     poster: {
       fontSize: '5.8rem'
    },
  },
  variants: {
    MuiTypography: [
      {
        props: { variant: 'poster' },
        styles: theme.typography.poster,
      },
    ],
  },
});

declare module '@material-ui/core/Typography/Typography' {
  interface TypographyPropsVariantOverrides {
    poster: true;
  }
}

<Typography variant="poster" />

But it's not what asked for:

const theme = createMuiTheme({
  typography: {
     poster: {
       color: 'red',
    },
  },
});

declare module '@material-ui/core/Typography/Typography' {
  interface TypographyPropsVariantOverrides {
    poster: true;
  }
}

<Typography variant="poster" />

It's a lot like #13875 where we talk about being able to tap into the theme directly without indirections. It should land before v5 beta.

cc @mnajdova

@mnajdova
Copy link
Member

I agree, in my opinion this is related to dynamic styles, which is a different problem

@oliviertassinari oliviertassinari changed the title Allow components like Typography to reference custom theme keys [theme] Allow custom typography variant Aug 18, 2020
@oliviertassinari
Copy link
Member

Ok I'm reopening to match #13875

@oliviertassinari oliviertassinari changed the title [theme] Allow custom typography variant [theme] Allow custom typography variants Aug 18, 2020
@oliviertassinari oliviertassinari added the priority: important This change can make a difference label Aug 18, 2020
@oliviertassinari
Copy link
Member

oliviertassinari commented Dec 18, 2020

We have fixed the underlying technical issue in #23841. Now, developers can do 🎉:

import * as React from "react";
import { createMuiTheme, ThemeProvider } from "@material-ui/core/styles";
import Typography from "@material-ui/core/Typography";

const theme = createMuiTheme({
  typography: {
    poster: {
      color: "red"
    },
    h3: null
  }
});

declare module "@material-ui/core/styles/createTypography" {
  interface Typography {
    poster: React.CSSProperties;
  }

  // allow configuration using `createMuiTheme`
  interface TypographyOptions {
    poster?: React.CSSProperties;
  }
}

declare module "@material-ui/core/Typography/Typography" {
  interface TypographyPropsVariantOverrides {
    poster: true;
    h3: false;
  }
}

export default function FontSizeTheme() {
  return (
    <ThemeProvider theme={theme}>
      {/* A new variant */}
      <Typography variant="poster">poster</Typography>
      {/* You can also disable variants */}
      <Typography variant="h3">h3</Typography>
    </ThemeProvider>
  );
}

https://codesandbox.io/s/fontsizetheme-material-demo-forked-l9u05?file=/demo.tsx

Capture d’écran 2020-12-18 à 13 00 25

I believe the last step is to properly document it. Maybe inside https://next.material-ui.com/customization/typography/? @mnajdova

@oliviertassinari oliviertassinari added this to the v5 milestone Dec 18, 2020
@mbrookes
Copy link
Member

We have fixed the underlying technical issue

Does this also allow removing typography variants by removing keys? (It came up in some related feedback.)

@oliviertassinari
Copy link
Member

oliviertassinari commented Dec 19, 2020

Does this also allow removing typography variants by removing keys?

@mbrookes Yes, also a good one to document.

@oliviertassinari oliviertassinari added the docs Improvements or additions to the documentation label Dec 19, 2020
@kishorekumaru
Copy link

any chance of getting this in current version?

@mnajdova
Copy link
Member

@kishorekumaru it is already available. Take a look on https://next.material-ui.com/customization/typography/#adding-amp-disabling-variants

@kishorekumaru
Copy link

kishorekumaru commented Jan 12, 2021

@mnajdova I follow the same tutorial on the current version v4.11.2 but typescript throwing typescript error on variant and not taking my typography changes, here is my code in sandbox please let me know if I am doing something wrong
https://codesandbox.io/s/infallible-rhodes-jg6gf?file=/src/App.tsx

@oliviertassinari
Copy link
Member

oliviertassinari commented Jan 12, 2021

@kishorekumaru This is a v5 only feature. See the policy for v4

⚠️ All ongoing work has moved to v5. The development of v4 is limited to important bug fixes, security patches and easing the upgrade path to v5.

@Lane
Copy link

Lane commented Feb 9, 2021

if someone wants to do this in V4, you can wrap the Material UI component with some of your own variants:

import { Typography as MuiTypography, withStyles } from "@material-ui/core";
import clsx from "clsx";

const style = (theme) => ({
  number: {
    fontSize: theme.typography.pxToRem(20),
    fontWeight: 700,
  },
  label: {
    fontSize: theme.typography.pxToRem(11.5),
    letterSpacing: "0.05em",
    fontStyle: "italic",
  },
});

/**
 * Overrides default material UI typography with some additional variants
 */
const Typography = ({ variant, classes, className, ...props }) => {
  const isCustom = Object.keys(classes).indexOf(variant) > -1;
  return (
    <MuiTypography
      className={isCustom ? clsx(classes[variant], className) : className}
      variant={isCustom ? undefined : variant}
      {...props}
    />
  );
};

export default withStyles(style)(Typography);

then using the typography component above, you can use your own variants:

<Typography variant="number">42</Typography>

not as nice as being able to define in the theme, but it works 🤷

@elchris953
Copy link

elchris953 commented Feb 20, 2021

A more clean approach to custom variants to be prepared for v5, from my perspective, would be:

import { createMuiTheme, makeStyles, ThemeProvider } from "@material-ui/core/styles"

let theme = createMuiTheme({
  typography: {
    display1: {
      fontSize: '64px'
    }
  }
})

let styles = makeStyles( theme => ({
  display1: theme.typography.display1
}))

const Component = () => {
  const classes = styles()

  return (
    <ThemeProvider theme={theme}>
      <span className={classes.display1}>Hello</span>
    </ThemeProvider>
  )
}

export default Component

@felipepastor
Copy link

@Lane Do you know how we could add Types for your proposal?

@oliviertassinari
Copy link
Member

oliviertassinari commented Aug 13, 2021

Do you know how we could add Types for your proposal?

@felipepastor Interesting point. I think that we could update https://next.material-ui.com/guides/composition/#wrapping-components to describe how to extend the props of the components, including TypeScript. We have a couple of frequently upvoted issues related to it.

For instance, @eps1lon has been advocating for using more this wrap pattern. There are definitely cases where you don't want to update the theme to add a variant to your how application, but instead, create a specialized component.

@teenguyen
Copy link

      variant={isCustom ? undefined : variant}

Just FYI if anybody is implementing something similar: body1 was being applied to all custom types (since leaving it undefined defaults to body1) and in some places taking precedence. I've switched it out to variant={isCustom ? "inherit" : variant} until we get the chance to upgrade to v5

@Plasmadog
Copy link

Plasmadog commented Sep 8, 2021

I've just tried adding a custom variant (in v5 beta 4), but the new variant does not inherit any of the defaults defined at the root of the typography part of the theme. Is this intentional?
For example:

typography: {
  fontFamily: '"Roboto", sans-serif',
  h7: {
    fontSize: '30px',
   }
}

All other variants use Roboto, but when using the "h7" variant I get Times New Roman. Is it a bug, or by design?

@borm
Copy link

borm commented Sep 21, 2021

@oliviertassinari , how do correct autocompletion for new variants?

declare module '@mui/material/styles/createTypography' {
  interface Typography {
    title: TypographyStyle;
    subtitle: TypographyStyle;
    paragraph: TypographyStyle;
  }

  // allow configuration using `createMuiTheme`
  interface TypographyOptions {
    title?: TypographyStyleOptions;
    subtitle?: TypographyStyleOptions;
    paragraph?: TypographyStyleOptions;
  }
}

declare module '@mui/material/Typography/Typography' {
  interface TypographyPropsVariantOverrides {
    title: true;
    subtitle: true;
    paragraph: true;
    h3: false;
    h4: false;
    h5: false;
    h6: false;
  }
}

image
image

like align prop, by string(variant="title"), not variant={'title'}

image

@borm
Copy link

borm commented Sep 21, 2021

@oliviertassinari , and also withStyles doest show properties for autocomplete, there is nothing types when mouse hover to variant

update, oh, its too bad, no jss support anymore ;(

import { withStyles } from '@mui/styles';
import MuiTypography from '@mui/material/Typography';

export const Typography = withStyles(
  () => ({
    root: {
      fontWeight: ({ fontWeight }) => fontWeight,
    },
    title: {
      fontSize: 32,
      fontWeight: 600,
      lineHeight: '48px',
    },
  }),
  {
    name: 'Typography',
  }
)(MuiTypography);

image

@jkananen
Copy link

Can a custom Typography variant be defined a certain element type by default?

The example above <Typography variant="poster">poster</Typography> yields in <span>poster</span>. What if I wanted it to be <p>poster</p>?

Yes this works <Typography variant="poster" component="p">poster</Typography> but passing the component prop every time feels unnecessary.

@jkananen
Copy link

Can a custom Typography variant be defined a certain element type by default?

I'm blind and completely missed variantMapping in the docs.

@jalalmanafi
Copy link

Is it possible to use custom variant and all default variants in same time, cause i don't want to disable any default variants, how can i do this ?
Screenshot 2022-12-27 at 19 04 05

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Improvements or additions to the documentation new feature New feature or request priority: important This change can make a difference
Projects
None yet
Development

Successfully merging a pull request may close this issue.