This is how I am loading my Font files in reactjs
import styled from 'styled-components';
import fontUrls from './UberMove-Bold.ttf';
import fontUrls1 from './UberMove-Light.ttf';
import fontUrls2 from './UberMove-Medium.ttf';
import fontUrls3 from './UberMove-Regular.ttf';
const Fonts = styled`
#font-face {
font-familty: 'UberMove-Light';
src: url(${fontUrls1}) format('truetype');
}`;
This throws an error while importing
Uncaught Error: Cannot create styled-component for component: #font-f .ace{font-familty:'UberMove-Light';src:url(,) format('truetype');}.
You need to load the font-face globally and then use it in the components:
import { createGlobalStyle } from "styled-components";
const GlobalStyles = createGlobalStyle`
body {
#import url(${fontUrls1});
font-family: 'UberMove-Light';
}
`
const App = () => (
<div>
<GlobalStyles />
//...
</div>
)
Related
I'm trying to learn Gatsby and I'm stuck on using styles from SCSS after I import it on the Homepage.
Here is my Homepage (index.js) that is loading and using SCSS with React JSX.
import * as React from "react"
import styles from '../styles/home.module.scss'
const IndexPage = () => {
return (
<main className={styles.container}>
<h1 className={styles.title}>Helloworld</h1>
</main>
)
}
export default IndexPage
Those are the styles I'm currently trying to import.
.container{
background: purple;
}
.title{
font-size: 5em;
color: white;
}
I'm using SCSS that came automatically installed from Gatbsy, and here is the Config file of Gatsby.
module.exports = {
siteMetadata: {
siteUrl: "https://www.yourdomain.tld",
title: "gatsby-learning",
},
plugins: ["gatsby-plugin-sass"],
};
So this is the weird error I get when the App runs.
In Gatsby v3 you need to import the styles as ES modules, like this:
import * as styles from '../styles/home.module.scss'
Then, you'll be able to use your CSS modules at, for example:
<main className={styles.container}>
Keep in mind that this is not the recommended way of importing CSS modules because you are not allowing webpack to treeshake your styles. Ideally, you should import each named module like:
import { container } from '../styles/home.module.scss'
And applied as:
<main className={container}>
we are currently loading Fonts and few other global styles like this:
import { createGlobalStyle } from 'styled-components';
export default createGlobalStyle`
#font-face {
font-family: 'Name';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/name/v12/iJWZBXyIfDnIV5PNhY1KTN7Z-Yh-B4iFU0U1Z4Y.woff2) format('woff2');
}
// more fonts..
}
And in every _app.tsx (from every project in repo) we just
import GlobalStyle from #our-company/ui;
// few other imports
const AppProviders = ({ children, messages, locale }: Props): JSX.Element => {
return (
<IntlProvider
locale={locale || 'en-GB'}
key={locale}
messages={messages[locale]}
defaultLocale="en-GB"
>
<GlobalStyle />
<DsThemeProvider
locale={locale}
>
{children}
</DsThemeProvider>
</IntlProvider>
);
};
But we noticed unnecessary font reloads caused by this GlobalStyle when clicking, for example, in checkbox elements (tried putting this in a .css and just load it and never happens again).
Any idea how could export this styles as GlobalStyle name without using styled-components so we don't have to change all import from all apps in the project?
why you dont create main.css and import it on your index.css or app.css , its download and cache on users browser so you don't need to use global styled component anymore
It seems like you're looking for something like injectGlobal:
import { injectGlobal } from 'styled-components';
injectGlobal`
/* your #font-face stuff here */
`
This seems like it would be a good fit for your situation, as it would be relatively easy to transition from the existing structure using createGlobalStyle to one that uses this.
In your case, the code would look like:
import { injectGlobal } from 'styled-components';
injectGlobal`
#font-face {
font-family: 'Name';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/name/v12/iJWZBXyIfDnIV5PNhY1KTN7Z-Yh-B4iFU0U1Z4Y.woff2) format('woff2');
}
// more fonts..
}
If you wish to use a solution that is backwards-compatible with any code that is rendering <GlobalStyle />, you can include a null component as the default export as a stop-gap solution, alongside your injectGlobal code:
export default () => null;
Would this solve your problem?
You can also bind the style directly inside the JS file
var stylingObject = {
div: {
color: "red",
border: "1px solid red"
}, input: {
margin: "2px",
padding: "5px"
}
}
function App() {
return (
<div style={stylingObject.div}>
<input style={stylingObject.input} type="text" />
</div>
);
}
Originally I had hoped to import some CSS file with the fonts defined there and then just importing it so it would affect the entire page, obviously because the way react works such a thing isn't possible cause it would take place only in the imported component not in the one that did the import.
the reason createGlobalStyle from styled-components renders each time is also due to react's workings - when we set the style for a "component like" (or actual component) object, like every react component its not static and renders only when needed. Even if we make it render by force on page load its not the same one (cause on each page we render it separately) so keeping up with the current config doesn't seem to be possible by react's standard.
If we want to make the styles static or "more" static we would have to :
either import them in each page separately - making us do a major refactor
or use either createGlobalStyle (allowing us to use our already created styled-components component) or importing a main css file in the main application component like in the example below:
globalStyles.js
import { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle`
body {
margin: 0;
padding: 0;
background: teal;
font-family: Open-Sans, Helvetica, Sans-Serif;
}
`;
export default GlobalStyle;
App.js
import React, { Fragment } from 'react';
import GlobalStyle from './theme/globalStyle';
import Content from './components/Content';
function App() {
return (
<Fragment>
<GlobalStyle />
<Content />
</Fragment>
);
}
export default App;
If you have a rather large global stylesheet like we did while migrating, you can use styled-components css method to leverage styled-components (css) IDE syntax highlighting & linting you can also do the following:
import React from 'react'
import { createGlobalStyle, css } from 'styled-components'
const Reset = css`
* {
box-sizing: border-box;
}
`
const Accessibility = css`
.hidden {
display: none !important;
visibility: hidden;
}
`
const BaseStyles = createGlobalStyle`
${Reset};
${Accessibility};
`
export const GlobalStyles = () => (
<>
<BaseStyles />
</>
)
Import GlobalStyles and render as sibling to {children}
this is my css file Header.css
.header{
background-color: lightblue;
text-align: center;
}
My Header.js file
import React from 'react'
import './Header.css'
const Header = () => {
return (
<div className = "header">
<p> hope u enjoyed it here</p>
</div>
);
}
export default Header;
these are The imports in the App.js file
import Recipe from './Recipe';
import Header from './layout/Header';
import Footer from './layout/Footer';
import Nav from './layout/Nav';
I've tried making a Nav Component but for some reason thats not rendering either.
I am using material-UI in my react web app.
I want to test my component with jest in way that styles would be saved in snapshot of component like what jest-styled-component do for styled-component but I cant.
you can see my sample project in codesandbox
but here are the important parts:
I create my project with create-react-app with this command:
npx create-react-app myapp
this is my index.js file:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import {MuiThemeProvider} from '#material-ui/core/styles';
import theme from './customTheme';
ReactDOM.render(
<MuiThemeProvider theme={theme}>
<App/>
</MuiThemeProvider>,
document.getElementById('root')
);
this is my customTheme.js file in src folder:
import {createMuiTheme} from '#material-ui/core/styles';
const theme = createMuiTheme({
typography: {
fontFamily: [
'Roboto',
'"Segoe UI"',
'"Helvetica Neue"',
'Arial',
'sans-serif',
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"',
].join(','),
},
palette: {
color: 'blue',
}
});
export default theme;
and this is my App.js that I want to test:
import React from 'react';
import PropTypes from 'prop-types';
import {withStyles} from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
export const styles = theme => ({
mystyle: {
fontFamily: theme.typography.fontFamily,
border: '1px solid green',
background: 'yellow',
color: theme.palette.color,
},
});
function MyComponent(props) {
const {classes} = props;
return (
<div>
<p className={classes.mystyle}> my text </p>
<Button className={classes.mystyle}>my button</Button>
</div>
);
}
MyComponent.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(MyComponent);
please notice that I am overwriting styles with JSS and I have my own theme.
I want to get snapshot from component in way that css be part of snapshot like this issue from material-UI's repository in github or like what jest-styled-component-do for styled-component. for reaching that goal I wrote this code in my demo.test.js:
import React from "react";
import renderer from "react-test-renderer";
import App from '../App';
import {styles} from '../App';
describe("snapshot test", () => {
it("should match snapshot", () => {
const wrapper = renderer
.create(<App classes={styles}/>)
.toJSON();
expect(wrapper).toMatchSnapshot();
});
});
but with this test my styles are not in snapshot therefore if I change mystyle in App component the snapshot test will not fail.
I have read bellow resources but couldn't get what I wanted:
https://github.com/mui-org/material-ui/issues/9492
https://github.com/mui-org/material-ui/issues/6834
thanks for any feedback
Within my React+StyledComponent app, I have a theme file like so:
theme.js:
const colors = {
blacks: [
'#14161B',
'#2E2E34',
'#3E3E43',
],
};
const theme = {
colors,
};
export default theme;
Currently, I can easily use these colors to style my components like so:
const MyStyledContainer = styled.div`
background-color: ${(props) => props.theme.colors.blacks[1]};
`;
The problem is, how do I pass blacks[1] to a Component as the prop of the color to use like so:
<Text color="black[1]">Hello</Text>
Where Text.js is:
const StyledSpan = styled.span`
color: ${(props) => props.theme.colors[props.color]};
`;
const Text = ({
color,
}) => {
return (
<StyledSpan
color={color}
>
{text}
</StyledSpan>
);
};
Text.propTypes = {
color: PropTypes.string,
};
export default Text;
Currently the above is silently failing and rending the following in the DOM:
<span class="sc-brqgn" color="blacks[1]">Hello</span>
Any ideas on how I can get this to work? Thank you
EDIT: Updated to use styled-components withTheme HOC
New answer
You could wrap the component rendering <Text> in the higher order component (HOC) withTheme provided by styled-components. This enables you to use the theme given to the <ThemeProvider> directly in the React component.
Example (based on the styled-components docs):
import React from 'react'
import { withTheme } from 'styled-components'
import Text from './Text.js'
class MyComponent extends React.Component {
render() {
<Text color={this.props.theme.colors.blacks[1]} />;
}
}
export default withTheme(MyComponent)
Then you could do
const MyStyledContainer = styled.div`
background-color: ${(props) => props.color};
`;
Old answer
You could import the theme where you render and pass <Text color={theme.blacks[1]} />.
import theme from './theme.js'
...
<Text color={theme.colors.blacks[1]} />
Then you could do
const MyStyledContainer = styled.div`
background-color: ${(props) => props.color};
`;
You can use defaultProps
import PropTypes from 'prop-types'
MyStyledContainer.defaultProps = { theme }
App.js
App gets theme and passes color to Text
import React, { Component } from 'react'
import styled from 'styled-components'
const Text = styled.div`
color: ${props => props.color || 'inherit'}
`
class App extends Component {
render() {
const { theme } = this.props
return (
<Text color={theme.colors.black[1]} />
)
}
}
export default App
Root.js
Root component passes theme to entire application.
import React, { Component } from 'react'
import { ThemeProvider } from 'styled-components'
import theme from './theme'
import App from './App'
class Root extends Component {
render() {
return (
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
)
}
}
export default Root
If you're using functional components in React and v4.x and higher styled-components, you need to leverage useContext and styled-components' ThemeContext. Together, these allow you to use your theme settings inside of components that aren't styled-components.
import { useContext } from 'react'
import { ThemeContext } from 'styled-components'
export default function MyComponent() {
// place ThemeContext into a context that is scoped to just this component
const themeProps = useContext(ThemeContext)
return(
<>
{/* Example here is a wrapper component that needs sizing params */}
{/* We access the context and all of our theme props are attached to it */}
<Wrapper maxWidth={ themeProps.maxWidth }>
</Wrapper>
</>
)
}
Further reading in the styled-components docs: https://styled-components.com/docs/advanced#via-usecontext-react-hook