Using styled-components in TypeScript: A tutorial with examples
Today, we need to build our user interface(UI) for our own websites, blogs, applications, products, etc., more attractive and elegant is essential to attract more users towards our products and services.The point where human users interact with an application is the user interface(UI).Take the ecommerce portal listed below, for instance.
This is the user interface, and it is how the e-commerce application communicates with the user. As you can see, it has established techniques for users that are more attractive, accessible, and understandable. It is done by using the right styling tools and coding languages when building the user interface. In this case, styled components are used.
Styled components
Styled components are nothing more than an advanced styling tool for using CSS code to construct React and React native components. It is an exclusive CSS-in-JS styling tool for React. Here, React is a JavaScript library used to create user interfaces, while React Native is also used to create user interfaces for mobile applications.
The use of styled components enables you to style your components using real CSS code. A styled component eliminates the mapping between components and styles; when you define your styles, you actually create a standard React component and attach your styles to it.
Styled components (CSS-in-JS) offer primitives for applying local CSS styles to a component with distinct, automatically created CSS classes."Tagged template literals" are used in styled components to style the components.
Let's explore the following contents to learn how we will use styled components in React JS to enhance TypeScript.
Configuration of a styled component in TypeScript
To start, we'll need to create a React app that supports TypeScript.
Run this command on your terminal.
npx create-react-app my-app --template typescript
# or
yarn create react-app my-app --template typescript
This will produce a simple template similar to the one below.
Next, execute the following commands in your root directory to install styled-components and the type definitions.
npm i styled-components @types/styled-components
#or
yarn add styled-components @types/styled-components
Create a Button element
Import the styled-components package into your App.tsx or App.ts file.
import styled from 'styled-components'
Make a styled button element and render it inside an HTML section tag above the App function.
const BUTTON = styled.button`
border: 1px dotted yellow;
background: white;
color: black;
font-weight: 500;
`
const App(){
return (
<section>
<BUTTON> First Btn </BUTTON>
<BUTTON> Second Btn </BUTTON>
</section>
)
}
Passing Props
UI components are made more dynamic by the usage of properties, or props for short. One significant benefit of using CSS in a JavaScript solution is the ability to pass customised props at runtime and adapt CSS in accordance.
Consider a scenario where you need two buttons with different border-colors but all other CSS values are the same. You may give props to each button under the condition that if the props value is present, the CSS property should be changed.
…
<BUTTON submit={true}> first Btn </BUTTON>
<BUTTON pay="shopping"> Second Btn </BUTTON>
...
From the aforementioned code, I assigned the first button the prop of submit and a boolean as the data type, and I assigned the prop of pay and a string to the second button.
Now, I define an interface containing both properties at the top of the styled button.
…
interface IBtn {
submit: boolean,
pay: string
}
const BUTTON = styled.button`
border: 1px dotted yellow;
background: white;
color: black;
font-weight: 500;
`
...
Now, all you have to do is pass this interface to the styled button, which will help typescript check the types of properties that should be accepted for the component.
…
const BUTTON = styled.button<IBtn>`
...
And after that, without TypeScript raising any errors, we can define the CSS properties based on the props the component receives.
…
const BUTTON = styled.button<IBtn>`
border: 1px ${props => props.submit ? 'solid' : 'dotted'} yellow;
background: white;
color: black;
font-weight: ${props => props.pay === "shopping" ? 'bold' : 500};
`…
Theming
By providing a wrapper component called <ThemeProvider>, styled-components offers complete theming functionality.Through the context API, this component grants a theme to all React components that are nested within it.All styled components in the render tree, regardless of how many levels deep they are, will have access to the specified theme.
Template of Theming concept
As you can see in the pictorial representation above, we want to define a ThemeContext and then wrap the whole app inside a ThemeContext.Provider.
Let's define a Theme interface first. Here, I want to construct a Theme interface with keys named according to the naming pattern for CSS variables.While colour values vary depending on the current theme, colour names are constant across all themes.
interface Theme {
'--primary': Color;
'--secondary': Color;
'--background': Color;
}
Then I developed a Color enum that lists every colour used in the app.
enum Color {
VIOLET = '#9E25FC',
DARK_VIOLET = '#250341',
LIGHT_GRAY = '#F4F4F4',
WHITE = '#FFF',
}
To identify the chosen theme, we additionally require a ThemeType type.
type ThemeType = 'dark' | 'light';
Finally, we require a themes configuration that details all of the colours used in each theme.
const THEMES: Record<ThemeType, Theme> = {
light: {
'--primary': Color.VIOLET,
'--secondary': Color.DARK_VIOLET,
'--background': Color.LIGHT_GRAY,
},
dark: {
'--primary': Color.VIOLET,
'--secondary': Color.WHITE,
'--background': Color.DARK_VIOLET,
}
};
Then, Themes Provider,
import React, { Dispatch, SetStateAction } from 'react';
import { THEMES } from './Theme.config';
import { ThemeType, Theme } from './Theme.types';
interface ThemeContextProps {
themeType: ThemeType;
theme: Theme,
setCurrentTheme: Dispatch<SetStateAction<ThemeType>> | null
}
export const ThemeContext = React.createContext<ThemeContextProps>({
themeType: 'light',
theme: THEMES['light'],
setCurrentTheme: null
}
export const ThemeProvider: React.FC = ({ children }) => {
const [currentTheme, setCurrentTheme] = React.useState<ThemeType>('light');
return (
<ThemeContext.Provider value={{
themeType: currentTheme,
theme: THEMES[currentTheme],
setCurrentTheme,
}}>
{children}
</ThemeContext.Provider>
)
}
export const useTheme = () => React.useContext(ThemeContext);
A popular react context implementation is the ThemeContext.I created a context type first.
ThemeContextProps
the context was then constructed with a starting state.
const ThemeContext = React.createContext<ThemeContextProps>({
themeType: 'light',
theme: THEMES['light'],
setCurrentTheme: null
}
Next, a ThemeProvider that accepts children as an argument must be made. It's crucial to have ThemeProvider support for rendering React components.
CurrentTheme state is managed by ThemeProvider. Finally, ThemeContext.Provider with the value object is returned. I passed themeType, theme, and setCurrentTheme in this example.
themeType - To know which theme is active at any given time and to be able to respond to that knowledge.
theme - This object includes each of the colors used in the current theme.
setCurrentTheme - theme-changing function.
I made the decision to wrap the entire react render in the ThemeProvider so that I could utilise the useTheme hook in the App component.
ReactDOM.render(
<React.StrictMode>
<ThemeProvider>
<App />
</ThemeProvider>
</React.StrictMode>,
document.getElementById('root')
);
We can easily obtain the theme via the useTheme hook to use it.
const { theme, themeType } = useTheme()
Now, depending on the themeType, we can render a specific graphic or another UI element, like in:
const logo = themeType === 'light' ? darkLogo : lightLogo
We must supply the theme object as CSS variables in order to use dynamic theme colours.
<div
style={{
...theme
} as React.CSSProperties}
>
// content
</div>
In essence, what happened above propagated the theme object in the div's style attribute. Now would be a good moment to remind you of the appearance of the theme object. Theme object therefore contains keys named according to the naming rules for CSS variables, and the values are colours listed in the Color enum.
These values were supplied as CSS variables, for instance.
'--primary': Color.VIOLET, // '#9E25FC'
It is now usable in CSS files.
.example {
color: var(--primary)
}
We can access all of the colours for the entire components tree if we supply the theme as a value for the style attribute at the very top level of the app.
Global Styling
Users can change the overall style of their entire website using a system and interface called global styles, which eliminates the need to edit individual blocks or pages. Users can choose a colour for the body background or adjust the line height for all of their heading blocks at once.
We will employ the createGlobalStyle function to declare styles that apply to the entire website. To achieve this, we will add a global.ts file to the src/styles directory.
Global styles:
// src/styles/global.ts
import { createGlobalStyle } from 'styled-components';
import BackgroundImage from '../assets/background.jpg';
export default createGlobalStyle`
* {
margin: 0;
padding: 0;
outline: 0;
box-sizing: border-box;
}
html {
background: url(${BackgroundImage}) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background
#root {
margin: 0 auto;
}
d-size: cover;
}
`;
A centralised background picture will be declared in the HTML and imported from a suitable path, in this case src/assets/background.jpg.
Media queries
Media queries are a crucial component of responsive web design because they let you design different layouts based on the size of the viewport. However, they can also be used to identify other aspects of the platform your site is running on, such as whether the user is using a touchscreen instead of a mouse.
A website or app's appearance (and sometimes even behaviour) can be changed by media queries in response to a matching set of criteria regarding the user's device, browser, or system settings.
const customMediaQuery = (maxWidth: number) => `@media (max-width: ${maxWidth}px)`;
const media = {
custom: customMediaQuery,
desktop: customMediaQuery(992),
tablet: customMediaQuery(768),
phone: customMediaQuery(576),
};
const ContentBlock = styled.div`
width: 4em;
height: 4em;
background: white;
/* Now we have our methods of raw queries */
${media.desktop} {
background: green;
}
${media.tablet} {
background: yellow;
}
${media.phone} {
background: blue;
}
`;
render(<ContentBlock />);
Additional features of styled components
Combined with code splitting, styled components fully automatically inject their styles while keeping track of which components are rendered on a page.
For your styles, styled components generate own class names. There are no issues with duplication, overlap, or misspellings.
CSS deletion is made simpler because it might be challenging to determine whether a class name is used elsewhere in your codebase. It is clear thanks to styled-components since each styling element is linked to a certain component. When a component is eliminated if it is unused (which tooling may identify) then all of its styles are also deleted.
Styled Components is a simple dynamic styling that allows you to adjust the styling of a component based on its props or a global theme without having to manually maintain dozens of classes.
No matter how large your codebase is, maintenance is simple since you never have to search through multiple files to find the styling that affects your component.
Automatic vendor prefixing: Use the current standard when writing your CSS, and let styled-components take care of the rest.
Boils down to
In CSS-in-JS libraries, styled components is a popular framework that allows you to use inline styled components in your React projects. The styles you create for your components won't influence other components unless you want them to, as they have an isolated scope.
Code splitting, automatic vendor prefixing, and basic dynamic styling are supported by styled components.
Since styled components are an advanced form of HTML and CSS, it is necessary to understand the fundamentals of HTML, CSS, and TypeScript before using them with styled components.
Conclusively,
(Styled Component = HTML + CSS) 👉 used with React(UI software) and TypeScript 👉 to style your user interface
Thank you, check you later !
Comments
Post a Comment