Material-UI styles and html / markdown
Asked Answered
U

3

13

Our application is build using Material-UI library (with themes). As part of this app we are parsing markdown to html (marked library).

How can you apply material-ui themes ( Typography ) to a pure html ?

Somehow

<div dangerouslySetInnerHTML={ {__html: marked(markdown code)}}/>

Should have the styles as defined by material-ui Typography

Ure answered 3/2, 2021 at 13:17 Comment(4)
Is there any reason you chose marked over a react specific library that has easier support for this?Rotz
@JacobSmit , no reason. But I don't want a library that adds a lot of react nodes as content is 'static'.Ure
Fair enough. As a piece of interest then, one of the co-founders of Material UI answered a question about markdown and typography before and linked to an example of how they are (or at least were) handling the markdown for the documentation website. github.com/mui-org/material-ui/issues/…Rotz
@JacobSmit , that helps . thanks. Looks as it's a 'manual' workUre
E
16

The styles for all the Typography variants are in the theme at theme.typography.<variant> (you can browse those entries in the default theme here: https://material-ui.com/customization/default-theme/#default-theme). You can leverage this to create styles to target the tags you want to support as shown in the example below:

import React from "react";
import { makeStyles } from "@material-ui/core";
import Typography from "@material-ui/core/Typography";

const useStyles = makeStyles((theme) => {
  const tags = ["h1", "h2", "h3", "h4", "h5", "h6"];
  const nestedRules = {};
  tags.forEach((tag) => {
    nestedRules[`& ${tag}`] = { ...theme.typography[tag] };
  });
  return {
    root: nestedRules
  };
});

export default function App() {
  const classes = useStyles();
  return (
    <Typography
      className={classes.root}
      variant="body1"
      dangerouslySetInnerHTML={{
        __html:
          "<h1>H1</h1><h2>H2</h2><h3>H3</h3><h4>H4</h4><h5>H5</h5><h6>H6</h6><p>default body1</p>"
      }}
    ></Typography>
  );
}

Edit style html tags

Related answer: material-ui makeStyles: how to style by tag name?

Epineurium answered 13/2, 2021 at 16:44 Comment(0)
P
6

use regular Typography component and pass that HTML in a similar way as it is passed in the question.

<Typography
    variant="h2"
    color="primary"
    dangerouslySetInnerHTML={{ __html: "<p>Hi from inner HTML</p>" }}>
    
</Typography>

One catch is here that when dangerouslySetInnerHTML is passed then don't pass anything as children.

Here is a working demo :

Edit nervous-cookies-nedrz

Note: Also make sure that the function marked(markdown code) returns the HTML in string.

Patton answered 3/2, 2021 at 14:4 Comment(4)
This might works with a single tag, but doesn't work with multiple ones (h1,h2.. ) -> codesandbox.io/s/dazzling-wildflower-p6dvq .. check how the styles are generated.Ure
I guess it is working as the color and font family of h2 variant is getting applied. Of what part you think this is not working?Patton
is it bcoz of fontSize?Patton
You expect the html inside h1 to use variant h1, the html inside h3 to use variante h3.. it's not the case.Ure
Y
2

Use the markdown-to-jsx npm package. here is the example from the material ui templates.

You basically have to create a config object that ReactMarkdown likes, that is specific for material ui

import React from 'react';
import ReactMarkdown from 'markdown-to-jsx';
import { withStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import Link from '@material-ui/core/Link';

const styles = (theme) => ({
  listItem: {
    marginTop: theme.spacing(1),
  },
});

const options = {
  overrides: {
    h1: {
      component: Typography,
      props: {
        gutterBottom: true,
        variant: 'h5',
      },
    },
    h2: { component: Typography, props: { gutterBottom: true, variant: 'h6' } },
    h3: { component: Typography, props: { gutterBottom: true, variant: 'subtitle1' } },
    h4: {
      component: Typography,
      props: { gutterBottom: true, variant: 'caption', paragraph: true },
    },
    p: { component: Typography, props: { paragraph: true } },
    a: { component: Link },
    li: {
      component: withStyles(styles)(({ classes, ...props }) => (
        <li className={classes.listItem}>
          <Typography component="span" {...props} />
        </li>
      )),
    },
  },
};

export default function Markdown(props) {
  return <ReactMarkdown options={options} {...props} />;
}

I got that straight from their example.

Yaker answered 18/2, 2021 at 21:58 Comment(2)
Bundling a whole MD parser just to style a couple of tags...Proconsul
@IvanKleshnin it's 5.7kb gzipped.Cruiserweight

© 2022 - 2024 — McMap. All rights reserved.