<Link> not working in <Button> for next.js - javascript

Trying to have a wrapping around a that I created in my Navbar as below shows:
<NavBtn>
<Link href="/contact" passHref>
<Button>
Contact Me
</Button>
</Link>
</NavBtn>
Here is my custom Button.js
const StyledButton = styled.button`
height: 45px;
width: 130px;
background: #908db9;
border: none;
border-radius: 4px;
outline: none;
color: #fafafa;
font-size: 1.05rem;
font-weight: 500;
&:hover {
background: #b8b4f0;
}
`
const Button = ({ children }) => {
return <StyledButton><a onClick={() => console.log("clicked")}>{children}</a></StyledButton>
}
Basically, I cannot click the button like I normal behaviour. But I can't resolve where the issue is coming from :(
Please advise as I am a little lost in what I have done wrong. If need more information let me know!
Thanks in advance.

Just wrapped inside Extra Div it will solve the problem.
where are using button component

Related

How to instantiate different instances of a svelte component in a single parent component every time the child component is used?

I am creating a custom select menu in svelte and have encountered an issue while trying to edit the transform property of the downward icon for the select menu.
I am creating a form with multiple select menus imported to one parent component. Whilst clicking on the second select menu box used in a parent component file, only the first select menu box's icon gets transformed, while no change occurs in the position of the icon of the second select menu box.
I think that this is because both the imported components(select menu) share the same class during compilation. If my assumption is correct, is there any way to instantiate an instance of the select menu component in the parent component every time the select component is used?
<script>
export let displayText;
let clickCount = 0;
</script>
<div
class="selection"
on:click={() => {
clickCount++;
clickCount == 1
? (document.querySelector(".arrow").style.transform = "rotate(180deg)")
: (document.querySelector(".arrow").style.transform = "rotate(0deg)");
clickCount == 2 ? (clickCount = 0) : (clickCount = clickCount);
}}
>
<span>{displayText}</span>
<div class="arrow" />
</div>
<style>
.selection {
display: flex;
border-radius: 5px;
padding-left: 10px;
padding: 10px;
font-weight: bold;
background-color: #363636;
font-size: 14px;
align-items: center;
cursor: pointer;
}
.selection .arrow {
transition: all 0.5s;
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 8px solid white;
margin-left: 10px;
}
</style>
The problem is the document.querySelector(".arrow") that will always find the first element with the class. Svelte has other tools to avoid that and target and manipulate element inside the component without querying the DOM. Here you can use the class: directive
REPL
<script>
export let displayText;
let open = false
</script>
<div class="selection"
on:click={() => open = !open}
>
<span>{displayText} - open = {open}</span>
<div class="arrow"
class:rotated={open}
/>
</div>
<style>
.selection {
...
}
.selection .arrow {
...
}
.rotated {
transform: rotate(180deg);
}
</style>

Div is ignoring whatever styling I put on it

We are doing a YouTube clone for a project and I'm trying to style it. Regardless of what I put for styling it disregards it and nothing is applied.
I have tried adding it on the main div, the link, and it still doesn't work.
import React from "react";
import { Link } from "react-router-dom";
const DisplayVideos = ({videos}) => {
return (
<div >
{videos.map((video, index) => {
// get video id
return (
<div style={{'margin-bottom': '80px'}}>
<Link to={`/video/${video.id.videoId}`}>
<div key={index}>
<img src={video.snippet.thumbnails.medium.url} alt="" />
</div>
<div>
<div >{video.snippet.title}</div>
</div>
</Link>
</div>
);
})}
</div>
);
}
export default DisplayVideos;
styles page:
.display-title{
font-family: Arial, Helvetica, sans-serif;
font-size: 20px;
color: rgb(29, 50, 67);
}
.display-description{
font-family: Arial, Helvetica, sans-serif;
font-size: 20px;
color: rgb(0, 0, 0);
}
Link{
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
/* CSS just to show the bounds */
border: 2px solid;
background-color: #eee
}
.text {
width: 20%;
inline-size: 10px;
overflow-wrap: break-word;
}
There is no HTML element called Link so you are not targeting anything when you do Link { instead you would need to do:
.link {
// styles
}
Then do <Link className="link" />
https://reactrouter.com/docs/en/v6/api#link
A <Link> is an element that lets the user navigate to another page by clicking or tapping on it. In react-router-dom, a <Link> renders an accessible <a> element with a real href that points to the resource it's linking to. This means that things like right-clicking a <Link> work as you'd expect. You can use <Link reloadDocument> to skip client side routing and let the browser handle the transition normally (as if it were an <a href>).
With react you have to use lowerCamelCase for CSS atributes.
Try marginBottom instead of margin-bottom in your component.
Use className='class1 class2 etc.' if you want to use CSS classes in HTML elements
<div className='class1 class2 etc.'>
Or
<div style={{marginBottom: '80px'}}>

Best way to change className in Next.js when a button is clicked, with CSS Modules?

I am creating a basic nav bar and I want to change it based on screen size. Once it hits 600px i'd like to hide the links and display a clickable nav button that will expand those options.
After console logging my list Elements I found that the className was given this 'Nav_floatLeft__H1YZ8'. So based on that finding, my code is as follows. However, my navigation does not display any changes when clicking the button.
I'm sure React has a better way of handling this situation, but I'm fairly new to it. Should I be using some kind of state/effect hook?
Nav:
const openCloseMenu = () => {
console.log(document.getElementsByClassName(styles.floatLeft).className);
let elements = document.getElementsByClassName(styles.floatLeft);
if (elements.className === "Nav_floatLeft__H1YZ8"){
alert("Changed to: Menu Bar Expanded");
elements.className = styles.menuBarExpanded;
}
else {
alert("Changed Back to: Float Left")
elements.className = styles.floatLeft;
}
}
return (
<div className={styles.topNav}>
<nav>
<ul className={styles.inlineListItem}>
<li className={styles.floatLeft}>
<Link href="/">
<a>Home</a>
</Link>
</li>
<li className={styles.floatLeft}>
<Link href="/search">
<a>Search</a>
</Link>
</li>
<li className={styles.menuBar}>
<button onClick={openCloseMenu}>Expand Nav</button>
</li>
</ul>
</nav>
</div>
)
CSS:
.inlineListItem{
display: inline;
list-style: none;
}
.floatLeft{
float: left;
margin: 1rem;
padding-left: 1rem;
text-align: center;
color: white;
}
.floatRight{
display: inline;
float: right;
color: white;
margin: 1rem;
padding-right: 2rem;
}
.menuBar{
display: none;
float: left;
margin: 1rem;
padding-left: 1rem;
text-align: center;
color: white;
}
.menuBarExpanded{
display: block;
}
#media screen and (max-width: 600px) {
.menuBar{
display: block;
}
.floatLeft{
display: none;
}
.floatRight{
display: none;
}
}
ways are there to solve this problem.
You can use material UI. To detect the breakpoint.
Like for you case. If want to detect 600px.
you can do something like that ---
const themeBreakpoint = theme.breakpoint.down('600px) // themeBreakpoint will be true under 600px.
using this flag you can change state and show what ever you want by using condition rendering.
Second Problem --
you can change any state based on onClick event.
like --
const[clicked,setclicked] = useState(false)
const handleClick = (e) =>{
setclicked(true)
}
now when you make that clicked flag true, You change you css class based on that flag.
You could implement an useState hook:
import { useState } from "react";
const YourComponent = () => {
const [cliked, setClicked] = useState(false);
return (
<YourNavbar className={clicked ? "display" : "hide"} />
....
<button onClick={() => setClicked(current => !current)}>Expand Nav</button>
....
)
}
And on css, you can establish the class display with the actual attributes of the navbar, and a hidden (display: none)
This will check if the navbar button has been clicked (set to true), and on the conditional class, if its true, then it will display the navbar through the "display" class, if the button is clicked again, clicked will be false and the class for the navbar will be "hidden".
Remember to delegate this classnames to the item only when the navbar is below 600px with #media

Button does not respond to DOM cssStyleDeclaration

I am sure this is a simple bug but I´ve been over an hour trying to find where the problem is and definetely could use a different point of view.
In the following function I change the style of two buttons. One of them, responds correctly and indeed its font size changes when the function gets called (deleteBtnToDecorate).
The other one, I cant understand why it doesn´t responds and it´s font size doesn´t get changed (doneBtnToDecorate):
changeStyle: function(idNumber){
const liToDecorate = document.getElementById(`id${idNumber}`)
const doneBtnToDecorate = document.getElementById(`idDone${idNumber}`)
const deleteBtnToDecorate = document.getElementById(`idDelete${idNumber}`)
liToDecorate.style.textDecoration = 'line-through'
doneBtnToDecorate.style.fontSize = '0.8rem'
deleteBtnToDecorate.style.fontSize = '1.1rem'
}
Things I´ve tried:
console logged clicking in both buttons to verify all of them are
targeted correctly. They are
changed css font size manually to verify in case bootstrap might be
the problem (although if it would be, the other button wouldn´t
change either) but anyway...the fact is: It changes succesfully
when i do it via CSS and not the DOM
This is my full code:
<ul class="item-list-ul">
<li
v-for="(i, index) in items"
:id="`id${index}`"
:key="index">{{ i }}
<div class="item-butons">
<b-button :id="`idDone${index}`" class="done-btn" #click="changeStyle(index)" size="sm" variant="outline-dark">Hecho!</b-button>
<b-button :id="`idDelete${index}`" class="delete-btn" #click="deleteItem(i)" size="sm" variant="warning">Borrar</b-button>
</div>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'TodoList',
methods: {
changeStyle: function(idNumber){
const liToDecorate = document.getElementById(`id${idNumber}`)
const doneBtnToDecorate = document.getElementById(`idDone${idNumber}`)
const deleteBtnToDecorate = document.getElementById(`idDelete${idNumber}`)
liToDecorate.style.textDecoration = 'line-through'
doneBtnToDecorate.style.fontSize = '0.8rem'
deleteBtnToDecorate.style.fontSize = '1.1rem'
}
}
}
</script>
<style lang="css">
.item-wrapper{
padding: 4vh 3vh 4vh 3vh;
}
.item-list-ul{
margin-right: 4vh;
}
.item-list-ul li{
margin-bottom: 3vh;
}
.item-list-ul li{
font-size: 1.4em !important;
font-weight: 600;
list-style: outside none none;
}
.done-btn{
margin-right: 20px;
font-size: 1rem !important;
font-weight: 600 !important;
}
.delete-btn{
font-size: 0.9rem;
font-weight: 600 !important;
}
</style>
Your CSS uses !important:
.done-btn {
...
font-size: 1rem !important;
...
}
If you use !important it will take precedence over inline styles.
Incidentally, this is not really the correct way to do this in Vue. You should apply the changes within the template via either class or style bindings rather than grabbing elements and changing them directly.

How to set padding of Gatsby Link Component to 0px with styled-components

I have made some style changes to the Gatsby Link component using styled-components. However for some reason, when i try to apply a padding of 0px, it still leaves a tiny space (few px) above/below the text (between text and top/bottom border). I used gatsby-default-starter in a codesandbox for the initial build.
HTML/CSS Env (codepen.io):
https://codepen.io/marti2221/pen/mNVJWZ
Gatsby Env (codesandbox):
https://codesandbox.io/s/gatsby-paddinglink-spacing-gedtq
I have tried applying padding via styled-components in a Gatsby environment, as well as a normal html/css environment. When padding is set to 0px on the "a" tag in css/html environment, there is no space around the text, as expected. However when i attempt to add the same padding to the gatsby Link component or even a regular a tag, in a gatsby environment, there is a tiny space between the text and my border. This leads to a larger padding on top/bottom for my BtnLink than expected. I could adjust my padding accordingly, but i would like to know the root cause of this issue.
const StyledLink = styled(Link)`
display: inline-block;
font-family: sans-serif;
border-radius: 25px;
padding: 0px;
text-decoration: none;
border: 2px solid green;
`
const StyledA = styled.a`
display: inline-block;
font-family: sans-serif;
border-radius: 25px;
padding: 0px;
text-decoration: none;
border: 2px solid green;
`
const BtnLink = props => (
<StyledLink {...props}>{props.children}</StyledLink>
)
const IndexPage = () => (
<Layout>
<BtnLink to="page-2">Request Quote</BtnLink>
<StyledA href="page-2">Request Quotes</StyledA>
<Link to="page-2">Link</Link>
</Layout>
)
My desired result is a gatsby Link component that can be styled the same as a regular link element (ie. 0px padding). My result is link text with some spacing around it in the Gatsby environment. When tested with regular HTML/CSS, results are as expected (no spacing when padding is set to 0px)
You've already made a styled(Link) styledComponent, and saved it to the const StyledLink.
const StyledLink = styled(Link)`
display: inline-block;
font-family: sans-serif;
border-radius: 25px;
padding: 0px;
text-decoration: none;
border: 2px solid green;
However, this won't have any affect on a regular gatsby Link component. You still need to render this new StyledLink styledComponent instead of a gatsby Link component if you want to see that styled variation on your page.
const IndexPage = () => (
<Layout>
<BtnLink to="page-2">Request Quote</BtnLink>
<StyledA href="page-2">Request Quotes</StyledA>
<StyledLink to="page-2">Link</StyledLink>
</Layout>
)

Categories