Can I use tailwind classes ( like colors ) into the styled-components ?
I want to use some classes instead of CSS styles to style my components
this is the way add class in styled-components:
const Button = styled.button.attrs(props => ({
className: "small",
}))`
/* other styles */
`;
so unlike styles, attrs className is only one single string, and I want to add classes for size, color, display and etc.
I have to concat them all every time, is there a better way ?
You can use macro, I suggest trying twin.macro:
import tw, { styled } from 'twin.macro'
const Input = styled.input`
color: purple;
${tw`border rounded`}
${({ hasHover }) => hasHover && tw`hover:border-black`}
`
const Component = () => <Input hasHover />
Related
so I am currently working with the stitches styling library and the radix-ui library. I am using the theme feature (darkTheme/lightTheme).
It all works perfectly in updating all but one of the radix-ui components.
The Dropdown.Content doesn't get updated right and I don't understand why. I am currently passing in a $backgroundColor to the styles and instead of it changing depending on the theme, it sticks to the color from the default theme.
This is the code from my styles.ts file:
export const DropdownContent = styled(DropdownMenu.Content, {
background: '$backgroundColor',
border: '2px solid $borderColor',
)},
This is a snippet from my stitches.config.ts file:
export const {
styled,
css,
globalCss,
keyframes,
theme,
createTheme,
config,
} = createStitches({
theme: {
colors: {
backgroundColor: '#ffffff',
borderColor: '#E5E8EB',
},
space: {},
fonts: {},
},
media: {},
utils: {},
});
export const darkTheme = createTheme({
colors: {
backgroundColor: '#141416',
borderColor: '#353945',
}
});
This is because the content is rendered directly in the body tag through a React Portal, a default Radix behavior. Try setting open={true} on the Select and inspect the content elements to see for yourself.
You're most likely adding the dark theme class somewhere along your component tree, i.e. on your App component. That will not work for elements outside of that tree, for instance ones rendered in the body tag through a portal.
You need to apply the dark theme class to your body tag, like this:
const [darkTheme, setDarkTheme] = useState(true);
useLayoutEffect(() => {
const { classList } = document.body;
if (darkTheme) classList.add(darkThemeCssClass);
else classList.remove(darkThemeCssClass);
}, [darkTheme]);
This will allow the theme-dependent styling to be applied to all elements on the page, not just ones in your component tree.
I was using this Link from #material-ui/core/Link in my TypeScript code and it worked perfectly:
<Link href="#" variant="body2">
Forgot?
</Link>
However, I am trying to switch to styled-components placed in another file. Now, I am trying to use this (eg: https://styled-components.com/docs/basics):
const Link = ({ className, children}) => (
<a className={className}>
{children}
</a>
);
export const StyledLink = styled(Link)`
href: #;
variant: body2;
`;
along with:
<StyledLink>Forgot?</StyledLink>
But I keep getting errors on className and children that Binding element 'children' implicitly has an 'any' type.ts(7031but even if I add any, It doesn't work.
What is the correct way to use styled-components in this case? Or any other css-in-js alternative?
This code works, and gets no warnings from the typescript compiler
import styled from "styled-components";
const Link = ({
className,
children
}: {
readonly className: string;
readonly children: React.ReactElement;
}) => (
<a href="/" className={className}>
{children}
</a>
);
export const StyledLink = styled(Link)`
href: #;
variant: body2;
color: red;
`;
function App() {
return (
<StyledLink className="classic">
<div>Forgot?</div>
</StyledLink>
);
}
You should make your Link component just like below:
// Link.js
import { Link } from '#material-ui/core/Link';
import styled from 'styled-components';
export default styled(Link)`
display: block;
color: #F51963;
text-decoration: none;
`;
You can use the <Link> on top of other divs or buttons for example
<Link><button className="Btn">Forgot?</button></Link>
you can then do two things to style the button / divs
<Link><button className="Btn" style={{backgroundColor: 'red'}}>Forgot?</button></Link>
or the second is import a separate css file
import classes from './ComponentName.module.css'
and then give a style
<Link><button className={classes.Btn}>Forgot?</button></Link>
I am using reactjs-popup, and one of it's props is contentStyle, which allow you to pass css-in-js object to style an internal div in the library.
however when I pass css object with #media in it, the library doesn't deal with it.
I wonder if there is a way to tell emotion to "translate" this object, or somehow wrap the library element, so it can treat the #media query as needed.
this is a code to demonstrate:
/** #jsx jsx */
import { jsx } from '#emotion/core';
import ReactJsPopup from 'reactjs-popup';
import { FC, PropsWithChildren } from 'react';
const Modal: FC<{}> = props => {
const style = {
padding: 0,
minHeight: '100%',
'#media (min-width: 576px)': {
minHeight: 'auto' // <----------- Doesn't work
}
}
return (
<ReactJsPopup contentStyle={style}>
{(close): JSX.Element => (
<div>
BODY
</div>
)}
</ReactJsPopup>
);
};
export default Modal;
Inline style objects currently do not support media queries.
The viable option here is to use the className prop to style the content. As the docs reads:
this class name will be merged with the component element: ex className='foo' means foo-arrow to style arrow, foo-overlay to style overlay and foo-content to style popup content
When using emotion, you can make sure that the selectors are unique using this property.
import { css } from "emotion";
<ReactJsPopup
className={css`
&-content {
color: red;
}
`}
>
</ReactJsPopup>
Note: The & is for the random classname that is going to be added by emotion. Followed by content that is added by the library
I would like to set global style for the react-select. For my understanding I can do 2 ways:
Using className and classNamePrefix and then target elements using CSS.
PROS: I can use the same style everywhere
CONS: Every new component must use exactly the same className and classNamePrefix
Example:
className='react-select-container'
classNamePrefix="react-select"
Result:
<div class="react-select-container">
<div class="react-select__control">
<div class="react-select__value-container">...</div>
<div class="react-select__indicators">...</div>
</div>
<div class="react-select__menu">
<div class="react-select__menu-list">
<div class="react-select__option">...</div>
</div>
</div>
</div>
Create external javascript file with "Provided Styles and State"
PROS: more flexible then CSS
CONS: Every new component must use style property using imported external file.
Example:
const customStyles = {
option: (provided, state) => ({
...provided,
borderBottom: '1px dotted pink',
color: state.isSelected ? 'red' : 'blue',
padding: 20,
}),
control: () => ({
// none of react-select's styles are passed to <Control />
width: 200,
}),
singleValue: (provided, state) => {
const opacity = state.isDisabled ? 0.5 : 1;
const transition = 'opacity 300ms';
return { ...provided, opacity, transition };
}
}
const App = () => (
<Select
styles={customStyles}
options={...}
/>
);
What is the best way to style multiple react-select components? Will be possible to set style globally and every new react-select component use that style automatically?
One way to do it is to create your own select component like CustomSelect that you import instead of react-select where you set for one the custom style or theme like:
import React, { Component } from 'react'
import Select from 'react-select'
class CustomSelect extends Component {
render() {
const styles = {
...
// what ever you need
}
return <Select styles={styles} {...this.props} />
}
}
export default CustomSelect
I can't really tell if it's the best way or not but I've tried both of it and in a big project with many select it's the easiest way to maintain / modify it. Plus it's really convenient if at some point you need to have custom components.
I am using the awesome "Styled-Components"
but I am now using another package that wraps an element inside it so I can't push my StyledComponents there as I don't want to change his package.
I saw glamor has a nice trick.
Is that supported with StyledComponents?
import { css } from 'glamor';
let rule = css({
color: 'red',
})
<div {...rule}>
zomg
</div>
If you think about why I need it, here is an example:
this is an external package I'm using:
External = props => (
<div>
<input style={props.inputStyle} className={props.inputClass} />
</div>
);
so you can see I need to pass in a json style or className
so Glamor will work here, but I dont want to use it just for this scenario.
I'm already enjoying StyledComponent
Thanks
If I understood your query, you can define css rules to a component, like this
import styled from 'styled-components'
const Wrapper = styled.div`
color: 'red';
font-weight: bold;
background-color: ${ props => props.color === 'primary' ? 'green' : 'red' }
`
export const Component = () => {
<Wrapper color='primary'>
I have a red text, and bold font-weight.
</Wrapper>
}