Link component not working with Styled Components - reactjs

The style not working
const MenuOption = styled(Link)`
font-size: 14px;
`;
Only using pseudo-class that styles its works

The better way is to Make a styled div or ul and then wrap it around link tag. Maybe make a component for it.
Example:
const NavBarLinkDiv = styled.div`
//your styles
`;
export default const NavBarLink = ({ children, to }) => {
return (
<Link to={to}>
<NavBarLinkDiv>{children} </NavBarLinkDiv>
</Link>
);
};

Related

Override them with styled components

I want to creare a template theme in React for my software suite and allow developers to customize the theme for each software they develop.
The theme will be shipped in a library using styled components
Here is an example of the code:
import styled from 'styled-components'
const ButtonStyled = styled.button`
font-size: 1.5em;
text-align: center;
color: green;
`;
const TomatoButton = styled(ButtonStyled)`
color: tomato;
`;
//This is the default template
const DefaultTemplate = () => {
return <div>
<ButtonStyled className='button'>Button</ButtonStyled>
<TomatoButton className='tomato-button'>Button II</TomatoButton>
</div>
}
//This is the template styled by developers
const DefaultTemplateStyled = styled(DefaultTemplate)`
color: white;
&.button{
color: violet
}
&.tomato-button{
color: black;
}
`;
function App() {
return (<DefaultTemplateStyled />);
}
export default App;
In this app I cannot see the override of the styles, am I missing something?
In styled-components what you should do is pass the className propm like this:
//This is the default template
const DefaultTemplate = ({ className }) => {
return (
<div>
<ButtonStyled className={`button ${className}`}>Button</ButtonStyled>
<TomatoButton className={`tomato-button ${className}`}>
Button II
</TomatoButton>
</div>
);
};
All the other code is fine

Receiving prop in Material UI and conditional rendering

This is a styled-component code block, it gets an img prop and based on the prop, it decides to load a specific image.
export const DialogBanner = styled.div`
min-height: 250px;
margin-bottom: 20px;
${({ img }) =>
img
? `background-image: url(${img});`
: `background-image: url("/img/banner.jpg");`}
background-position: center;
background-size: cover;
filter: contrast(85%);
`;
<DialogBanner img={food.img} />
How can I write the same thing using Material UI's useStyles?
EDIT: This is now legacy and was written for version 4
Using the latest version of Material-UI you would use makeStyles which creates a hook for use within your component. https://material-ui.com/styles/basics/#adapting-based-on-props
For Example.
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
// Create our styles using passed props
// These are `functors` it seems
const useStyles = makeStyles({
root: {
backgroundImage: ({ img }) =>
img
? `url(${img});`
: `url("/img/banner.jpg");`}
},
});
function DialogBanner(props) {
// Separating out our children
const { children, ...rest } = props
// Prop containing our `img`
const classes = useStyles(rest);
retun <div className={classes.root>{children}</div>
}

Is there a way to declare styled component with different main elements?

I need to create 2 similar styled components, which will share their styling but use different HTML element.
There is a way to do in runtime with "as" property (), but I have a specific exports which I need to use the default but I need for it to be in a way without using it so the Link styled component be a "styled.a" and StyledLink component to be "styled.span", I tried to do something like:
export const StyledLink = styled.span(`
color: ${props => props.theme.colors.mainLinkColor};;
text-decoration: underline;
&:hover {
color: ${props => props.theme.colors.textAccent};
text-decoration: underline;
}
`);
export const Link = <StyledLink as={RRLink} />;
That is obviously not working... So is there a way for a Link to mimic StyledLink styles but use an "a" tag instead of "span"?
Simply import and use css from styled-components like so:
import React from "react";
import ReactDOM from "react-dom";
import styled, { css } from 'styled-components';
const sharedStyles = css`
background-color: gold;
`;
const Div = styled.div`
${sharedStyles}
`;
const Button = styled.button`
${sharedStyles}
`;
const App = () => (
<>
<Div>Hello Div</Div>
<Button>Hello Button</Button>
</>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

How to inherit style from another component?

I want to take styling from the component 'Tab' which is a react-router-dom Navlink and apply it to my new component 'DropdownTab' which is a 'div'. How can I inherit the styling without making it a NavLink? I want to do this to avoid duplicate lines of code.
const Tab = styled(NavLink)`
padding: 0 20px;
height: ${variables.height};
line-height: ${variables.height};
`;
// Should be the component 'Menu' and is now the component NavLink
const DropdownTab = styled(Tab)`
`;
Perhaps you can use as?
const DropdownTab = styled(props => <Tab as="div" {...props} />)`
/* additional styles */
`;
That's ugly though, so maybe you can just extract the common styles into a variable:
const commonStyles = `
/* common styles */
`
const Tab = styled(NavLink)`${commonStyles}`
const DropdownTab = styled('div')`${commonStyles}`
If you have prop-based style in your component (i.e color: ${props => props.color}, you'd need to use css helper:
import styled, { css } from 'styled-components'
const commonStyles = css`
color: ${({ isActive }) => isActive ? 'red' : 'blue' };
`
...
Why is DropdownTab a div?
Based on your code, DropdownTab is a Tab. You've used the extending styles concept of styled-components and you've done it right.

Best way to style a component?

I have two solutions to style my component. Which one is the better choice?
First option is to set everything in the styled component.
Second option is to use many container and styles one by one containers.
First option:
export const BaseContainer = styled.div`
span {
color: #E0E0E0;
}
i {
margin-right: 16px;
}
`;
<BaseContainer data-testid="base">
<i className="icon-share" />
<span> {base} </span>
</BaseContainer>
Second option:
export const BaseContainer = styled.div`
color: #E0E0E0;
`;
export const IconContainer = styled.div`
margin-right: 16px;
`;
<IconContainer>
<i className="icon-share" />
</IconContainer>
<BaseContainer data-testid="base">
{base}
</BaseContainer>
I would go for the second option as the first option ties together 2 elements in one div and if you would want to use the same css properties in another case would require refactoring.
But be aware that your second option is not really a small difference from the first:
In your first option you have one div with one i and one span inside of it and you are applying style to i and span correspondingly.
In your second option you have 2 separate div one with one i and the other with just a content and you are applying style to both div instead.
That said, the best solution would be to actually style the span and i individually, something like
const StyledSpan = styled.span`
color: #E0E0E0;
`
const StyledIcon = styled.i`
margin-right: 16px;
`
And then use them as:
<div data-testid="base">
<StyledIcon className="icon-share" />
<StyledSpan>{base}</StyledSpan>
</div>
I think it's a bit opinion based, but I would approach this a manner like this:
const IconContainer = styled.i`
margin-right:16px;
`;
const Icon = ({
iconType,
...props}) => <IconContainer className={ `icon-${iconType}` } {...props } />;
const BaseContainer = styled.div`
color: #E0E0E0;
`;
const LabelledIcon = ({ iconType, ...props }) => <BaseContainer>
<Icon iconType={ iconType } />
{ props.children }
</BaseContainer>;
// usage:
<LabelledIcon iconType="share"> icon label text </LabelledIcon>

Resources