How to remove styling from Link of react router with styled-components - css

I'm using styled-components but in a different file. I've searched for this question and found many answers, but I'm still confused about how to apply it in my code version. So, sorry in advance if it will be repetitive.
File Main.jsx :
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
function Main() {
return (
<>
<Router>
<MainComponent>
<Menu>
<Link to="/crypto">
<HyperLink>Crypto</HyperLink>
</Link>
<Link to="/marketplace">
<HyperLink>Market Place</HyperLink>
</Link>
</Menu>
<Switch>
<Route path="/crypto" component={Crypto} />
<Route path="/marketplace" component={MarketPlace} />
</Switch>
</MainComponent>
</Router>
</>
);
}
File MainElements.jsx:
import styled from "styled-components";
export const MainComponent = styled.div`
width: 100%;
height: 100vh;
background-color: #1e2258;
`;
export const Menu = styled.div`
display: flex;
width: 80%;
margin: auto;
height: 10vh;
color: #fff;
border: 1px solid white;
align-items: center;
`;
export const HyperLink = styled.p`
text-decoration: none;
&:focus,
&:hover,
&:visited,
&:link,
&:active {
text-decoration: none;
}
`;

Can try example from react-router docs https://reactrouter.com/web/api/Link/component-reactcomponent
Just use a tag instead of p for link.
const FancyLink = React.forwardRef((props, ref) => (
<HyperLink ref={ref} {...props}>{props.children}</HyperLink>
))
<Link to="/" component={FancyLink} />
const CustomLink = ({ ...props }) => <Link component={FancyLink} {...props} />

Related

MUI specificity is different in storybook than in application

I noticed that my styles on a component look right in storybook but not in the running application. The component code is at the bottom of this post.
All the components are from MUI, and looking at the "Computed" tab of the Chrome inspector, I can see that the Avatar components are getting their styles differently in the two environments -- the priorities of the classes are swapped:
In the app:
In the storybook
Wrapping the styles in && fixes the problem, and I've used this solution before for MUI style issues, but I've never come across the case where it behaves differently in the app vs storybook.
Here's my main decorator in preview.tsx
export const decorators: ComponentStoryObj<React.FC>['decorators'] = [
story => {
return (
<>
<header>
<link
href='https://fonts.googleapis.com/css?family=Roboto:100,200,300,400,500,600,700'
rel='stylesheet'
/>
<link
href='https://fonts.googleapis.com/css?family=Roboto+Condensed:400,500,600,700'
rel='stylesheet'
/>
</header>
<AppWrapperWithUser>{story()}</AppWrapperWithUser>
</>
);
},
];
Here's the AppWrapper used above, which also wraps the application itself (so that the styles match)
import { ThemeProvider as MuiThemeProvider } from '#mui/material/styles';
import { ThemeProvider as StyledThemeProvider } from 'styled-components';
import { globalStyles, theme } from './theme';
type Props = {
store?: ReturnType<typeof createStore>;
initialState?: RootState;
};
export const AppWrapper: React.FC<Props> = ({ children, store, initialState }) => {
const appStore = store || createStore(initialState);
return (
<MuiThemeProvider theme={theme}>
<StyledThemeProvider theme={theme}>
{globalStyles}
<Provider store={appStore}>{children}</Provider>
</StyledThemeProvider>
</MuiThemeProvider>
);
};
And the component in question:
const S = {
Wrapper: styled(Paper)`
padding: 32px;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;Ø
overflow: hidden;
`,
Pane: styled.div<{ centered?: boolean }>`
display: flex;
flex-direction: column;
gap: 4px;
align-items: ${p => p.centered && 'center'};
`,
Subtitle: styled(Typography).attrs({ variant: 'body2' })`
font-size: 14px;
text-transform: uppercase;
`,
Title: styled(Typography)`
&& {
font-size: 28px;
font-weight: 700;
}
`,
Avatar: styled(Avatar)`
height: 84px;
width: 84px;
box-sizing: content-box;
border: 2px solid rgba(0, 0, 0, 0.1);
`,
TeamLogoWrapper: styled.div`
display: flex;
align-items: center;
height: 100%;
width: 222px;
`,
TeamLogo: styled(Avatar)`
height: 222px;
width: 222px;
box-sizing: content-box;
opacity: 0.3;
border: 2px solid rgba(0, 0, 0, 0.1);
position: absolute;
`,
};
const PlayerDetailHeader = ({ player }: { player: ProcessedPropUIPlayer }) => {
const { ... } = player;
const infoStr = [teamName, `#${uniformNumber}`, position].join(' | ');
return (
<S.Wrapper data-testid={`PlayerDetailHeader-${playerId}`}>
<S.Avatar alt={playerName} src={playerImg} />
<S.Pane>
<S.Title>{playerName}</S.Title>
<S.Subtitle>{infoStr}</S.Subtitle>
</S.Pane>
<S.Pane centered>
<S.Title>{openProps}</S.Title>
<S.Subtitle>Open Props</S.Subtitle>
</S.Pane>
<S.Pane centered>
<S.Title>{dollarFormatter(openAction)}</S.Title>
<S.Subtitle>Open Action</S.Subtitle>
</S.Pane>
<S.TeamLogoWrapper>
<S.TeamLogo alt={teamName} src={teamImg} />
</S.TeamLogoWrapper>
</S.Wrapper>
);
};

react styled-component nested item's props

My problem is about props. I want to use nested components with props in styled-components. For example:
const MenuItem = ({ item }) => {
const router = useRouter();
const [isOpen, setIsOpen] = useState(false);
const isActive = router?.asPath === item?.path;
return (
<MenuItemWrapper key={item?.slug} onClick={() => setIsOpen(!isOpen)}>
<Link href={item?.path}>
<InnerMenuItem isActive={isActive}>
{item?.prefix && <Prefix>{item?.prefix}</Prefix>}
{item?.label}
{item?.children && <RightArrow isOpen={isOpen} />}
</InnerMenuItem>
</Link>
<Children>
{
item?.children?.map((child) => <MenuItem item={child} />)
}
</Children>
</MenuItemWrapper>
);
};
export default MenuItem;
this is MenuItem component. I use MenuItem component as a recursion component.
in styled-component i tried this but it doesnt work. I want to apply different style in Children > InnerMenuItem but it not working
export const Children = styled.div`
display: flex;
flex-direction: column;
margin-left: 65px;
${MenuItemWrapper} {
font-size: 16px;
padding: 9px 0;
&:not(:first-child) {
border-top:none;
}
}
${InnerMenuItem} {
${({ isActive }) => // HOW CAN I USE THIS PROPS HERE
isActive &&
css`
color: orange
`};
}
`;
from styled components official documentations:
"If the styled target is a simple element (e.g. styled.div), styled-components passes through any known HTML attribute to the DOM. If it is a custom React component (e.g. styled(MyComponent)), styled-components passes through all props."
example :
const Input = styled.input`
color: ${props => props.inputColor || "palevioletred"};
`;
return(
<Input inputColor="rebeccapurple" />
)
another way is by Extending Styles, example :
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;
return(
<div>
<Button>Normal Button</Button>
<TomatoButton>Tomato Button</TomatoButton>
</div>
);
more about styled-components read here
have you tried
${InnerMenuItem} {
color: ${({isActive})=> isActive ? 'orange' : undefined}
};

How to find out which Router component is being rendered in React?

I have a Navbar component and I am trying to render it with different CSS styles using styled-components with respect to the component route which is being rendered. How can I check if that component is being rendered or not ?
const NavbarContainer = styled.div`
height: 115px;
font-family: 'Domine', serif;
align-content: center;
align-items: center;
position: absolute;
z-index: 4;
width: 100vw;
overflow: hidden;
&:hover {
background-color: white;
color: black !important;
}
`;
lets say this the component and I want to change position: absolute to position: static in Login page but I want that to stay that as position: absolute in the home page. How can I achieve this?
Create a version of the NavbarContainer specific for the login route and override the position rule, and use layout routes to render the appropriate routes with the appropriate layout/navbar.
Example:
const NavbarContainer = styled.div`
height: 115px;
font-family: 'Domine', serif;
align-content: center;
align-items: center;
position: absolute;
z-index: 4;
width: 100vw;
overflow: hidden;
&:hover {
background-color: white;
color: black !important;
}
`;
const StaticNavbarContainer = styled(NavbarContainer)`
position: static;
`;
...
import { Outlet } from 'react-router-dom';
const NavbarLayout = ({ children }) => (
<>
<NavbarContainer>{children}</NavbarContainer>
<Outlet />
</>
);
const StaticNavbarLayout = ({ children }) => (
<>
<StaticNavbarContainer>{children}</StaticNavbarContainer>
<Outlet />
</>
);
...
<Routes>
<Route
element={(
<NavbarLayout>
// ... render links here as children
</NavbarLayout>
)}
>
<Route path="/" element={<Home />} />
// ... routes to render with absolute positioned navbar
</Route>
<Route
element={(
<StaticNavbarLayout>
// ... render links here as children
</StaticNavbarLayout>
)}
>
<Route path="/login" element={<Login />} />
// ... other routes with static positioned navbar
</Route>
// ... other routes without navbars
</Routes>
One idea would be to wrap your component inside another
like
In Login page
const NavWrapper = styled.div`
>div{
position: static
}
`
<NavWrapper>
<NavbarContainer/>
</NavWrapper>
You can achieve this with conditional styled based on login path
<Appbar style={{ position: pathname === '/login' ? 'static' : 'absolute' }}></Appbar>

organize Css menu-bars

i had create a menu-bars hamburger inside the app.js file to show it when I click on the 3bars alls is good but I had a problem related to CSS so when I click on icons-bar the menubar display very well but the other menu navbar on the right of it disappear.to be honest with you I'm not hero in CSS.this is my code :
app.js file:
import {useState} from "react";
import {BrowserRouter, Routes, Route, Link} from "react-router-dom";
import {useSelector} from "react-redux";
import HomePage from "./Pages/HomePage";
import ProductPage from "./Pages/ProductPage";
import CartPage from "./Pages/CartPage"
function App() {
const cart = useSelector(state=> state.cart);
const productsList = useSelector(state=> state.productsList);
const { products } = productsList;
const categories = products?.length
? products.map(({category})=> category)
: [];
const [open, setOpen] = useState(false);
const allCategories = categories.filter((element, index, categories)=> element !== categories[index + 1]);
console.log(allCategories)
const { cartProducts } = cart;
const menuBar = () => {
return (
<div className={open ?"bars": "bars-close"} >
{allCategories.map((category, index)=> <div key={index} className="bar" >{category}</div>
)}
</div>
)
}
console.log(open)
return (
<BrowserRouter>
<div className="grid-container" >
<header className="row">
<div>
<Link className="brand" to="/">My shop</Link>
<span className ="menu-bar">
<i onClick={()=> setOpen(!open)} className="fa fa-bars"></i>
</span>
{menuBar()}
</div>
<div>
<Link to="/cart/:id">Cart
{cartProducts.length > 0 && (
<span className="badge" >{cartProducts.length}</span>
)}
</Link>
<Link to="/signin">Sign In</Link>
</div>
</header>
<main>
<Routes>
<Route path="/cart/:id" element={<CartPage />} ></Route>
<Route path="/product/:id" element={<ProductPage />} exact ></Route>
<Route path="/" element={<HomePage />} ></Route>
</Routes>
</main>
<footer className="row center" >All right reserved</footer>
</div>
</BrowserRouter>
);
}
export default App;
index.css file just the part of menu-bars:
.bars {
display: block;
width: 20rem;
background-color: #101010;
height: 80px;
transition-delay: 400ms;
z-index: 2;
position: relative;
left: 5rem;
}
.bars-close {
display: none;
transition-delay: 500ms;
}
.bars .bar {
font-size: 2rem;
color: #fff;
text-decoration: underline;
margin: 0.2rem 0;
text-align: center;
}
.menu-bar {
color: #ffffff;
}
.menu-bar i {
margin-left: 2rem;
font-size: 3rem;
cursor: pointer;
}

props is not applied although passed it to styled component

What I want to do
Changing colors depending on props passed from a component using styled component.
Problem
SmallButton component definitely gets props but it doesn't change like props indicates.
I would like to change styles of SmallButton depending on props that a component gives to the button component.
SmallButton has these props but it doesn't change at all.
I would like you to teach me how to solve it.
Thank you very much.
=== ==== === ===
My code is like this.
Header.jsx
render() {
return (
<>
<Wrapper>
{/* CSS Grid( 1 : 1 : 1) 左 */}
<Image src={Logo} alt="" />
{/* CSS Grid( 1 : 1 : 1) 中央 */}
<SearchBox />
{/* CSS Grid( 1 : 1 : 1) 右 */}
{this.props.isAuthenticated ? (
<>
<div>
<MessageToUserDiv>
<span>Hello {this.state.loginUser.username}</span> 
<LogoutButton onClick={this.handleLogout}>Logout</LogoutButton>
</MessageToUserDiv>
<AuthButtonDiv>
<SmallButton
btn_border="#466A80"
btn_back="#466A80"
btn_text_color="#D9F1FF"
btn_name="Post"
btn_click={this.jumpToPostGive}
/>
<SmallButton
btn_border="#466A80"
btn_back="#8DD6FF"
btn_text_color="#466A80"
btn_name="Info"
btn_click=""
/>
</AuthButtonDiv>
</div>
</>
) : (
<>
<div>
<p>Hello Guest</p>
<AuthButtonDiv>
<SmallButton btn_name="Register" btn_click={this.jumpToRegister} />
<SmallButton btn_name="Login" btn_click={this.jumpToLogin} />
</AuthButtonDiv>
</div>
</>
)}
</Wrapper>
</>
);
}
}
const Wrapper = styled.div`
background-color: #8dd6ff;
width: 100%;
display: grid;
grid-template-columns: 1fr 2.3fr 1fr;
padding: 10px 5px 5px 5px;
`;
const Image = styled.img`
width: 230px;
margin-top: 5px;
`;
const MessageToUserDiv = styled.div`
font-size: 13px;
text-align: right;
height: 20%;
`;
const LogoutButton = styled.button`
color: #6e787f;
width: 30%;
`;
const AuthButtonDiv = styled.div`
display: flex;
justify-content: space-around;
align-items: flex-end;
height: 80%;
`;
SmallButton.jsx
class SmallButton extends Component {
constructor(props) {
super(props);
}
render() {
return (
<StyledButton
type={this.props.btn_type}
onClick={this.props.btn_click}
onSubmit={this.props.btn_submit}
disabled={this.props.btn_disable}
>
{this.props.btn_name}
</StyledButton>
);
}
}
const Colors = {
main: '#8DD6FF',
characters: '#6C7880',
subcolor1: '#D9F1FF',
accent1: '#70AACC',
accent2: '#466A80',
};
const StyledButton = styled.button`
font-size: 1.18em;
border-radius: 7px;
height: 45px;
width: 100px;
padding: 2px 3.5px;
border: solid 2.5px;
border-color: ${(props) => props.btn_border};
background: ${(props) => props.btn_back};
color: ${(props) => props.btn_text_color};
`;
spread the rest for your props to StyledButton like this:
<StyledButton
type={this.props.btn_type}
onClick={this.props.btn_click}
onSubmit={this.props.btn_submit}
disabled={this.props.btn_disable}
{...this.props}
>
{this.props.btn_name}
</StyledButton>

Resources