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

Using custom fonts #542

Closed
archived-m opened this issue Apr 25, 2019 · 15 comments
Closed

Using custom fonts #542

archived-m opened this issue Apr 25, 2019 · 15 comments

Comments

@archived-m
Copy link
Contributor

Last month in #460, someone said Evergreen doesn't set fonts by default. But from what I understand, there's a default theme that sets base fonts: https://github.com/segmentio/evergreen/blob/master/src/theme/src/default-theme/typography/fontFamilies.js

I'm having trouble overwriting them. I set a font-family for body, and it won't overwrite the themed styles, even when including !important. How do I use a custom font-family across all of the components supplied by Evergreen?

@jmfury
Copy link
Contributor

jmfury commented Apr 26, 2019

Have you tried composing the components with the fontFamily prop? Does that work?

I have done fontFamily="inherit" in situations where I have needed to define fonts outside.

Has worked for me, for what it's worth, but might not be the recommended solution either.

@archived-m
Copy link
Contributor Author

Seems strange to pass a prop every single time I use one of Evergreen's components. I could create a wrapper for each, but that seems to defeat the purpose of using a component library in the first place.

I understand Evergreen does not support theming, but overriding a font in CSS seems like something a lot of people would need.

I'll take this as an opportunity to create wrappers around all of the components I import for Evergreen, if only so I can easily switch them out in the future.

I'd really like to hear about additional ways to override the fonts though :)

@mshwery
Copy link
Contributor

mshwery commented May 3, 2019

Theming actually is supported, despite not being documented.

You can import { ThemeProvider } from 'evergreen-ui' and then pass it your own theme.

What you'll probably want to do is use defaultTheme (also exported publicly from evergreen-ui) as your base theme because many theme properties are required for evergreen to work. You can override the theme by merging your own values over existing ones.

Something like this:

import { defaultTheme } from 'evergreen-ui'
import { merge } from 'lodash'

const myCustomTheme = merge({}, defaultTheme, {
  typography: {
    fontFamilies: {
      display: '-apple-system, ...whatever other fonts',
      ui: '-apple-system, sans-serif',
      mono: '"SF Mono", monospace'
    }
  }
})

export default myCustomTheme

If you are familiar with React's context feature, that's what Evergreen uses under the hood. Wrap your app with <ThemeProvider value={myCustomTheme} /> to apply your custom themes.

@archived-m
Copy link
Contributor Author

archived-m commented May 3, 2019

Aha, nice! I got confused because the FAQ on v4-create-theme-branch still says it is not supported.
Great solution.

Am I supposed to do anything else than supply the theme to the ThemeProvider? I overrode the fontFamilies and passed them as you suggested, but the components are still using the default font stack. I verified they were set correctly by logging the theme prop in ThemeConsumer, it does log the updated theme object, but doesn't apply it.

@mshwery
Copy link
Contributor

mshwery commented May 3, 2019

Oof. Hate to say it but your best bet might be to mutate defaultTheme directly. I am looking into this and it seems that the theme context is only half-baked in v4. I'm guessing that some of the theme getter functions are reaching directly into internal objects instead of always looking at the theme context object.

@archived-m
Copy link
Contributor Author

I tried mutating, but that didn't work either. Also tried a combination of both :p.
Tried moving it up the component hierarchy and composing with withTheme. To no avail

Any more ideas?

I would create a wrapper and pass the fontFamily prop to everything as JMFURY suggested, but some components don't accept it (such as Dialog).

@mshwery
Copy link
Contributor

mshwery commented May 4, 2019

Mutating worked for me. Here's a codesandbox.

@mshwery
Copy link
Contributor

mshwery commented May 4, 2019

If all else fail you can take the wrapper approach.

We should dive into the problem to see why we can't always use ThemeProvider. I think we are actually really close to having it all wired up, there are just a few spots importing theme variables directly from the defaultTheme instead of from the context.

@archived-m
Copy link
Contributor Author

Ah yes, it works when I use lodash so I must not be mutating it properly without it.

Thanks for all the help!

@gonzarascon
Copy link

What properties can you have in a custom theme (Such as typography)? I'm looking for those and can't find them.

@mshwery
Copy link
Contributor

mshwery commented Jun 15, 2019

Custom themes aren't officially supported (and that's why there are no docs for it) but you can try using the defaultTheme to inform how you put together a custom theme. This is something we're considering improving in v5/6.

The easiest way is to override individual components using ui-box properties (most evergreen components support all or almost all of the props that ui-box provides.
https://github.com/segmentio/ui-box/#css-properties

@Sowed
Copy link

Sowed commented Jul 29, 2020

Theming actually is supported, despite not being documented.

You can import { ThemeProvider } from 'evergreen-ui' and then pass it your own theme.

@mshwery, I am using "evergreen-ui": "^4.28.1",, and it's amazing. Except at overriding fonts. Working with TypeScript and tried your suggested approach above but it looks like ThemeProvider is missing type definitions. Could not find any mention of theme provider except in a comment-line1816

  /**
   * Theme provided by ThemeProvider.
   */
  theme?: Theme

Overrding the ui-box props is so cumbersome. So my current work around is to inspect the component in DevTools, get the target css class names and override those in my in my styled-component definition.

const LayoutWrapper = styled.div`
  & .📦fnt-fam_b77syt,
  & .📦fnt-fam_wm9v6k {
    font-family: var(--font-body) !important;
  }
`;

It works for now but it feels a bit hacky and bound to break on builds and updates. Whats the fix for TS imports of the ThemeProvider? I am missing something?

@mshwery
Copy link
Contributor

mshwery commented Jul 29, 2020

@Sowed v5 includes the types for ThemeProvider and ThemeConsumer, as well as the useTheme hook!

While not ideal, you could bypass this sort of typedef concern by @ts-ignoreing the import until you are able to upgrade to the version that includes the typedefs. Alternatively you could extend the types in your project locally.

@Sowed
Copy link

Sowed commented Aug 13, 2020

@mshwery, I can confirm, as per your sandbox, mutating with lodash.merge works. Like @MichielLeyman , I found a hard time trying to make it work without mutating the defaultTheme but it looks like its the only way for now.

With that mutation, it makes me wonder why we still need the ThemeProvider anyway because it still works without it.

@mshwery
Copy link
Contributor

mshwery commented Aug 13, 2020

@Sowed yeah – unfortunately until we fix the theme and provide first-class support for theming the ThemeProvider only is useful for the few scenarios that don't require mutating defaultTheme.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants