How to make the label that wraps a button clickable too in React - javascript

Having the following components:
<CheckboxGroupLabel htmlFor={option.label}>
<FormCheckbox
onClick={() => onChange}
key={option.label}
defaultChecked={defaultChecked}
{...rest}
/>
{option.value}
</CheckboxGroupLabel>
Their styled components are:
import styled from 'styled-components';
import * as Checkbox from '#radix-ui/react-checkbox';
export const CheckboxGroupLabel = styled.label`
background-color: red;
display: flex;
width: 100%;
margin: 18px;
line-height: 20px;
cursor: pointer;
width: 100px;
`;
export const StyledCheckboxRoot = styled(Checkbox.Root)`
button {
all: unset;
}
`;
So the checkbox is inside label but only checkbox is clickable, I would like to make the whole label clickable.
Is there a way to do that?

Have you tried just moving onClick into CheckboxGroupLabel?
https://codesandbox.io/s/label-onclick-3ebkbi
import "./styles.css";
import * as Checkbox from "#radix-ui/react-checkbox";
import { CheckIcon } from "#radix-ui/react-icons";
export default function MyComponent() {
const onLabelClick = () => {
console.log("clicked label");
};
return (
<div>
<label onClick={onLabelClick} htmlFor="mycheckbox">
<Checkbox.Root className="checkbox" defaultChecked id="mycheckbox">
<Checkbox.Indicator className="indicator">
<CheckIcon />
</Checkbox.Indicator>
My checkbox label
</Checkbox.Root>
</label>
</div>
);
}

Related

Unable to extend react component in styled-component

I am trying to extent react component in styled-component and trying to add custom style on extended component but unable to see the style changes that I am applying
I have created a button component in /src/newbutton.js with following code
import styled from "styled-components";
const Button = styled.button`
background: ${props => props.primary ? "palevioletred" : "white"};
color: ${props => props.primary ? "white" : "palevioletred"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
export const NewButton = ({ className, children }) => {
return (
<Button primary>Primary</Button>
)
}
And extending and creating another button component with custom style in /src/custom-button.js with following code
import styled from "styled-components";
import { NewButton } from './button'
const ButtonWrapper = styled(NewButton)`
width: 100%;
color: red
`;
const ExtendedButton = ({ className, children }) => {
return (
<ButtonWrapper />
)
}
I have added the custom style like width: 100% & color: red but it is not applying on ExtendedButton. Infect colour and width is same as NewButton
You need to pass a className to your NewButton in order to customize it, using styled-components.
Styled components works by creating a unique className that associated with a component and its CSS.
export const NewButton = ({ className, children }) => {
return (
<Button className={className} primary>Primary</Button>
)
}
I am posting the complete working code for future reference based on #Flat Globe solution. And it is working fine as expected.
I have modified the Button component code just by adding className in /src/newbutton.js with following code
import styled from "styled-components";
const Button = styled.button`
background: ${props => props.primary ? "palevioletred" : "white"};
color: ${props => props.primary ? "white" : "palevioletred"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
export const NewButton = ({ className, children }) => {
return (
<Button primary className={className}>Primary</Button>
)
}
I have also modified the extended-button code by just passing the className in /src/custom-button.js. check the full code below
import styled from "styled-components";
import { NewButton } from './button'
const ButtonWrapper = styled(NewButton)`
width: 100%;
color: red
`;
const ExtendedButton = ({ className, children }) => {
return (
<ButtonWrapper className="extended-button"/>
)
}

React color background on event

I use the npm package use-dark-mode as the name implies, it makes it possible to change the theme to light or dark, The problem is that I want to change the background-color of some blocks when changing the theme to dark, and vice versa, return the old color when I switch to light mode, for example, my block background is orange, I switch to dark mode, it turns red and when I switch to light mode, it returns old orange
App.js
import React from 'react';
import './App.css'
import Content from "./components/Content/Content";
import Dark_Mode from "./components/Dark Mode/Dark_Mode";
const App = () => {
return(
<div>
<Dark_Mode />
<Content />
</div>
);
};
export default App;
Content.jsx
import React from 'react';
import './style.css'
const Content = () => {
return (
<>
<div className={"content_container"}>
<h3>Hello from React.JS</h3>
</div>
</>
);
};
export default Content;
Dark_Mode.jsx
import React from 'react';
import useDarkMode from 'use-dark-mode';
const DarkModeToggle = () => {
const darkMode = useDarkMode(false);
return (
<div>
<button type="button" onClick={darkMode.disable}>
☀
</button>
<button type="button" onClick={darkMode.enable}>
☾
</button>
</div>
);
};
export default DarkModeToggle;
style.css
#import '../../App.css';
.content_container {
margin: auto;
width: 500px;
max-width: 100%;
background: orange;
}
.content_container h3 {
text-align: center;
}
App.css
body.light-mode {
background-color: #fff;
color: #333;
transition: background-color 0.3s ease;
}
body.dark-mode {
background-color: #1a1919;
color: #999;
}
:root {
--color-orange: orange;
}
As you can see, I have App.css when the theme changes, it changes the background of the <body>, I still have Content.jsx when switching theme I want to change the background of the block with the className content_container which is connected to style.css, In addition, you may have noticed that I tried to use global styles, but I failed. Finally, I would like to show a screenshot on the site for a clear understanding of everything.
You could give the root element a class on theme change and use css variables in root, but be class specific:
Dark_mode.jsx:
function setTheme(themeName) {
document.documentElement.classList.remove('light-theme', 'dark-theme');
document.documentElement.classList.add(themeName);
}
const DarkModeToggle = () => {
const activateDarkTheme = () => setTheme('dark-theme');
const activateLightTheme = () => setTheme('light-theme');
return (
<div>
<button type="button" onClick={activateDarkTheme}>
☀
</button>
<button type="button" onClick={activateLightTheme}>
☾
</button>
</div>
);
};
Styles:
:root, // this is used for the default theme, will be overwritten by other styles with classes because of specifity
:root.dark-theme {
--color-bg: #000;
}
:root.light-theme {
--color-bg: #fff;
}
I found a more convenient solution! although it is my fault, I was a little inattentive and did not study the documentation of this package that I use in my project, here is a simple solution
Content.jsx
import './Content.css'
import useDarkMode from 'use-dark-mode';
export default function Content () {
const { value } = useDarkMode(false);
return <div>
<div className={value ? 'Dark_Mode' : 'Light_Mode'}>
<h3>Hello from React.JS</h3>
</div>
</div>
}
Content.css
.Dark_Mode {
margin: auto;
max-width: 100%;
width: 400px;
height: 275px;
background-color: orange;
}
.Light_Mode {
margin: auto;
max-width: 100%;
width: 400px;
height: 275px;
background-color: rgb(24, 106, 199);
}

Disabled button doesn't work in React JS if text color is specified

I would like to specify style(background and text color) of the button that will be disabled later in code.
button needs to look like this on render and like this after click
My code is
import React, { useState, useEffect } from "react";
import "./styles.css";
export default function App() {
const [loading, setLoading] = useState(false);
const handleClick = (e) => {
e.preventDefault();
setLoading(true);
};
return (
<div className="App">
<button disabled={loading} onClick={handleClick} className="btn">
{" "}
Click me
</button>
</div>
);
}
and Css
.btn {
width: 200px;
height: 50px;
background-color: blue;
/* color: white; */
}
.btn:hover {
cursor: pointer;
}
link to codesandbox
When I specify color of the text(white) disabled doesn't change color to grey( button doesn't look disabled), when text color is not defined, it's black and after click it's grey. Is there any way to define text color as white before click, and when button is clicked change color to grey? Because I need to make the button with blue background and white text on render. Thank you anyone who will help me.
Most of this can be done with CSS, though you'll need to add one more thing to your React component.
JS:
import React, { useState, useEffect } from "react";
import "./styles.css";
export default function App() {
const [loading, setLoading] = useState(false);
const handleClick = (e) => {
e.preventDefault();
setLoading(true);
};
return (
<div className="App">
<button disabled={loading} onClick={handleClick} className={`btn${loading ? ' disabled' : ''}`}>
{" "}
Click me
</button>
</div>
);
}
CSS
.btn {
width: 200px;
height: 50px;
background-color: blue;
/* color: white; */
}
.btn.disabled {
opacity: .65;
pointer-events: none;
}
.btn:hover {
cursor: pointer;
}
.btn:active {
color: green; // Or whatever style you want
}
EDIT: You can also use the :enabled and :disabled pseudo-selectors like the comment above said.

Want to target only one div at a time, the div which is hovered but not the other sibling div in ReactJS?

I am having a unique scenario but I am unable to understand this.
When I hover on one DIV then it selects both the sibling DIVS.
I do not want this behaviour.
I want to select only the DIV which is being hovered.
How can I achieve this in ReactJS ?.
The working code is shown below.
App.js
import React,{useState} from 'react';
import "./App.css";
const App = () => {
const [hover, setHover] = useState(false);
const texts = ["Arjun", "Andy"];
let cclass = hover ? "item itemHover":"item";
return (
<div className="wrapper">
{
texts.map((t, i) => (
<div className={cclass} key={i} onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}>
{t}
</div>
))
}
</div>
)
}
export default App;
App.css
.wrapper{
width: 60%;
margin: 10rem auto;
border: 1px solid;
display: flex;
}
.item{
width: 50%;
border: 1px solid grey;
height: auto;
padding: 2rem 3rem;
}
.itemHover{
background: grey;
}
The hover state in App is common for both divs. To make it work you need to
have hover state for each div separate. For this, create a new component TextDiv
import React, {useState} from "react";
import "./styles.css";
export default function TextDiv({t}) {
const [hover, setHover] = useState(false);
let cclass = hover ? "item itemHover":"item";
return (
<div className={cclass} onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}>
{t}
</div>
)
}
and change App.js file
import React, {useState} from "react";
import TextDiv from './TextDiv'
import "./styles.css";
export default function App() {
const texts = ["Arjun", "Andy"];
return (
<div className="wrapper">
{
texts.map((t, i) => (
<TextDiv t={t} key={i}/>
))
}
</div>
)
}
Can you do it with CSS? It's very simple with CSS. Just add this:
.item:hover{
background: grey;
}

React styled-components not applying styles to custom styled components

I'm using react-styled-components to style some custom components in my React/AntDesign application but the styles are not applied to my application.
When I tried reproducing the component in a clean codesandbox.io project the styles were applied successfully.
While some styled-components in my project do work this doesn't, what could be interfering with styled-components?
Here's the code:
import React from "react";
import "antd/dist/antd.css";
import styled from "styled-components";
import { FaMale, FaFemale, FaChild, FaUserFriends } from "react-icons/fa";
import { MdChildFriendly } from "react-icons/md";
import { Row, Col, Modal, Button } from 'antd';
class App extends React.Component {
state = { visible: false };
showModal = () => {
this.setState({
visible: true,
});
};
handleCancel = e => {
console.log(e);
this.setState({
visible: false,
});
};
ProductBtn = styled.div`
box-shadow: 0 0 15px rgba(0,0,0,0.1);
border: 1px solid #eee;
padding: 16px;
text-align: center;
border-radius: 5px;
cursor: pointer;
background-color: #fff
p {
margin-bottom: 0;
margin-top: 5px;
font-weight: bold;
}
`;
render() {
return (
<div>
<Button type="primary" onClick={this.showModal}>New Transaction</Button>
<Modal
title="New transaction"
visible={this.state.visible}
nOk={this.handleCancel}
onCancel={this.handleCancel}
>
<Row gutter={[16, 16]}>
<Col span={8}>
<this.ProductBtn onClick={this.handleProductClicked}>
<FaUserFriends style={{ fontSize: '24px' }} />
<p>Add couple</p>
<small>$70.00</small>
</this.ProductBtn>
</Col>
...
</Row>
</Modal>
</div>
)
}
}
export default App;
This is how it should look and how it looks in CodeSandbox:
This is how it looks in my application, without the widget/button-like styling on the ProductBtn styled component:

Categories

Resources