KyleAMathews / typography.js

A powerful toolkit for building websites with beautiful design
http://kyleamathews.github.io/typography.js/
MIT License
3.83k stars 181 forks source link

react-typography and create-react-app #177

Open mvasin opened 6 years ago

mvasin commented 6 years ago

I'm trying to use react-typography in a create-react-app based application.

In CRA there is no such thing as index.js that readme mentions, and I don't understand how to add <TypographyStyle> and <GoogleFont> to the <head> of index.html.

I tried

function App() {
  return (
    <React.Fragment>
      <Helmet>
        <TypographyStyle typography={typography} />
        <GoogleFont typography={typography} />
      </Helmet>
      ... my app here ...
    </React.Fragment>

but it didn't work and produced You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information. in the console.

Without <Helmet> it works, but <link> and <style> happen to be in the <body> (that's expected, and not good).

CRA is probably the most common way to bootstrap react apps, so this issue should be addressed in the readme.

mvasin commented 6 years ago

Injecting <TypographyStyle> does work by means of typography.injectStyles(), as mentioned in the readme. Similar inject method is missing for google fonts, and I resorted to copying <link> from google fonts website to public/index.html. It's not elegant, because I have to keep in sync google fonts I declare in new Typography({...}) with fonts I load in <link>.

I guess injectStyles method could be modified to receive an options object with googleFonts property of true or false: typography.injectStyles({googleFonts: true}). If it's true, google font's <link> would be injected in <head> along with <style> tag of typography.js.

dradetsky commented 5 years ago

@mvasin i imagine you've come up with something better by now, BUT: I came across this googling for answers. I couldn't find anything better, so I hacked together the following solution:

https://github.com/dradetsky/typography-inject-fonts

Basically, you add another line injectFonts(typography). It at least initially appears to work (famous last words).

I'll sort out npm publication later; gotta get to a job interview soon. In the meantime, I suppose you could tell me any obvious mistakes I've made (you may find /bin/cat helpful here).

dradetsky commented 5 years ago

@KyleAMathews pinging you in case you want to mark this as solved, or even (ha ha) mention it in the readme.

KyleAMathews commented 5 years ago

@dradetsky this is great! Could you PR it to the README once you've got the NPM publication completed?

dradetsky commented 5 years ago

@KyleAMathews yeah, i just added it. I'll write something up & PR it soon.

FWIW, a much better solution would be if you (or somebody else who knows how to do this sort of thing properly) made a create-react-app template which has an index.js/html.js root instead of being injected into a root element of the base index.html. That would (I think) make OP's solution work. Then you could just say "Create React App: Use the X template, it'll make things easier. If you can't, here's an ugly hack that may help:"

dradetsky commented 5 years ago

BTW, I originally started to use typescript.js typography.js just to find an easy way to make my app look halfway decent, which isn't even a major requirement to begin with (it's basically a clone of Dash.app that runs in the browser). The easiest way to do that was to use one of your default typeography themes, but then I had to get the google fonts to work, and this was the easiest way to make that happen.

But it turns out there was an even easier way: just use typefaces-open-sans. Now the hack is no longer necessary. This method also provides self-hosting, which is even better for my app. Not only is erroring on caltrain undesirable, super-high responsiveness is a major requirement. It's one of the reasons I consider reading the docs off the filesystem instead of off the internet basically essential.

So basically, I've abandoned the solution myself (not that it doesn't appear to work). I'm also thinking I should add something like "But you could also just use Open Sans" to my readme PR. Maybe that will seem like a pretty extreme response to a typical font-obsessed frontend designer, but it's exactly what I would have wanted to see.

nathonius commented 4 years ago

Not trying to resurrect this, but I got this working with react-helmet like this (in Typescript):

import React from 'react';
import { Helmet, HelmetProps } from 'react-helmet';
import typography from '../../util/typography'; // my exported theme

export const Head: React.FC<HelmetProps> = props => {
  const { children, ...rest } = props;
  // Create family + styles string
  let fontsStr = '';
  if (typography.options.googleFonts) {
    const fonts = typography.options.googleFonts.map(font => {
      let str = '';
      str += font.name.split(' ').join('+');
      str += ':';
      str += font.styles.join(',');

      return str;
    });

    fontsStr = fonts.join('|');
  }

  return (
    <Helmet {...rest}>
      {fontsStr !== '' && (
        <link
          href={`//fonts.googleapis.com/css?family=${fontsStr}`}
          rel="stylesheet"
          type="text/css"
        />
      )}
      <style>{`${typography.createStyles()}`}</style>
      {children}
    </Helmet>
  );
};

Then, I can just use <Head> instead of <Helmet>:

import React from 'react';
import { Head } from '../MetaComponents/Head';

export const HomePage: React.FC = props => {
  return (
    <div>
      <Head>
        <title>Nathan Smith</title>
      </Head>
      <h1>Hello World</h1>
    </div>
  );
};

The secret sauce is (for some reason) putting in the styles as a template rather than using children or dangerouslySetInnerHTML.

manavm1990 commented 3 years ago
import { GoogleFont } from "react-typography";
<GoogleFont typography={typography} />

This will work by just artificially dumping the <link for 'Google fonts.'

From here, you can clean it up by just cutting this link and then placing it in the 'public/index.html' so it's in <head> like supposed to be.

From there, just remove the 'react-typography' and <GoogleFont> and all still works.

Of course, if you change themes, you have to do this again.