Utilizing TypeScript to incorporate media queries into styled components theme

In my development project using styled components with React and typescript, I have set up a theme.ts file to define the variables that are used in my ThemeProvider to expose them across the application. Additionally, I have created a styled.d.ts file where I declare DefaultTheme as an interface for theme.ts.

Recently, I created a media.ts file where I implemented reusable media queries based on an article I found at: https://medium.com/@samuelresua/easy-media-queries-in-styled-components-690b78f50053. Now, I want to include this media functionality in my theme so that it can be utilized throughout:

media.ts

import { css } from 'styled-components'

interface MediaQueryProps {
    [key: string]: any;
}

const breakpoints:  MediaQueryProps = {
   xs: 480,
   sm: 768,
   md: 992,
   lg: 1200 
}

export default Object.keys(breakpoints).reduce((acc, label) => {
   acc[label] = (literals: TemplateStringsArray, ...placeholders: any[]) => css`
      @media (max-width: ${breakpoints[label]}px) {
         ${css(literals, ...placeholders)};
      }
   `.join("");
   return acc
}, {}  as Record<keyof typeof breakpoints, (l: TemplateStringsArray, ...p: any[])=> string>)


theme.ts

import { DefaultTheme } from 'styled-components'
import media from './media';

const theme: DefaultTheme = {
    primary: "#262646",
    secondary: "#F9FAFE",
    success: "#00897B",
    danger: "#B00020",
    text: "#263646", 
    background: "#E8EAF6",
    white: "#ffffff",
    fonts: ["sans-serif", "Roboto"],
    ...media,
    fontSizes: {
      small: "1em",
      medium: "1.2em",
    },
}  
export default theme;

styled.d.ts

// import original module declarations
import 'styled-components'

// and extend them!
declare module 'styled-components' {
  export interface DefaultTheme {
    primary: string,
    secondary: string,
    success: string,
    danger: string,
    text: string, 
    background: string,
    white: string,
    fonts: Array<string>,
    fontSizes: {
      small: string,
      medium: string,
    },
  }
}

When attempting to use the mediaqueries in my App.ts without including ...media in DefaultTheme, I encounter an error stating 'Property 'media' does not exist on type 'DefaultTheme'.ts(2339)':

const TableRow = styled.tr`
    &:nth-of-type(odd){
        background: ${props => props.theme.secondary}
    }
    ${({theme}) => theme.media.sm`
        background: ${theme.secondary}
  `}
`

However, if I try defining it as follows, another error arises:

declare module 'styled-components' {
  export interface DefaultTheme {
    media: Array<string>
  }
} 

This results in an error in theme.ts stating 'Property 'media' is missing in type '{ primary: string; secondary: string; success: string; danger: string; text: string; background: string; white: string; fonts: string[]; fontSizes: { small: string; medium: string; }; }' but required in type 'DefaultTheme'.ts(2741)'

I am struggling to determine the correct way to define it in order for everything to function properly. When hovering over media in my code editor, I receive the following information from Typescript:

(alias) const media: Record string>

If you have any insights or guidance, please help...

Answer №1

It appears that your issue stems from not defining the necessary theme interface fields for media, yet attempting to use them in a default theme of type Them which lacks these specific fields.

A simple solution could be to define a media field within your interface, using type "any" and placing the media queries inside this new field. While I can't guarantee this will work or is considered best practice, it might be worth trying out. Personally, I don't have much experience with this type of theming, but something along these lines should suffice.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Refreshing pages when routing with Angular 2 router

While delving into the world of Angular 2, I encountered a challenge with setting up a basic route. Every time I click on a link, the browser redirects to the new route but it seems like all the resources are being re-requested, which goes against the beha ...

What is the most effective method for combining React, Redux, Redux-Form, and React-Saga seamlessly?

Having thoroughly researched the integration of react-saga and redux-form, I find myself at a crossroads in need of guidance. My journey to this point began with choosing Redux for my app, which has been smooth sailing so far. Transition from Thunk to Sa ...

Verify if the specified key is present in the type parameter and if it corresponds to the expected data type in the value parameter

I have a specific goal in mind: export interface GCLPluginConfig { [key: string]: string | number | boolean | Date | string[]; } export interface CorePluginConfig extends GCLPluginConfig { "core.lastUpdateCheck": Date; } export interface An ...

What is the best method for generating type declarations efficiently?

What is the most effective method for generating type declarations in a Typescript project (library) while also transpiling and bundling code efficiently? I am currently utilizing webpack, ts-loader, and fork-ts-checker-webpack-plugin. During a single bu ...

Using react hooks, I am refreshing the product image by replacing it with the thumbnail image

I'm currently working on an e-commerce platform that resembles Amazon. In the product detail page, I want the right side image to update when I click on a thumbnail image on the left side. The issue I'm facing is that upon first loading, the def ...

Expansive Child Division with Ample Margins

I'm currently working with a nested set of divs and I need the inner div to occupy the full width without extending beyond the parent div's margins. Despite trying to use max-width:100%, it hasn't been successful so far. For this particular ...

Designing a collection of inline divs that automatically stretch to fit the parent container, while also wrapping to a new line if the minimum width is reached

Welcome to my first post on this platform! I love a good HTML challenge, but I'm stumped on this particular issue and could really use some help. Thank you in advance to anyone who can assist. What I am trying to achieve is to create a series of inl ...

Creating a series of scalable svgs of uniform size in a row, enabling me to resize them based on width without disrupting the overall design

I need a row of equally sized SVGs with some text below them, like a navigation bar but larger. I almost have it working, but there are some issues with my current setup. To clarify, this is what I am aiming for: The SVGs should be responsive and scale a ...

Having trouble compiling the Electron App because of a parser error

Struggling to set up a basic electron app using Vue 3 and Typescript. Following the successful execution of certain commands: vue create app_name cd .\app_name\ vue add electron-builder npm run electron:serve Encountering issues when trying to i ...

Updating a Parent component from a Child component in React (Functional Components)

My functional component RoomManagement initiates the fetchRooms function on the first render, setting state variables with data from a database. I then pass setLoading and fetchRooms to a child component called RoomManagementModal. The issue arises when t ...

Navbar Username in Next.js with Typescript and Supabase Integration

I'm currently facing an issue with retrieving the username of a user to display in my navbar. The desired username is stored in the "username" column of the table called "profiles" in my Supabase database. However, the data that's populating the ...

Achieve horizontal centering of modal without the use of jQuery

Currently, I am developing a modal within a React application. The modal's width is set to auto and its position is set to fixed. My goal is to center it horizontally in the middle of the screen. .Modal { position: fixed; width: auto; z- ...

Removing fields when extending an interface in TypeScript

Attempting to extend the ISampleB interface and exclude certain values, like in the code snippet below. Not sure if there is an error in this implementation export interface ISampleA extends Omit<ISampleB, 'fieldA' | 'fieldB' | &apos ...

What is the best way to choose two <li> elements with multiple classes in my WordPress navigation menu?

I am looking for a JavaScript function that will add the class "current_highlight" when an element with the class "activo2" also has the class "active". Here is my HTML code: <div class="navbar-header"> <button type="button " class="navbar-to ...

Exploring external URLs beyond your Django website

Imagine you have a Django site with numerous buttons and links that all lead to . Instead of manually typing out the URL each time like this: <a href="http://stackoverflow.com" target="_blank" rel="noopener"> Is there a way to simplify this proces ...

A guide on leveraging Jest and Typescript to mock a static field within a class

While working with Typescript and a third-party library, I encountered an issue trying to write unit tests that mock out the library. Here's an example scenario: // Library.ts // Simulating a third party library export class Library { static code ...

animation for closing the hamburger menu

Having trouble creating a hamburger menu animation. I've set up two divs - one for the basic horizontal lines and one for the X icon. Using jQuery, I can hide and show them (clicking on the lines hides them and shows the X). But now I want to animate ...

Angular and Bootstrap 5 combine to create a dynamic multi-item carousel featuring animated slide transitions and embedded YouTube videos

I'm trying to create a multi-item carousel using YouTube videos, and although I have managed to get it working with Bootstrap 5 carousel and cards, the animation when the carousel slides is not as smooth as I would like. The issue seems to be that the ...

Getting the Angular component class reference within a triggered Highcharts selection event callback - what's the best approach?

It seems like I'm facing a common javascript closure issue, but let me illustrate it with a specific example as I'm struggling to grasp it in an Angular context. In my Angular component, I'm using the Highcharts library to visualize data. W ...

What strategies work well for managing Firestore integration within a React application?

Primarily, I have expertise as a react developer and my knowledge of the back-end is limited to just the basics. In an attempt to create a react project with Firebase using Firestore as the database, I typically rely on either redux or react-query to sto ...