Component of Style: Hover effect defined in props

I'm trying to enhance my StyledButton by applying a hover effect. Currently, this is how I'm using it:

const StyledButton = styled.div<{
  hoverStyle?: CSSProperties
}>`
  color: black;
  background: blue;

  // Is there a way to incorporate the hoverStyle here?
`

<StyledButton
  hoverStyle={{
    backgroundColor: 'red',
    color: 'white',
  }}
>
  Click me
</StyledButton>

Does anyone have suggestions on achieving this?

Answer №1

Typically, we usually include individual values in additional styling properties. However, it is still entirely feasible to provide a collection of CSS rules (a CSSObject).

To start, you must utilize an interpolation function to adjust the style according to runtime props:

const StyledButton = styled.div<{
  hoverStyle?: CSSProperties
}>`
  color: black;
  background: blue;

  // How can I incorporate the hoverStyle here?
  ${(props) => props.hoverStyle && inlineRules(props.hoverStyle)}
`

In this case, I employed an inlineRules function to translate the CSSObject into a series of rules:

function inlineRules(rulesObj: CSSProperties) {
  return Object.entries(rulesObj).map(([property, value]) => `${property}: ${value};`).join('');
}

Now, considering the "hoverStyle" designation of your styling property, it suggests that these rules should only apply on :hover rather than directly merging with the primary styles of your <div>. Consequently, they need to be placed within a nested block, wherein you can employ the & symbol to reference the self style:

& signifies all instances of the component and is utilized for implementing broad overrides

  &:hover {
    ${(props) => props.hoverStyle && inlineRules(props.hoverStyle)}
  }

Experience a live demonstration on CodeSandbox: https://codesandbox.io/s/sleepy-brook-h515v7?file=/src/App.tsx

Please note: In styled-components, CSS rules are formatted using standard "kebab-case," while CSSProperties follow camelCase (e.g., "background-color" versus "backgroundColor" in your scenario). Within the aforementioned demo, I implemented a template literal conversion type to convert them to kebab-case, referencing TypeScript add kebab case types form actual camel case keys

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

Creating keys from extensive JSON data without having to manually match types using Typescript

Is there a way to efficiently parse and access the values in large JSON files using Typescript, without the need to manually define interfaces for all expected key/value pairs? In the past, working with small JSON files required only extracting a few spec ...

Passing props to a click event in React JS: A comprehensive guide

I have two color circles displayed below. When a circle is clicked, the color of that circle should update the bottom icon with the same color. However, this functionality is currently not working. Is there a way to pass the addcolor props to the handleCl ...

The react-google-maps-api documentation is unfortunately not easily reachable

Whenever I attempt to access the documentation, I receive an error message stating 404 not found Even after clearing my cache, I am still encountering the same issue. There is no other available documentation. - this link leads to the documentation page, ...

Controlling the Alignment of HTML Div Elements

I'm struggling to align some of these divs, especially centering them. I want the page to closely resemble this image: Here are the specific requirements: 1) The header text should be centered vertically and placed in a separate div with a black back ...

Adding a dropdown feature in a React.js component

I am working on a React project that requires me to create a dropdown menu using only pure React. The dropdown should also be responsive for different devices. The expected interactions are as follows: For larger devices like desktop screens: On hover Fo ...

Entry Points for Logging In

After stumbling upon this pre-styled Material UI login page example, I decided that it was exactly what I needed. However, I ran into an issue when trying to figure out how to store the username and password values. Whenever I try to use 'State' ...

Implementing a Timer on an HTML Page with JavaScript

I am looking to add a timer to my HTML page using JavaScript. The timer should get the selected date and time from an input field <input type="date" /> and control it. If the time difference between the current time and the selected time is less than ...

Uncertain entities in Typescript

I used to use Flow for typing. How can I type an imprecise object? Here's the array I'm working with: const arr = [ {label: 'Set', value: setNumber, id: 'setNumber', set: setSetNumber, type: 'text'}, ...

Switch the color (make it gray) of the selected tab in the navigation bar

<!-- Customizing the Navbar --> <nav class="navbar navbar-expand-sm bg-primary navbar-dark"> <a class="navbar-brand" href="<?php echo base_url('Controller_dashboard'); ?>"><strong>StuFAP MS</strong></a> ...

Jest stumbled upon a surprise token when trying to import OpenLayers

https://i.sstatic.net/gwhSF.png https://i.sstatic.net/CyxXR.png I have carefully reviewed this error and looked into various solutions provided in different posts. Unfortunately, none of them seem to resolve the issue for me. After thorough research, it ...

Encountered an issue attempting to create a rectangle with react-leaflet-draw in Vite: "Uncaught ReferenceError: assignment to undeclared variable type"

Encountering an issue when attempting to draw a rectangle, the error message reads: "Uncaught ReferenceError: assignment to undeclared variable type". All other shapes work fine, except for the rectangle. This error occurs with Vite, but everything functio ...

HTML does not support the use of certain symbols

Currently, I am in the process of designing a homepage for my school project. However, I have run into an issue. The content that I want to be displayed on my homepage is as follows: "Daudzspēlētāju tiešsaites lomu spēle (Massively Multiplayer Online ...

Uniformly spaced design with one child extending across the entire width of the screen

Is it possible to create a layout resembling the one shown in the image below by setting the fixed width only on the parent container? I am unable to use position: absolute; left: 0; right: 0; on the Full screen width child since it must remain in the flow ...

Preventing the "Block-scoped variable used before its declaration" error in an Angular/TypeScript tree structure with child/parent references

Imagine a scenario where we have a set of simple nodes/objects forming a tree structure, each with parent and children references. The challenge lies in the need to reference both the parent and children nodes independently from the tree itself. This means ...

Utilizing yarn workspaces and the yarn link feature in your project is

In my workspaces project, the structure is as follows: /project - package.json /packages /project-a package.json /project-b package.json The project-b relies on project-a. In the workspaces setup, everything works ...

An error occurred in TypeScript when trying to use the useState function with a string type. The ReferenceError indicates that

import React, { FunctionComponent, useState, useEffect } from 'react' const SearchBar: FunctionComponent = () => { const [searchValue, setSearchValue] = useState<string>('') const [isSuggestionOpen, setIsSuggestionO ...

Verifying Admin Roles with JWT in a Node.js environment

How can I determine if the user or admin made changes to the data on the site? I am utilizing JWT, nodeJS, typescript (along with postman for testing) This is my method for retrieving all users: UserSchema: export const userSchema = new Schema({ usern ...

Move the image inside the box without directly following the mouse cursor, but at a slightly faster pace

I am facing an issue with a Vue component that allows me to zoom in on an image and move it around the container. The problem is, when the image is zoomed in, it moves faster than the mouse due to using the scale transform. Additionally, I noticed that cl ...

Invisible Line Issue in React Apexcharts Line Chart

I've encountered an issue while using the apexcharts library with React to create a line chart. The problem is that the line representing the curve is not visible, especially when dealing with a large set of series data. Interestingly, when I reduce ...

It is not feasible to navigate in DetailsList using the Monaco editor

Hey there! I've been working with the DetailsList component and I'm trying to figure out how to navigate between columns using the tab key. However, I encountered an issue on Github that discusses this problem: https://github.com/microsoft/fluen ...