NextJs passing in prop as className - html

I'm having trouble with passing a prop to a className and am wondering if it is even possible.
For example, let's say category is passed into the function and category is "category1". In the className can I call styles.category to get styles.category1?
export const function ({category}) => {
return (
<button className={styles.category}></button>
)
}
.category1 {
background: #FF4646 0% 0% no-repeat padding-box;
opacity: 1;
width: 200px;
height: 200px;
outline: none;
border: none;
font: url('../../public/fonts/AirbnbCerealBlack.woff');
font-size: 20px;
font-weight:900;
color: black;
}
.category2 {
background: #4EEA9C 0% 0% no-repeat padding-box;
opacity: 1;
width: 270px;
height: 270px;
outline: none;
border: none;
font: url('../../public/fonts/AirbnbCerealBlack.woff');
font-size: 20px;
font-weight:900;
}

You can use it as styles[category] to set the className on your button.
export const function ({ category }) =>{
return (
<button className={styles[category]}></button>
)
}

Due to the fact that you unpack the argument, you should just be able to do className={category}.

Related

Circular cursor covers the text

I'm creating a circular cursor, and when it overlaps with the text, I want it to have the white background, but to leave the text. Now, however, it covers the text. I tried using z-index but nothing happened.
my html:
<div class="cursor">
</div>
<section class="hero-text">
<div class="hero-text-content">
<h1 class="cursor-scale">Привет!</h1>
<h2 id="hi">That's how we say 'Hi' in Russian</h2>
</div>
</section>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.3/gsap.min.js"></script>
<script src="static/js/main.js"></script>
my css:
.hero-text {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
font-family: 'Poppins', sans-serif;
cursor: none;
}
.hero-text h1 {
font-size: 8vw;
line-height: 1;
font-weight: 700;
background-image: linear-gradient(132deg,
#3ff4af 0%, #d8e614 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
z-index: 9999;
}
.hero-text h2 {
font-size: 5vw;
color: black;
display: inline-flex;
z-index: 9999;
}
.cursor {
position: fixed;
width: 40px;
height: 40px;
border: 2px solid pink;
border-radius: 50%;
margin-left: -20px;
margin-top: -20px;
transition: transform .3s ease;
pointer-events: none;
transform-origin: center center;
}
.grow {
transform: scale(10);
background: white;
/*mix-blend-mode: difference;*/
border: none;
}
my js:
function elementsOverlap(el1, el2) {
const domRect1 = el1.getBoundingClientRect();
const domRect2 = el2.getBoundingClientRect();
return !(
domRect1.top > domRect2.bottom ||
domRect1.right < domRect2.left ||
domRect1.bottom < domRect2.top ||
domRect1.left > domRect2.right
);
}
var cursor = document.querySelector('.cursor'),
cursorScale = document.querySelectorAll('.cursor-scale'),
hi = this.document.querySelector('#hi'),
mouseX = 0,
mouseY = 0
gsap.to({}, 0.016, {
repeat: -1,
onRepeat: function() {
gsap.set(cursor, {
css: {
left: mouseX,
top: mouseY
}
})
}
})
window.addEventListener('mousemove', function (e) {
mouseX = e.clientX
mouseY = e.clientY
})
cursorScale.forEach(link => {
link.addEventListener('mouseleave', () => {
cursor.classList.remove('grow');
cursor.classList.remove('grow-small')
});
link.addEventListener('mousemove', () => {
cursor.classList.add('grow');
if (link.classList.contains('small')) {
cursor.classList.remove('grow');
cursor.classList.add('grow-small')
}
})
})
my result:
I'm doing it from the tutorial, and there they use mix-blend-mode: difference, but what I need is that when the cursor is white, it reveals the black text (<h2>), but when the mix-blend-mode is used, the text is white, so I decided to delete this property, but now the cursor is overlapped.
Thanks for any help!
mix-blend-mode: difference; makes sense over here.
Is this not what you require? Please specify what you're looking for.
From what I understood from the description, you want the h2 text to only be visible within the large cursor.
In that case, clip-path might help.
Alternatively, adding invert filter with mix-blend-mode gives this result.
.hero-text h2 {
color: white;
filter: invert(100%);
}
.grow {
background: white;
mix-blend-mode: difference;
}

Z-index does not works

Codesandbox: https://codesandbox.io/s/colorful-tooltip-antd-4-21-0-forked-dctrww?file=/Tooltip.js
I can not press {children} element because tooltip has an padding-bottom. I tried in dev tools browser set z-index on children but this does not helps. How should I set children to be always 'above' tooltip padding - so i will able to click on {children}
Tooltip:
import React from "react";
import "antd/dist/antd.css";
import "./index.css";
import { Tooltip } from "antd";
import styled from "styled-components";
export const Tool = ({ children, title, left, top }) => (
<Custom
visible
left={left}
top={top}
title={title}
getPopupContainer={(triggerNode) => triggerNode}
>
<Children>{children}</Children>
</Custom>
);
const Children = styled.div`
position: relative;
display: inline;
> * {
position: relative;
display: inline;
}
`;
const Custom = styled(Tooltip)`
.ant-tooltip-arrow {
display: none;
}
.ant-tooltip {
left: ${(props) => props.left || 0} !important;
top: ${(props) => props.top || "-70px"} !important;
}
.ant-tooltip-content {
position: relative;
overflow-x: hidden;
overflow-y: visible;
padding-bottom: 20px;
display: inline-block;
}
.ant-tooltip-inner {
padding: 10px 15px;
background: white;
top: 0;
display: inline-block;
border-radius: 10px;
border: 3px solid red;
border-bottom-right-radius: 0px;
z-index: 2;
max-width: 200px;
box-shadow: none;
color: black;
word-wrap: break-word;
}
.ant-tooltip-content:before {
content: "";
position: absolute;
width: 25px;
height: 25px;
background: white;
bottom: 14px;
right: -6px;
transform: rotate(25deg);
border-bottom: 3px solid red;
}
.ant-tooltip-content:after {
content: "";
width: 3px;
background: red;
height: 50%;
position: absolute;
right: 0;
bottom: 13px;
}
`;
import React from "react";
import "antd/dist/antd.css";
import "./index.css";
import { Tool } from "./Tooltip";
const App = () => {
return (
<Tool title="Tooltip">
<p>Button</p>
</Tool>
);
};
export default App;
Keep in mind that the antd library also has its own styles that it adds in the DOM, so I recommend starting codesandbox and checking there

multiple toggle of classlist onclick

good day everyone this is my first post on this site, i am wondering if it's possible to have multiple classList, and will be toggle each click on the element and loop after the last classList
here's my css:
:root {
--primCol: #fff;
}
.dark-theme{
--primCol: #9A4747;
}
body {
display: inline-flex;
width: 100vw;
height: 100vh;
background-color: var(--primCol);
margin: 0;
padding: 0;
justify-content: center;
align-items: center;
transition: all .5s;
}
#wrapper {
transition: all .7s;
border-radius: 5px;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
background-color: var(--primCol);
width: 300px;
height: 300px;
box-shadow: 0 0 10px #B8B8B8;
}
#wrapper:active {
transform: scale(1.3);
}
my jQuery:
$(document).ready(() => {
$('#wrapper').click( () => {
document.body.classList.toggle("dark-theme");
});
});
Try this. Then, use variables from your ::root to give styles to elements.
$('#theme-switcher').click(function() {
document.body.classList.toggle("dark-theme");
});
:root {
--primCol: #fff;
}
::root.dark-theme {
--primCol: #9A4747;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="theme-switcher">Toggle Theme</button>

React app stops working when I add textfield

I'm a beginner in React and I'm trying to create a web application's front end UI part and I'm trying to add a text field in the box that I've added but every time i do that, the app does not render anything other than a blank color filled to the screen.
without the text field:
with the text field:
My code:
App.js:
import React, { Component} from 'react'
import 'bootstrap/dist/css/bootstrap.min.css';
import './App.css';
import Text1 from './Text1';
import Helmet from 'react-helmet';
import HRLOGO from './images/logo.png';
import ABCLOGO from './images/Group 20399.png';
export default class App extends Component
{
state = {};
render()
{
return (
<div className="hr">
<div>
<img src={HRLOGO} alt="" className="container-div"/>
</div>
<div>
<img src={ABCLOGO} alt="" className="container-div2"/>
</div>
<Helmet>
<style>{'body { background-color: #2d4250; }'}</style>
</Helmet>
<div>
<h1 className="InvoiceStyle">Invoice List</h1>
</div>
<div className="Rectangle">
</div>
<div className="search">
<Text1></Text1>
</div>
<footer className="Privacy">
<p>
Privacy Policy
| ©Highradius Corporation. All rights reserved.
</p>
</footer >
</div>
);
}
}
The css File App.css:
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
margin:auto;
}
#media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
margin:auto;
}
}
.Rectangle {
width: 2000px;
height: 570px;
background: #2e4551;
position: fixed;
top: 130px;
}
.container-div {
display: flex;
height: 50px;
width: 235px;
position: fixed;
top: 8px;
right: 600px;
text-align: center;
}
.InvoiceStyle {
display: flex;
color: #fff;
font-family: 'Open Sans';
font-size: x-large;
position: fixed;
top: 90px;
left: 25px;
}
.container-div2 {
display: flex;
height: 50px;
width: 312px;
position: fixed;
top: 7px;
left: 15px;
}
.Privacy {
display: flex;
position: fixed;
top: 720px;
left: 600px;
color: white;
}
.search {
position: fixed;
top: 155px;
left: 690px;
width: 16%;
height: 40px;
background-color: #fff;
border: none;
border-top-left-radius: 10px !important;
border-bottom-left-radius: 10px !important;
border-top-right-radius: 10px !important;
border-bottom-right-radius: 10px !important;
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: rgb(11, 68, 253);
}
.App-link {
color: #ff0000;
}
#keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
Text1.js:
import TextField from "#mui/material/TextField";
const Text1 = () => {
return (
<form noValidate autoComplete = "off">
<TextField id="outlined-basic" label="Outlined" variant="outlined" />
</form>
);
}
export default Text1;
Like the page just goes blank, How do I fix this?
Edit:
Browser Console:
The primary error appears to be Cannot read properties of null (reading 'useContext'). React has the concept of ambient Context to simplify passing values down through your Component hierarchy. In this particular case, the TextField component has been assigned a variant theme. In order to lookup and apply that theme, it is expecting to find somewhere in it's parent component hierarchy a ThemeProvider. https://mui.com/material-ui/customization/theming/#theme-provider
Solution: Add a ThemeProvider as a parent component within the render section of your App component.
function render() {
return (<ThemeProvider ...>
...
</ThemeProvider>);
}
After you do this, the TextField component should be able to properly retrieve the context via it's call to the useContext hook. If you run into further issues, make sure you carefully review the basic installation and usage documentation for that library: https://mui.com/material-ui/getting-started/usage/

In React, how to create a bubble head on top of the thumb of a range slider

var slider = document.getElementById("myRange");
var output = document.getElementById("demo");
output.innerHTML = slider.value;
slider.oninput = function() {
output.innerHTML = this.value;
}
.slidecontainer {
width: 100%;
}
.slider {
-webkit-appearance: none;
width: 100%;
height: 15px;
border-radius: 5px;
background: #d3d3d3;
outline: none;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
}
.slider:hover {
opacity: 1;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 25px;
height: 25px;
border-radius: 50%;
background: #04AA6D;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 25px;
height: 25px;
border-radius: 50%;
background: #04AA6D;
cursor: pointer;
}
<h1>Round Range Slider</h1>
<div class="slidecontainer">
<input type="range" min="1" max="100" value="50" class="slider" id="myRange" style="width: 200px">
<p>Value: <span id="demo"></span></p>
</div>
The code above is a range slider made in HTML.
This is example of how it could look.
For the solution, first need to get the input range, then the width of step, because of the range will be greater than your maximum value, the bubble can't to place by center to the thumb. Finally multiply range and step to get the bubble position. The bubble better create with the svg create bubble. For styling the range input link
function App() {
const [range, setRange] = React.useState(0);
const [step, setStep] = React.useState(0);
const ref = React.useRef(null);
const getRange = (ev) => {
setRange(ev.target.value);
};
React.useEffect(() => {
const rangeLinePadding = 16;
const calcStep =
(ref.current.offsetWidth - rangeLinePadding) / ref.current.max;
setStep(calcStep);
}, []);
return ( <div className="App">
<h1> Range Slider </h1>
<div className="slider">
<input
type="range"
id="range"
min="0"
max="100"
value={range}
onChange={getRange}
ref={ref}
/>
<label
htmlFor="range"
style={{
transform: `translateX(${range * step}px)`,
}}>
<span> {range} </span>
<svg viewBox="0 0 15 18">
<path d="M14,7a7,7,0,0,1-2,4.87L7.72,16.35a1,1,0,0,1-1.44,0L2,11.87A6.93,6.93,0,0,1,0,7,7,7,0,0,1,14,7Z" />
</svg>
</label>
</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render( <
App / > ,
rootElement
);
.App {
display: flex;
flex-direction: column;
align-items: center;
gap: 50px;
font-family: sans-serif;
text-align: center;
}
.slider {
width: 200px;
display: flex;
flex-direction: column;
position: relative;
padding: 0 10px;
}
label[for='range'] {
width: 35px;
height: 40px;
position: absolute;
top: -45px;
left: 0;
color: hsl(0, 0%, 0%);
pointer-events: none;
}
label[for='range'] span {
position: absolute;
top: 8px;
left: 50%;
text-align: center;
font-size: 0.9em;
font-weight: bold;
transform: translateX(-50%);
z-index: 5;
}
label[for='range'] svg {
height: inherit;
position: relative;
left: 1px;
fill: hsl(207, 90%, 77%);
z-index: -1;
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I know this is old, but I'm posting it here because I ran into the same problem. While Anton's answer is fine if your custom range component always has the minimum of 0, it breaks dow when that is not the case. So if you have a range with minimum 2 and maximum 10, the bubble will not be aligned properly.
To solve that, in the calcThumbStep we need to change the calculation to account for minimum
React.useEffect(() => {
const rangeLinePadding = 16;
const calcStep =
(ref.current.offsetWidth - rangeLinePadding) / (ref.current.max - ref.current.min);
setStep(calcStep);
}, []);
Later in the input element itself, in the translate calculation, we need to update it to account for when the element is at the left most position with a non 0 minimum.
style={{
transform: `translateX(${value * thumbStep - thumbStep * min}px)`,
}}
For a full code reference check out Anton's answer and just swap in my changes.
Hope this helps someone out there.