I am currently working on a project which involves a dropdown menu, and I am following a tutorial. An issue that I encountered is with the dynamic styling of the dropdown.
<ul className={`dropdown ${dropdown ? "show" : ""}`}>
this is the code from the tutorial, my question is how can I rewrite it using styled-components?
// my Dropdown component
const Dropdown = ({ submenus, dropdown }) => {
return (
<StyledDropdown dropdown={dropdown}>
{submenus.map((submenu, index) => (
<li key={index}>
{submenu.title}
</li>
))}
</StyledDropdown>
);
};
export default Dropdown;
//styling of dropdown
export const StyledDropdown = styled.ul``;
You can get props in styled components
import styled, { css } from 'styled-components'
export const StyledDropdown = styled.ul`
${props => props.dropdown ? css`
// Style for show
` : ''}
`;
Related
I'm using a component in react.
import style from "../../Style/Styles.module.scss";
const Anchor = (props) => {
return <a className={style["anchorTags"]} href={props.href}>{props.title}</a>;
};
export default Anchor;
where I have already written CSS for this component in my SCSS file.
.anchorTags {
border: 2px solid $Very-Light-Gray;
color: $Very-Light-Gray;
}
but when I'm writing inline css in a component when using this on another component it is not working.
import style from "../../Style/Styles.module.scss";
import Anchor from "./achortag";
<Anchor
style={{ paddingBlock: "0.7em", paddingInline: "2em" }}
href="/viewPlan"
title="VIEW PLANS"
/>
Please share your suggestion on how this will work?
In Anchor component:
const Anchor = (props) => {
return (
<a className={style.anchorTags} href="#" style={props.style}>
{props.title}
</a>
);
};
export default Anchor;
or use the spread operator, this will add any additional attributes:
const Anchor = (props) => {
return (
<a className={style.anchorTags} href="#" {...props}>
{props.title}
</a>
);
};
export default Anchor;
To use the desired style, you must use this syntax:
import style from "../../Style/Styles.module.scss";
const Anchor = (props) => (
<a className={style.anchorTags} href={props.href} {...props}>{props.title}</a>;
);
export default Anchor;
For more information, you can read this (Adding a CSS Modules Stylesheet).
Let's say you have a navbar and when you're using this component on your homepage you want it to have a certain background color and display property, but when you use that same navbar component on another page in your application you want to change these CSS properties. Seeing as the component has one CSS file linked how would you change the style of a component depending on where it is being rendered?
My personal favourite method nowadays is styled components. Your component might look something like this:
// NavBar.js
import styled from 'styled-components'
const StyledDiv = styled.div`
width: 100%;
height: 2rem;
background-color: ${props => props.bgColor};
`
const NavBar = (bgColor) => {
return <StyledDiv bgColor={bgColor}>
}
Then to use it in your different contexts you simply pass the color prop:
// homepage.js
<NavBar bgColor="red" />
// otherpage.js
<NavBar bgColor="#123ABC" />
Styled components are becoming a very popular way of doing things, but be aware that there are a huge array of ways you can do this.
https://styled-components.com/
(Code not tested)
Well If you just want to use plain CSS then you can change the className based on route so the styles also changes.
Example:
import { useLocation } from "react-router-dom";
const Navigation = () => {
let location = useLocation();
...
return(
<nav className={location.pathname === "/home" ? "homepage-navbar" : "default-navbar"}>
...
</nav>
)
}
You can write longer condition for multiple pages as well.
Other better thing you can do is pass the location.pathname and value of className as prop.
import { useLocation } from "react-router-dom";
const Home = () => {
let location = useLocation();
...
return (
<>...
<Navigation location={location.pathname} styleClass={"homepage-navbar"}/>
</>
)
}
const Navigation = ({location, styleClass}) => {
...
return(
<nav className={location === "/home" ? styleClass : "default-navbar"}>
...
</nav>
)
}
So now you can pass different values for className from different components and get different styles for the navbar.
i am trying to toggle a class with useState, but i imported the class using module (not globally, xxx.module.css).
is it possible to toggle the class without changing them to global?
example:
import styles from 'xxx.module.css'
function app(){
const [active, setActive] = useState(false);
return()
<div className={active ? "active" : " "}><p>Hy there!</p> </div>
<button onClick={() => setActive(!active)}>toggle me</button>
}
export default app
with a css
.active{
display: flex;
}
its something like that, but if i use module to import css it won't really work since it require {styles.active} (i've already tried changing the class name to {styles.active} its not really working).
is there any way to work around this? thanks!
My solution:
import s from './x.module.css'
import {useState} from 'react'
const App = () => {
const [active, setActive] = useState(false)
return (
<div>
<div className={active ? s.active : null}>Hi world!</div>
<button onClick={()=> setActive(!active)}>Activate!</button>
</div>
)
}
x.module.css:
.active {
color: black;
}
I personally use the classnames library for this:
const className = classnames({ [styles.active]: active });
Alternatively, you can set up the functionality yourself:
const className = active ? styles.active : undefined;
and then: <div className={className}>
You must use className as styles.active and it must not be between quotation marks.
So your division tag must like that:
<div className={active ? styles.active : " "}>
...some JSX...
</div>
PS: The code you write here to specifing the problem have full of errors. I don't think in real code you did this terrible mistakes but I want to indicate this stiutaion.
The following question came up when I wanted to migrate from Styled Components to CSS Modules.
Let's say I have the following styled component which accepts a dynamic parameter offset and a dynamic CSS string theme:
const Li = styled.li`
&.selected {
background-color: grey;
}
margin-left: ${({ offset }) => offset}px;
${({ theme }) => theme};
`;
In my code, I'd use it the following way:
const Parent = () => (
<List>
{list.map((item) => (
<Item
key={item.id}
id={item.id}
selectedIds={[]}
offset={24}
theme={`
&.selected {
background-color: green;
}
`}
>
{item.name}
</Item>
))}
</List>
);
const Item = ({ id, offset = 0, theme, children }) => {
return (
<Li
theme={theme}
offset={offset}
className={selectedIds.includes(id) && 'selected'}
>
{children}
</Li>
);
};
Requirement: Now I would really keep the Item's component API: passing a number offset and a style string theme. So essentially everything in Parent component should stay this way.
How can I convert the Item component internally to use CSS Modules instead of the styled Li component?
It's probably a different way of thinking than you used to but it can work
You can use css variable
style={{ [`--offset`]: `${offset}px` }}
.item {
margin-left: var(--offset);
}
You can have a css module (file) dedicated to themes. In your case, it has withSelected
.withSelected {
&.selected {
background-color: green;
}
}
So you could pass it as "theme"
theme={themes.withSelected}
This is how the components look
import styles from "./style.module.scss";
import themes from "./themes.module.scss";
const Parent = () => (
<ul>
{list.map((item) => (
<Item
key={item.id}
id={item.id}
selectedIds={[1]}
offset={24}
theme={themes.withSelected}
>
{item.name}
</Item>
))}
</ul>
);
const Item = ({ id, offset = 0, theme, children, selectedIds }) => {
return (
<li
className={`${styles.item} ${theme} ${
selectedIds.includes(id) && themes.selected
}`}
theme={theme}
style={{ [`--offset`]: `${offset}px` }}
>
{children}
</li>
);
};
Demo: https://codesandbox.io/s/styledcomponent-to-css-modules-1kbqx
With 1 I'd concur with #Mosh to just use the style prop. Css modules are static by design and there no way to get this done otherwise (I think that styled-components also uses the style prop so you're not losing anything).
For 2 you can leverage Sass modules which allow you to define your theme in a single place and import them as required:
/theme/_colors.scss
$red: rgb(200, 0 50);
/components/Item.module.scss
#import "../theme/colors"
.selected {
background: $red;
}
Note: if you use Create React App absolute paths you can import from root as ~theme/colors
Im trying to make a wide drop down, to show a login form in it , and im trying reactstrap for it:
this is the code:
import React, { useState } from 'react';
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
const Example = (props) => {
const [dropdownOpen, setDropdownOpen] = useState(false);
const toggle = () => setDropdownOpen(prevState => !prevState);
return (
<Dropdown isOpen={dropdownOpen} toggle={toggle}>
<DropdownToggle caret>
Dropdown
</DropdownToggle>
<DropdownMenu>
<DropdownItem header>Header</DropdownItem>
<DropdownItem>Some Action</DropdownItem>
<DropdownItem disabled>Action (disabled)</DropdownItem>
<DropdownItem divider />
<DropdownItem>Foo Action</DropdownItem>
<DropdownItem>Bar Action</DropdownItem>
<DropdownItem>Quo Action</DropdownItem>
</DropdownMenu>
</Dropdown>
);
}
export default Example;
I wish the dropdown Menu would be like 500 px wide, how exactly can I do that? is it even possible?
You have to override the bootstrap css for the dropdown-menu.
Working Example
I think you can use reactStrap class to do that, you can try the following css as
.dropdown-menu {
width: 500px;
}
Hope it helps