I'm trying to toggle between two classes dark mode and normal mode.
THis is the vanilla js eventlistener
const modeSwitch = document.querySelector('.mode-switch');
modeSwitch.addEventListener('click', () => {
document.documentElement.classList.toggle('dark');
modeSwitch.classList.toggle('active');
});
This is the button that when clicked on, switches between the two modes. how can I achieve this with react
const [active, setActive] = useState(false)
const handleToggle = () => {
setActive(!active)
}
return (
<button className="mode-switch" title="Switch Theme" onClick={handleToggle}>
<svg className="moon" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" width="24" height="24" viewBox="0 0 24 24">
<defs></defs>
<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"></path>
</svg>
</button>
)
In this case you could use useRef:
const [active, setActive] = useState(false)
const modeRef = useRef();
const handleToggle = () => {
modeRef.current.classList.toggle("dark")
}
return (
<button ref={modeRef} className="mode-switch" title="Switch Theme" onClick={handleToggle}>
<svg className="moon" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" width="24" height="24" viewBox="0 0 24 24">
<defs></defs>
<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"></path>
</svg>
</button>
)
Related
I have a header with Logo, on left side, page title - in the middle, and user menu, on the right. Currently I'm displaying a SVG next to each page title. For example, on page /organizations I display this:
After that I've added a SVG that shows when I hover on the element (it's the same SVG, but filled)
How could I make transition between these two smooth? I'm using Tailwind for styling and tried adding transition-all to almost every class but that sadly didn't work.
This is the code responsible for switching between the SVGs:
const [hover, setHover] = React.useState(false);
const handleMouseOver = () => {
setHover(true);
};
const handleMouseLeave = () => {
setHover(false);
};
return (
...
<div className="w-1/2 flex justify-center">
<Link
to={getModuleInfo(pathname, t, organization).url}
className="max-w-fit flex items-center gap-2"
prefetch="intent"
>
<div
className="flex items-center gap-2"
onMouseOver={handleMouseOver}
onMouseLeave={handleMouseLeave}
>
<>
{hover
? getModuleInfo(pathname, t, organization).logoHover
: getModuleInfo(pathname, t, organization).logo}
</>
<h5 className="organizations text-md md:text-2xl font-sans font-normal text-center text-colublue-500">
{getModuleInfo(pathname, t, organization).title}
</h5>
</div>
</Link>
</div>
...
)
UPD: to make things more clear, these would be 2 SVG examples that I would like to transition between:
And this are the <svg> for them:
// Unfilled SVG
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.41421 2.58579C8.78929 2.21071 9.29799 2 9.82843 2H18C18.5304 2 19.0391 2.21071 19.4142 2.58579C19.7893 2.96086 20 3.46957 20 4V20C20 20.5304 19.7893 21.0391 19.4142 21.4142C19.0391 21.7893 18.5304 22 18 22H6C5.46957 22 4.96086 21.7893 4.58579 21.4142C4.21071 21.0391 4 20.5304 4 20V7.82843C4 7.29799 4.21071 6.78929 4.58579 6.41421L8.41421 2.58579Z" stroke="#052141" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 2V7C10 7.55228 9.55228 8 9 8H4.5" stroke="#052141" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
// Filled SVG
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.82843 1C9.03278 1 8.26972 1.31607 7.70711 1.87868L3.87868 5.70711C3.31607 6.26972 3 7.03278 3 7.82843V20C3 20.7957 3.31607 21.5587 3.87868 22.1213C4.44129 22.6839 5.20435 23 6 23H18C18.7956 23 19.5587 22.6839 20.1213 22.1213C20.6839 21.5587 21 20.7957 21 20V4C21 3.20435 20.6839 2.44129 20.1213 1.87868C19.5587 1.31607 18.7956 1 18 1H9.82843ZM16.7071 9.29289C17.0976 9.68342 17.0976 10.3166 16.7071 10.7071L11.3738 16.0404C10.9832 16.431 10.3501 16.431 9.95956 16.0404L7.29289 13.3738C6.90237 12.9832 6.90237 12.3501 7.29289 11.9596C7.68342 11.569 8.31658 11.569 8.70711 11.9596L10.6667 13.9191L15.2929 9.29289C15.6834 8.90237 16.3166 8.90237 16.7071 9.29289Z" fill="#052141"/>
</svg>
With plain CSS and SVG, you can do this with opacity and transition.
.filled {
opacity: 0;
transition: opacity 0.3s;
}
svg:hover .filled {
opacity: 1;
}
<svg width="96" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.41421 2.58579C8.78929 2.21071 9.29799 2 9.82843 2H18C18.5304 2 19.0391 2.21071 19.4142 2.58579C19.7893 2.96086 20 3.46957 20 4V20C20 20.5304 19.7893 21.0391 19.4142 21.4142C19.0391 21.7893 18.5304 22 18 22H6C5.46957 22 4.96086 21.7893 4.58579 21.4142C4.21071 21.0391 4 20.5304 4 20V7.82843C4 7.29799 4.21071 6.78929 4.58579 6.41421L8.41421 2.58579Z" stroke="#052141" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 2V7C10 7.55228 9.55228 8 9 8H4.5" stroke="#052141" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path class="filled" d="M9.82843 1C9.03278 1 8.26972 1.31607 7.70711 1.87868L3.87868 5.70711C3.31607 6.26972 3 7.03278 3 7.82843V20C3 20.7957 3.31607 21.5587 3.87868 22.1213C4.44129 22.6839 5.20435 23 6 23H18C18.7956 23 19.5587 22.6839 20.1213 22.1213C20.6839 21.5587 21 20.7957 21 20V4C21 3.20435 20.6839 2.44129 20.1213 1.87868C19.5587 1.31607 18.7956 1 18 1H9.82843ZM16.7071 9.29289C17.0976 9.68342 17.0976 10.3166 16.7071 10.7071L11.3738 16.0404C10.9832 16.431 10.3501 16.431 9.95956 16.0404L7.29289 13.3738C6.90237 12.9832 6.90237 12.3501 7.29289 11.9596C7.68342 11.569 8.31658 11.569 8.70711 11.9596L10.6667 13.9191L15.2929 9.29289C15.6834 8.90237 16.3166 8.90237 16.7071 9.29289Z" fill="#052141"/>
</svg>
You could also use css variables to transition between the design states.
Similar to #ksav's this approach will also need to combine both svgs.
This way we can render the icon with more design variations.
let icon = document.querySelector('.iconTrans');
function toggleState() {
icon.classList.toggle('active')
}
svg {
border: 1px solid #ccc;
overflow: visible;
width: 10em;
}
svg path {
transition: 1s;
}
.iconTrans {
--strokeColor: #052141;
--strokeWidth: 2px;
--opacity1: 1;
--opacity2: 0;
--fillColor: #052141;
}
.active {
--strokeColor: #052141;
--strokeWidth: 0px;
--opacity1: 0;
--opacity2: 1;
--fillColor: #ccc;
}
<p><button id="btnToggle" onclick="toggleState()">Toggle state</button></p>
<svg class="iconTrans" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path class="paper" d="M8.41421 2.58579C8.78929 2.21071 9.29799 2 9.82843 2H18C18.5304 2 19.0391 2.21071 19.4142 2.58579C19.7893 2.96086 20 3.46957 20 4V20C20 20.5304 19.7893 21.0391 19.4142 21.4142C19.0391 21.7893 18.5304 22 18 22H6C5.46957 22 4.96086 21.7893 4.58579 21.4142C4.21071 21.0391 4 20.5304 4 20V7.82843C4 7.29799 4.21071 6.78929 4.58579 6.41421L8.41421 2.58579Z
M10 2V7C10 7.55228 9.55228 8 9 8H4.5" style="stroke:var(--strokeColor); stroke-width:var(--strokeWidth); opacity:var(--opacity1)" stroke-linecap="round" stroke-linejoin="round" />
<path class="paperCheck" d="M9.82843 1C9.03278 1 8.26972 1.31607 7.70711 1.87868L3.87868 5.70711C3.31607 6.26972 3 7.03278 3 7.82843V20C3 20.7957 3.31607 21.5587 3.87868 22.1213C4.44129 22.6839 5.20435 23 6 23H18C18.7956 23 19.5587 22.6839 20.1213 22.1213C20.6839 21.5587 21 20.7957 21 20V4C21 3.20435 20.6839 2.44129 20.1213 1.87868C19.5587 1.31607 18.7956 1 18 1H9.82843Z
M16.7071 9.29289C17.0976 9.68342 17.0976 10.3166 16.7071 10.7071L11.3738 16.0404C10.9832 16.431 10.3501 16.431 9.95956 16.0404L7.29289 13.3738C6.90237 12.9832 6.90237 12.3501 7.29289 11.9596C7.68342 11.569 8.31658 11.569 8.70711 11.9596L10.6667 13.9191L15.2929 9.29289C15.6834 8.90237 16.3166 8.90237 16.7071 9.29289Z" style="fill:var(--fillColor); opacity:var(--opacity2); " />
</svg>
I have one common component for which I want to change its color property to use it at other place.
const ViewAllIcon = (props) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 26 27"
{...props}
>
<path
fill="var(--primary)"
d="M13 0C5.832 0 0 5.86 0 13.061c0 7.202 5.832 13.062 13 13.062s13-5.86 13-13.062C26 5.86 20.168 0 13 0z"
/>
<path
fill="#FFF"
d="M14.764 13.061l-4.437-4.726c-.48-.512-.48-1.344 0-1.856s1.261-.512 1.742 0l5.357 5.708c.454.483.454 1.266 0 1.749l-5.357 5.707c-.48.512-1.261.512-1.742 0-.48-.512-.48-1.343 0-1.855l4.437-4.727z"
/>
</svg>
);
export default ViewAllIcon;
This is common component having primary blue and white color.
<ViewAllIcon className="ml8" fill="white" />
I am using it to change the fill color to white and green.
change fill value to "currentColor" and than pass color var to component.
ViewAllIcon({ color: 'var(--primary)' })
or
<ViewAllIcon color={'var(--primary)'} />
const ViewAllIcon = (props) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 26 27"
{...props}
>
<path
fill="currentColor"
d="M13 0C5.832 0 0 5.86 0 13.061c0 7.202 5.832 13.062 13 13.062s13-5.86 13-13.062C26 5.86 20.168 0 13 0z"
/>
<path
fill="currentColor"
d="M14.764 13.061l-4.437-4.726c-.48-.512-.48-1.344 0-1.856s1.261-.512 1.742 0l5.357 5.708c.454.483.454 1.266 0 1.749l-5.357 5.707c-.48.512-1.261.512-1.742 0-.48-.512-.48-1.343 0-1.855l4.437-4.727z"
/>
</svg>
);
export default ViewAllIcon;
You could put the props directly to fill attribute
Something like this:
const ViewAllIcon = (props) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 26 27"
{...props}
>
<path
fill={props.fill} // <--- UPDATE HERE!
d="M13 0C5.832 0 0 5.86 0 13.061c0 7.202 5.832 13.062 13 13.062s13-5.86 13-13.062C26 5.86 20.168 0 13 0z"
/>
<path
fill="#FFF"
d="M14.764 13.061l-4.437-4.726c-.48-.512-.48-1.344 0-1.856s1.261-.512 1.742 0l5.357 5.708c.454.483.454 1.266 0 1.749l-5.357 5.707c-.48.512-1.261.512-1.742 0-.48-.512-.48-1.343 0-1.855l4.437-4.727z"
/>
</svg>
);
export default ViewAllIcon;
Working Example:
I am making a side nav for which I need to add the left border to the current tab How can I achieve this using state by passing a boolean value to the Child SideNavItem class as a prop and the change it on every tab change.
Here is My code for the parent SideNav class
Here I am using an if-else condition to check for the current location and the pass that is a prop to the Child class. But Right now both the Home and My Profile is getting the side border.
import { NavLink } from "react-router-dom";
import SideNavItems from "./SideNavItems";
import React, {useState} from 'react';
const HomeIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-8 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
/>
</svg>
);
const ProfileIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-8 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
/>
</svg>
);
const PointIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-8 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"
/>
</svg>
);
const SupportIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-8 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
/>
</svg>
);
const ContributeIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-8 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"
/>
</svg>
);
const SideNav = (): JSX.Element => {
let [active, setActive] = useState(true);
let isActive = (currentPath: any, thisPath: any) => {
if (currentPath===thisPath) {
setActive(true)
} else {
setActive(false);
}
return active;
}
const resetState = () => {
setActive(false);
};
return (
<div className="sidebar mt-5">
<div className="logo ml-2">
<img
alt="logo"
src={require("../assets/images/logo.png").default}
/>
</div>
<NavLink to="/"><SideNavItems active={() => isActive(window.location.pathname, "/")} icon={HomeIcon} text={"Home"}/></NavLink>
<NavLink to="/profile"><SideNavItems active={() => isActive(window.location.pathname, "/profile")} icon={ProfileIcon} text={"My Profile"}/></NavLink>
<SideNavItems active={""} icon={PointIcon} text={"Daily Points"}/>
<SideNavItems active={""} icon={SupportIcon} text={"Support"}/>
<SideNavItems active={""} icon={ContributeIcon} text={"Contribute"}/>
</div>
);
};
export default SideNav;
Here is the code for Child Class
import React from "react";
type Props = {
active: any;
text: string;
icon: any;
};
const SideNavItems: React.FC<Props> = ({active, icon, text }) => (
<div className={`flex items-center cursor-pointer hover:text-red-400 transition duration-100 ease-in-out ${active ? ` text-red-400 border-l-4 border-red-400` : ``}`}>
<div className="icon p-5">{icon}</div>
<h2 className="font-extrabold text-xl mr-5">{text}</h2>
</div>
);
export default SideNavItems;
Part of the confusion you're facing here is due to the fact that calling setActive in the isActive function doesn't immediately change the value of the active variable, and since you are returning the active variable immediately, you are actually returning the previous value active, not the intended value.
In fact, you probably don't need to save the value of active in a component state variable:
const SideNav = (): JSX.Element => {
return (
<div className='sidebar mt-5'>
<div className='logo ml-2'>
<img alt='logo' src={require('../assets/images/logo.png').default} />
</div>
<NavLink to='/'>
<SideNavItems
active={window.location.pathname === '/'}
icon={HomeIcon}
text={'Home'}
/>
</NavLink>
<NavLink to='/profile'>
<SideNavItems
active={window.location.pathname === '/profile'}
icon={ProfileIcon}
text={'My Profile'}
/>
</NavLink>
<SideNavItems active={''} icon={PointIcon} text={'Daily Points'} />
<SideNavItems active={''} icon={SupportIcon} text={'Support'} />
<SideNavItems active={''} icon={ContributeIcon} text={'Contribute'} />
</div>
);
};
export default SideNav;
or if you're using react router, you can use the useLocation hook to make sure the component always re-renders when the path changes:
import { useLocation } from 'react-router-dom';
const SideNav = (): JSX.Element => {
const { pathname: currentPath } = useLocation();
return (
<div className='sidebar mt-5'>
<div className='logo ml-2'>
<img alt='logo' src={require('../assets/images/logo.png').default} />
</div>
<NavLink to='/'>
<SideNavItems
active={currentPath === '/'}
icon={HomeIcon}
text={'Home'}
/>
</NavLink>
<NavLink to='/profile'>
<SideNavItems
active={currentPath === '/profile'}
icon={ProfileIcon}
text={'My Profile'}
/>
</NavLink>
<SideNavItems active={''} icon={PointIcon} text={'Daily Points'} />
<SideNavItems active={''} icon={SupportIcon} text={'Support'} />
<SideNavItems active={''} icon={ContributeIcon} text={'Contribute'} />
</div>
);
};
export default SideNav;
The website have a button called (svgAdd) where everytime I click this button it's supposed to add a point to the listBody div. but it is not working I tried a lot of ways but nothing worked, and if your thinking about using += point then it will remove the value of the textarea everytime I add a point to the listbody.
let count = 0;
$(`#svgNew`).click(function() {
let point =
`
<div class="point d-flex justify-content-between align-items-center" id="point">
<div class="pointTxt" id="pointTxt">
<p class="list-font">Enter Your Text</p>
<textarea id="txtA" cols="30" rows="10"></textarea>
</div>
<div class="pointIcon${count}" id="pointIcon">
</div>
</div>
`;
let list =
`
<div class="list col-lg-4" id="list${count}">
<div class="listHead d-flex justify-content-between align-items-center">
<div class="listHeadSet" id="listHeadSet${count}">
<svg xmlns="http://www.w3.org/2000/svg" class="list-svg" id="svgAdd${count}" width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
<svg xmlns="http://www.w3.org/2000/svg" class="list-svg" id="svgDelete${count}" width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-trash"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>
<svg xmlns="http://www.w3.org/2000/svg" class="list-svg" id="svgRemove${count}" width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-minus"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="9" y1="15" x2="15" y2="15"></line></svg>
</div>
<div class="listHeadTitle" id="listHeadTitle${count}">
<h1 class="titleH list-font" id="titleH${count}">Title</h1>
<input type="text" class="list-font titleInp" id="titleInp${count}" aria-label="Default" autocomplete="off" placeholder="Enter Title">
</div>
<div class="listHeadIcons">
<svg xmlns="http://www.w3.org/2000/svg" class="list-svg" id="svgEdit${count}" width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2"><path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path></svg>
<svg xmlns="http://www.w3.org/2000/svg" class="list-svg" id="svgSet${count}" width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-sliders"><line x1="4" y1="21" x2="4" y2="14"></line><line x1="4" y1="10" x2="4" y2="3"></line><line x1="12" y1="21" x2="12" y2="12"></line><line x1="12" y1="8" x2="12" y2="3"></line><line x1="20" y1="21" x2="20" y2="16"></line><line x1="20" y1="12" x2="20" y2="3"></line><line x1="1" y1="14" x2="7" y2="14"></line><line x1="9" y1="8" x2="15" y2="8"></line><line x1="17" y1="16" x2="23" y2="16"></line></svg>
</div>
</div>
<div class="listBody${count}" id="listBody${count}"></div>
</div>
`;
$(`.lists`).append(list);
const listx = document.querySelector(`#list${count}`);
const svgAdd = document.querySelector(`#svgAdd${count}`);
const svgDelete = document.querySelector(`#svgDelete${count}`);
const svgRemove = document.querySelector(`#svgRemove${count}`);
const listHeadTitle = document.querySelector(`#listHeadTitle${count}`);
const titleH = document.querySelector(`#titleH${count}`);
const titleInp = document.querySelector(`#titleInp${count}`);
const svgEdit = document.querySelector(`#svgEdit${count}`);
const svgSet = document.querySelector(`#svgSet${count}`);
const listHeadSet = document.querySelector(`#listHeadSet${count}`);
const listBody = document.querySelector(`#listBody${count}`);
let titleArr = [];
let text = "";
svgEdit.addEventListener("click", ()=> {
titleH.classList.toggle(`hidden`);
titleInp.classList.toggle(`show`);
let inpValue = titleInp.value;
if (inpValue.length == 0) titleH.innerHTML = titleArr[titleArr.length];
else if (inpValue.length <= 15) titleH.innerHTML = inpValue; titleArr.push(titleInp.value);
});
svgSet.addEventListener("click", ()=> {
listHeadTitle.classList.toggle(`hidden`);
svgEdit.classList.toggle(`hidden`);
listHeadSet.classList.toggle(`show`);
});
svgRemove.addEventListener("click", ()=> {listx.remove()});
svgAdd.addEventListener("click", ()=> {
$(`#listBody${count}`).append(point);
})
count++;
});
Why not completely use Jquery for your element selection also. With that you do not need to use "addEventListener"
const listx = $(`#list${count}`);
const svgAdd = $(`#svgAdd${count}`);
const svgDelete = $(`#svgDelete${count}`);
const svgRemove = $(`#svgRemove${count}`);
const listHeadTitle = $(`#listHeadTitle${count}`);
const titleH = $(`#titleH${count}`);
const titleInp = $(`#titleInp${count}`);
const svgEdit = $(`#svgEdit${count}`);
const svgSet = $(`#svgSet${count}`);
const listHeadSet = $(`#listHeadSet${count}`);
const listBody = $(`#listBody${count}`);
let titleArr = [];
let text = "";
svgEdit.on("click", ()=> {
titleH.toggleClass(`hidden`);
titleInp.toggleClass(`show`);
let inpValue = titleInp.value;
if (inpValue.length == 0) titleH.innerHTML = titleArr[titleArr.length];
else if (inpValue.length <= 15) titleH.innerHTML = inpValue;
titleArr.push(titleInp.value);
});
svgSet.on("click", ()=> {
listHeadTitle.toggleClass(`hidden`);
svgEdit.toggleClass(`hidden`);
listHeadSet.toggleClass(`show`);
});
svgRemove.on("click", ()=> {listx.remove()});
svgAdd.on("click", ()=> {
$(`#listBody${count}`).append(point);
})
count++;
I have two SVG icons I'm importing within my react application using "react-svg-loader"
The icons are imported as components with their own paths yet the output is the same for which ever icon is first in the code.
Why is this happening and how can I fix this?
Here is my code:
import React, { Component } from 'react';
import Navigation from '../Navigation/index.js';
import MainLogo from '../MainLogo/index.js';
import Search from '../Search/index.js';
import './index.css'; // styles from
import Logo from '../../assets/svg/logos/Voo_Main.svg';
import SearchIcon from '../../assets/svg/icons/search.svg';
export default class Header extends Component {
render() {
const { navItems } = this.props;
return (
<header className="header">
<SearchIcon />
<Logo />
</header>
);
}
};
Here is the output:
Here is my loader within my webpack config:
// react-svg-loader
// https://www.npmjs.com/package/react-svg-loader
{
test: /\.svg$/,
use: [
{
loader: "babel-loader",
},
{
loader: "react-svg-loader",
options: {
jsx: true, // true outputs JSX tags
},
},
],
},
Here is the code for the SVG icons from the DOM:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
<defs>
<path id="a" d="M14.5 16A6.508 6.508 0 0 1 8 9.5C8 5.916 10.916 3 14.5 3S21 5.916 21 9.5 18.084 16 14.5 16m0-15C9.813 1 6 4.813 6 9.5c0 1.983.688 3.807 1.832 5.254l-6.539 6.539a.999.999 0 1 0 1.414 1.414l6.539-6.539A8.443 8.443 0 0 0 14.5 18c4.687 0 8.5-3.813 8.5-8.5C23 4.813 19.187 1 14.5 1"></path>
</defs>
<g fill="none" fill-rule="evenodd">
<mask id="b" fill="#fff">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#a"></use>
</mask>
<use fill="#D3D3D3" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#a"></use>
<g fill="#121A28" mask="url(#b)">
<path d="M0 24h24V0H0z"></path>
</g>
</g>
</svg>
Second icon:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="120" height="50" viewBox="0 0 120 50">
<defs>
<path id="a" d="M95.448 0c-6.967 0-13.25 2.905-17.717 7.567C73.262 2.905 66.979 0 60.01 0c-6.974 0-13.263 2.912-17.73 7.578C37.81 2.912 31.523 0 24.548 0 10.992 0 0 10.989 0 24.546c0 13.557 10.992 24.548 24.548 24.548 6.975 0 13.263-2.91 17.732-7.579 4.467 4.668 10.756 7.579 17.73 7.579 6.969 0 13.252-2.908 17.72-7.568 4.469 4.66 10.751 7.568 17.718 7.568 13.56 0 24.552-10.99 24.552-24.548C120 10.989 109.008 0 95.448 0M37.533 19.734l-9.664 14.84a3.968 3.968 0 0 1-3.327 1.8 3.967 3.967 0 0 1-3.33-1.8l-9.661-14.84a3.937 3.937 0 0 1 1.17-5.462 3.971 3.971 0 0 1 5.484 1.167l6.337 9.728 6.332-9.728a3.974 3.974 0 0 1 5.485-1.167 3.94 3.94 0 0 1 1.174 5.462m22.465 15.7c-6.018 0-10.898-4.878-10.898-10.898 0-6.018 4.88-10.899 10.898-10.899 6.021 0 10.903 4.88 10.903 10.9 0 6.02-4.88 10.897-10.903 10.897m35.438 0c-6.018 0-10.898-4.878-10.898-10.898 0-6.018 4.88-10.899 10.898-10.899 6.021 0 10.902 4.88 10.902 10.9 0 6.02-4.88 10.897-10.902 10.897"></path>
</defs>
<g fill="none" fill-rule="evenodd">
<mask id="b" fill="#fff">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#a"></use>
</mask>
<use fill="#FEFEFE" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#a"></use>
<g fill="#D4107A" mask="url(#b)">
<path d="M0 0h120v50H0z"></path>
</g>
</g>
</svg>
If you convert the SVG to a .jsx file and modify the attributes so it's .jsx-friendly, it will render the SVGs as if it were a .svg file.
import * as React from 'react';
const svg = (
<div>
<svg
width="120"
height="50"
viewBox="0 0 120 50"
>
<defs>
<path
id="a"
d="M95.448 0c-6.967 0-13.25
2.905-17.717 7.567C73.262 2.905 66.979 0
60.01 0c-6.974 0-13.263 2.912-17.73 7.578C37.81
2.912 31.523 0 24.548 0 10.992 0 0 10.989 0 24.546c0
13.557 10.992 24.548 24.548 24.548 6.975 0 13.263-2.91
17.732-7.579 4.467 4.668 10.756 7.579 17.73 7.579 6.969
0 13.252-2.908 17.72-7.568 4.469 4.66 10.751 7.568 17.718
7.568 13.56 0 24.552-10.99 24.552-24.548C120 10.989 109.008
0 95.448 0M37.533 19.734l-9.664 14.84a3.968 3.968 0 0 1-3.327
1.8 3.967 3.967 0 0 1-3.33-1.8l-9.661-14.84a3.937 3.937 0 0 1
1.17-5.462 3.971 3.971 0 0 1 5.484 1.167l6.337
9.728 6.332-9.728a3.974 3.974 0 0 1 5.485-1.167 3.94 3.94 0
0 1 1.174 5.462m22.465 15.7c-6.018 0-10.898-4.878-10.898-10.898
0-6.018 4.88-10.899 10.898-10.899 6.021 0 10.903 4.88 10.903
10.9 0 6.02-4.88 10.897-10.903 10.897m35.438 0c-6.018
0-10.898-4.878-10.898-10.898 0-6.018 4.88-10.899 10.898-10.899
6.021 0 10.902 4.88 10.902 10.9 0 6.02-4.88 10.897-10.902 10.897"
/>
</defs>
<g fill="none" fillRule="evenodd">
<mask id="b" fill="#fff">
<use xmlns="http://www.w3.org/1999/xlink" xlinkHref="#a"/>
</mask>
<use fill="#FEFEFE"/>
<g fill="#D4107A" mask="url(#b)">
<path d="M0 0h120v50H0z"/>
</g>
</g >
</svg >
</div>
);
Excuse the blue background. That's the background color I have in my test dev environment.
Encountered the same issue - it seems that different SVGs used the same path id.
This is how I solved it - changed each SVG file to use different ID:
In your case - you should change the second SVG:
<path id="a" to <path id="b"
AND
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#a"></use>
to
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#b"></use>
AND
<use fill="#D3D3D3" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#a"></use>
to
<use fill="#D3D3D3" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#b"></use>