Gatsby / GraphQL App - Rendering and Style Issues When Deployed (Netlify and Surge) - graphql
Built a portfolio page with Gatsby / GraphQL, using styled components. On my local machine, it looks and functions exactly as I want it to. When deployed, there seem to be button style issues and one of my images isn't rendering at all. I tried deploying on both Netlify and Surge.sh, but had the same result both times. What am I doing incorrectly? Edit: could my button styles be affected by how Link is used?
Here are how my button styles look locally:
Here's how they look deployed ('View Repo' doesn't even work deployed):
My 'About Me' section locally (2 columns):
My 'About Me' section deployed (only column 1 shows):
gatsby-config.js
module.exports = {
siteMetadata: {
title: `Portfolio`,
description: `Lorem ipsum.`,
author: `#jordanwhunter`,
},
plugins: [
`gatsby-plugin-react-helmet`,
`gatsby-plugin-image`,
`gatsby-plugin-styled-components`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/assets/images`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `videos`,
path: `${__dirname}/src/assets/videos`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-starter-default`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/assets/images/memoji.jpeg`, // This path is relative to the root of the site.
},
},
`gatsby-plugin-gatsby-cloud`,
`gatsby-transformer-json`,
{
resolve: `gatsby-source-filesystem`,
options: {
path: `./src/data/`,
},
},
],
}
package.json
{
"name": "gatsby-starter-default",
"private": true,
"description": "A simple starter to get up and developing quickly with Gatsby",
"version": "0.1.0",
"author": "Kyle Mathews <mathews.kyle#gmail.com>",
"dependencies": {
"babel-plugin-styled-components": "^1.12.0",
"gatsby": "^3.0.1",
"gatsby-image": "^3.0.0",
"gatsby-plugin-gatsby-cloud": "^2.0.0",
"gatsby-plugin-image": "^1.0.0",
"gatsby-plugin-manifest": "^3.0.0",
"gatsby-plugin-offline": "^4.0.0",
"gatsby-plugin-react-helmet": "^4.0.0",
"gatsby-plugin-sharp": "^3.0.0",
"gatsby-plugin-styled-components": "^4.0.0",
"gatsby-source-filesystem": "^3.0.0",
"gatsby-transformer-json": "^3.0.0",
"gatsby-transformer-sharp": "^3.0.0",
"gh-pages": "^3.1.0",
"prop-types": "^15.7.2",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-helmet": "^6.1.0",
"react-icons": "^4.2.0",
"styled-components": "^5.2.1",
"surge": "^0.22.1"
},
"devDependencies": {
"prettier": "2.2.1"
},
"keywords": [
"gatsby"
],
"license": "0BSD",
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
"start": "npm run develop",
"serve": "gatsby serve",
"clean": "gatsby clean",
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/gatsbyjs/gatsby-starter-default"
},
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
}
}
Portfolio.js (button code starts on line 226)
import React from 'react'
import { useStaticQuery, graphql } from "gatsby"
import { Button } from "./Button"
import Img from "gatsby-image"
import styled from "styled-components"
const PortfolioContainer = styled.div`
min-height: 100vh;
padding: 5rem calc((100vw - 1300px) / 2);
background: #fff;
color: #fff;
`
const PortfolioHeading = styled.div`
font-size: clamp(1.5rem, 5vw, 2.5rem);
text-align: center;
margin-bottom: 5rem;
color: #000;
`
const PortfolioImg = styled(Img)`
height: 100%;
max-width: 100%;
position: absolute;
border-radius: 10px;
filter: brightness(100%);
transition: 0.4s cubic-bezier(0.075, 0.82, 0.165, 1);
`
const PortfolioWrapper = styled.div`
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
justify-items: center;
padding: 0 2rem;
#media screen and (max-width: 1200px) {
grid-template-columns: 1fr 1fr;
}
#media screen and (max-width: 868px) {
grid-template-columns: 1fr;
}
`
const PortfolioInfo = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-content: center;
align-items: center;
justify-items: center;
padding: 0 2rem;
visibility: hidden;
opacity: 0;
transition: opacity .2s, visibility .2s;
#media screen and (max-width: 280px) {
padding: 0 1rem;
justify-content: center;
align-content: center;
}
`
const PortfolioCard = styled.div`
line-height: 2;
width: 100%;
height: 500px;
position: relative;
border-radius: 10px;
transition: 0.2s ease;
&:hover ${PortfolioInfo}{
visibility: visible;
opacity: 1;
}
&:hover ${PortfolioImg}{
filter: brightness(50%)
}
`
const TextWrap = styled.div`
display: flex;
align-items: center;
text-align: center;
position: absolute;
top: 375px;
flex-wrap: wrap;
justify-content: center;
align-content: center;
width: 87%;
`
const PortfolioTitle = styled.div`
font-weight: 400;
font-size: 1rem;
margin-left: 0.5rem;
#media screen and (max-width: 280px) {
font-size: 12px;
}
`
const PortfolioDescription = styled.div`
font-size: 1rem;
#media screen and (max-width: 280px) {
font-size: 12px;
}
`
const PortfolioTechnologies = styled.div`
font-size: 1rem;
#media screen and (max-width: 280px) {
font-size: 12px;
}
`
const ButtonLink = styled.a`
text-decoration: none;
cursor: pointer;
`
const ButtonWrap = styled.div`
display: flex;
flex-direction: row;
position: absolute;
justify-content: center;
align-content: center;
align-items: center;
width: 100%;
height: -400px;
z-index: 1;
gap: 10px;
#media screen and (max-width: 280px) {
padding: 0 1rem;
justify-content: center;
align-content: center;
}
`
const CustomButton = styled(Button)`
display: flex;
align-items: center;
position: relative;
font-size: 14px;
width: 100%;
cursor: pointer;
top: -60px;
#media screen and (max-width: 480px) {
background: none;
border: none;
padding: 0 !important;
font-family: arial, sans-serif;
color: #fff;
text-decoration: underline;
cursor: pointer;
width: 100%;
font-size: 12px;
justify-content: center;
}
`
const CustomP = styled.p`
font-size: 12px;
`
export default function Portfolio({ heading }) {
const data = useStaticQuery(graphql`
query PortfolioQuery {
allPortfolioJson {
edges {
node {
alt
button1
button2
description
name
technologies
demo
repo
img {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
}
}
}
`)
function getPortfolio(data) {
const portfolioArray = []
data.allPortfolioJson.edges.forEach((item, index) => {
portfolioArray.push(
<PortfolioCard key={index}>
<PortfolioImg
src={item.node.img.childImageSharp.fluid.src}
fluid={item.node.img.childImageSharp.fluid}
alt={item.node.alt}
/>
<PortfolioInfo>
<TextWrap>
<PortfolioTitle
css={`
margin-top: -500px;
`}
>
<strong><u>Project:</u></strong> <br />
{item.node.name}
</PortfolioTitle>
<PortfolioDescription
css={`
margin-top: -300px;
`}
>
<strong><u>Description:</u></strong> <br />
{item.node.description}
</PortfolioDescription>
<PortfolioTechnologies
css={`
margin-top: -100px;
`}
>
<strong><u>Technologies:</u></strong> <br />
{item.node.technologies}
</PortfolioTechnologies>
</TextWrap>
<ButtonWrap>
<ButtonLink
href={`${item.node.demo}`}
target="_blank"
>
<CustomButton
primary="true"
round="true"
>
{item.node.button1}
</CustomButton>
</ButtonLink>
<ButtonLink
href={`${item.node.repo}`}
target="_blank"
>
<CustomButton
primary="true"
round="true"
>
{item.node.button2}
</CustomButton>
</ButtonLink>
</ButtonWrap>
</PortfolioInfo>
</PortfolioCard>
)
})
return portfolioArray;
}
return (
<PortfolioContainer id="portfolio">
<PortfolioHeading>
{heading}
<CustomP>(Tap on Mobile)</CustomP>
</PortfolioHeading>
<PortfolioWrapper>
{getPortfolio(data)}
</PortfolioWrapper>
</PortfolioContainer>
)
};
About.js (column 2 code starts on line 137):
import React from 'react'
import { useStaticQuery, graphql } from 'gatsby';
import { GrCircleInformation, GrCode, GrDocumentImage } from "react-icons/gr";
import styled from "styled-components"
import Img from "gatsby-image"
const AboutContainer = styled.div`
width: 100%;
background: #fcfcfc;
color: #000;
padding: 5rem calc((100vw - 1300px) / 2);
height: 100%;
border-top: 1px solid gray;
border-bottom: 1px solid gray;
`
const TopLine = styled.div`
color: #077bf1;
font-size: 1rem;
padding-left: 2rem;
margin-bottom: 0.75rem;
`
const Description = styled.p`
text-align: start;
padding-left: 2rem;
margin-bottom: 4rem;
font-size: clamp(1.5rem, 5vw, 2rem);
font-weight: bold;
`
const ContentWrapper = styled.div`
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
#media screen and (max-width: 768px) {
grid-template-columns: 1fr;
}
`
const ColumnOne = styled.div`
display: grid;
grid-template-rows: 1fr 1fr;
`
const Biography = styled.div`
padding-top: 1rem;
padding-right: 2rem;
h3 {
margin-bottom: 1rem;
font-size: 1.5rem;
font-style: italic;
}
p {
color: #3b3b3b;
}
`
const ColumnTwo = styled.div`
display: grid;
grid-template-columns: 1fr;
margin-top: 2rem;
grid-gap: 10px;
#media screen and (max-width: 500px) {
grid-template-columns: 1fr;
}
`
const Image = styled(Img)`
border-radius: 10px;
height: 100%;
margin-top: -50px;
#media screen and (max-width: 375px) {
margin-top: 0;
}
`
export default function About() {
const data = useStaticQuery(graphql`
query MyQuery {
allFile(filter: {ext: {regex: "/(jpg)|(png)|(jpeg)/"}, name: {in: ["profile-photo"]}}) {
edges {
node {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`)
return (
<AboutContainer id="about">
<TopLine>
About Me
</TopLine>
<Description>
<div css={`display: flex;`}>
<GrDocumentImage /><h4 css={`font-style: italic;`}>Resumes</h4>
</div>
<div
css={`
display: flex;
font-size: 14px;
margin-bottom: -40px;
`}
>
<p>
Resume 2021 (ATS Version)<br />
Resume 2021 (Styled Version)
</p>
</div>
</Description>
<ContentWrapper>
<ColumnOne>
<Biography>
<div css={`display: flex;`}>
<GrCircleInformation /><h3>Brand Statement</h3>
</div>
<p>
Full stack web/software developer with an entrepreneurial spirit, and keen sense of efficiency and time management. A passionate, goal-oriented team player that strives to always write clean, precise code focused on mobile responsive themes. Maintains a problem solving, can-do attitude and exhibits consistent eagerness to learn new technologies/techniques.
</p>
</Biography>
<Biography>
<div css={`display: flex;`}>
<GrCode />
<h3>Technologies</h3>
</div>
<p>
JavaScript, React, Preact, Next, Gatsby, Svelte, Node, Express, Firebase, Vercel, MongoDB, MySQL, Handlebars, jQuery, D3, GraphQL, Material-UI, CSS3, Bootstrap, Materialize, Bulma, HTML5
</p>
</Biography>
</ColumnOne>
<ColumnTwo>
{data.allFile.edges.map((image, key) => (
<Image
key={key}
src={image.node.childImageSharp.src}
fluid={image.node.childImageSharp.fluid}
/>
))}
</ColumnTwo>
</ContentWrapper>
</AboutContainer>
)
};
Inspect generated html:
<div class="Portfolio__ButtonWrap-zwd7jb-14 boxtca">
<a href="https://filmapi.vercel.app/" target="_blank" class="Portfolio__ButtonLink-zwd7jb-13 dHdqal">
<a primary="true" round="true" class="Button-sc-1t76fnu-0 Portfolio__CustomButton-zwd7jb-15 iA-DhcJ cycuPQ">View App</a>
</a>
<a primary="true" round="true" class="Button-sc-1t76fnu-0 Portfolio__CustomButton-zwd7jb-15 iA-DhcJ cycuPQ">
<a primary="true" round="true" class="Button-sc-1t76fnu-0 Portfolio__CustomButton-zwd7jb-15 iA-DhcJ cycuPQ">View Repo</a>
</a>
</div>
Observation #1:
bad structure for a second button (not a ButtonLink);
Why:
messed virtual DOM [and as a result real DOM];
Possible reason:
multiple, the same kind children rendered without key prop (the most frequent bad React rendering reason?);
Solution #1: always use a key prop for [elements of] lists/arrays/groups!
'About me' missing column problem:
Observation #2:
before (at first render) and during [image] loading html/DOM structure is OK;
React update (rerendering) breaks child divs [of AboutContainer] - no keys used (then no unique identifiers for multiple divs in VDOM), result - the update breaks the content structure.
But this is not the only reason - the real one was using <Img/>-based component - outdated for new gatsby image plugins [versions].
Solution #2:
You should use <GatsbyImage/> components.
Always make sure the documentation you're referencing is current!
There are significant syntax changes with graphql and using the GatsbyImage / StaticImage components from gatsby-plugin-image instead of the Img component from gatsby-image.
To fix Portfolio.js - the image rendering was affecting the button links - code had to be refactored for the current syntax referencing the GatsbyImage component from gatsby-plugin-image. graphql and useStaticQuery syntax also had to be refactored. For more information, visit Gatsby's documentation (thanks to #xadm for pointing me in the right direction).
About.js was also fixed by updating syntax...except this Img tag was changed to StaticImage and graphql and useStaticQuery were removed entirely.
Related
Why does my <ul> become hidden in desktop mode?
Sorry if this question has already been asked, I don't find anything similar. So I am following a course and I have created the mobile navbar, which works. Then I write the mediaquery for larger screens and the list, instead of being displayed to the right of the navbar, is hidden. If I inspect the page I can see that the list and the list items are on the right spot, but they are not visible. I have tried with "visibility: visible" but it doesnt' work. Where is the mistake? const collapsibles = document.querySelectorAll(".collapsible"); collapsibles.forEach((item) => item.addEventListener("click", function () { this.classList.toggle("collapsible--expanded"); }) ); /* Typography */ html { font-size: 62.5%; } :root { --color-primary: #2584ff; --color-secondary: #00d9ff; --color-accent: #ff3400; --color-headings: #1b0760; --color-body: #918ca4; --color-border: #ccc; --border-radius: 30px; --color-body-darker: #5c5577; } body { font-family: Inter, Arial, Helvetica, sans-serif; font-size: 2.4rem; line-height: 1.5; color: var(--color-body); } h1, h2, h3 { color: var(--color-headings); margin-bottom: 1rem; } h1 { font-size: 7rem; } h2 { font-size: 4rem; } h3 { font-size: 3rem; } p { margin-top: 0; } #media screen and (min-width: 1024px) { body { font-size: 1.8rem; } h1 { font-size: 8rem; } h2 { font-size: 4rem; } h3 { font-size: 2.4rem; } } /* Links */ a { text-decoration: none; } .link-arrow { color: var(--color-accent); text-transform: uppercase; font-size: 2rem; font-weight: bold; } .link-arrow::after { content: "-->"; margin-left: 5px; transition: margin 0.15s; } .link-arrow:hover::after { margin-left: 10px; } #media screen and (min-width: 1024px) { .link-arrow { font-size: 1.5rem; } } /* Badges */ .badge { border-radius: 20px; font-size: 2rem; font-weight: 600; padding: 0.5rem 2rem; white-space: nowrap; } .badge--primary { background: var(--color-primary); color: white; } .badge--secondary { background: var(--color-secondary); color: white; } .badge--small { font-size: 1.6rem; padding: 0.5rem 1.5rem; } #media screen and (min-width: 1024px) { .badge { font-size: 1.5rem; } .badge--small { font-size: 1.2rem; } } /* Lists */ .list { list-style: none; padding-left: 0; color: var(--color-headings); } .list--inline .list__item { display: inline-block; margin-right: 2rem; } .list--tick { list-style-image: url(/images/tick.svg); padding-left: 3rem; } .list--tick .list__item { padding-left: 0.5rem; margin-bottom: 1rem; } #media screen and (min-width: 1024px) { .list--tick .list__item { padding-left: 0; } } /* Icons */ .icon { width: 40px; height: 40px; } .icon--small { width: 30px; height: 30px; } .icon--primary { fill: var(--color-primary); } .icon--white { fill: white; } .icon-container { background: #f3f9fa; width: 64px; height: 64px; border-radius: 100%; display: inline-flex; justify-content: center; align-items: center; } .icon-container--accent { background: var(--color-accent); } /* Buttons */ .btn { border-radius: 40px; border: none; cursor: pointer; font-size: 1.8rem; font-weight: 600; margin-left: 5px; margin-top: 5px; padding: 2rem 3rem; text-transform: uppercase; white-space: nowrap; } .btn--primary { background-color: var(--color-primary); color: white; } .btn--primary:hover { background: #8a91f3; } .btn--secondary { background-color: var(--color-secondary); color: white; } .btn--accent { background-color: var(--color-accent); color: white; } .btn--accent:hover { background: #e66545; } .btn--outline { background-color: white; color: black; border: 2px solid var(--color-headings); } .btn--block { display: inline-block; width: 100%; } .btn--stretched { padding-left: 6rem; padding-right: 6rem; } /* Input */ .input { border-radius: 30px; border: 1px solid #ccc; color: var(--color-headings); font-size: 2rem; outline: 0; padding: 1.5rem 3.5rem; } ::placeholder { color: #cdcbd7; } .input-group { border: 1px solid var(--color-border); border-radius: var(--border-radius); display: flex; } .input-group .input { border: 0; flex-grow: 1; padding: 1rem 1rem; } .input-group .btn { margin: 4px; } #media screen and (min-width: 1024px) { .input { font-size: 1.5rem; } } /* Cards */ .card { border-radius: 7px; box-shadow: 0 0 20px 10px #f3f3f3; overflow: hidden; min-width: 300px; } .card__header, .card__body { padding: 2rem 3rem; } .card--primary .card__header { background: var(--color-primary); color: #fff; } .card--secondary .card__header { background: var(--color-secondary); color: #fff; } .card--secondary .badge--secondary { background: #02cdf1; } /* Plans */ .plan__name { color: #fff; margin: 0; font-weight: 500; font-size: 2.4rem; } .plan__price { font-size: 6rem; } .plan__billing-cycle { font-size: 2.4rem; font-weight: 300; opacity: 0.8; margin-right: 1rem; } .plan__description { font-size: 2rem; font-weight: 300; letter-spacing: 1px; display: block; } .plan .list__item { margin-bottom: 2rem; } .plan--popular .card__header { position: relative; } .plan--popular .card__header::before { content: url(/images/popular.svg); width: 40px; display: inline-block; position: absolute; top: -6px; right: 5%; } #media screen and (min-width: 1024px) { .plan__name { font-size: 1.4rem; } .plan__price { font-size: 5rem; } .plan__billing-cycle { font-size: 1.6rem; } .plan__description { font-size: 1.7rem; } } /* Media */ .media { display: flex; max-width: 500px; } .media__title { margin-top: 0; } .media__body { margin: 0 2rem; } .media__image { margin-top: 1rem; } /* Quotes */ .quote { font-size: 3rem; font-style: italic; color: var(--color-body-darker); line-height: 1.3; } .quote__text::before { content: open-quote; } .quote__text::after { content: close-quote; } /* footer p { font-size: 1.6rem; } */ .quote__company { font-size: 1.6rem; opacity: 0.4; color: var(--color-headings); font-style: normal; } /* Grids */ .grid { display: grid; } #media screen and (min-width: 768px) { .grid--1x2 { grid-template-columns: 1fr 1fr; } } #media screen and (min-width: 1024px) { .grid--1x3 { grid-template-columns: 1fr 1fr 1fr; } } /* testimonials */ .testimonial { padding: 3rem; } .testimonial__image { position: relative; } .testimonial__image > img { width: 100%; } .testimonial__image > .icon-container { position: absolute; top: 3rem; right: -32px; } /* Callout */ .callout { padding: 4rem; border-radius: 5px; } .callout--primary { background: var(--color-primary); color: white; } .callout__heading { color: white; margin-top: 0; font-size: 3rem; } .callout .btn { justify-self: center; align-self: center; } .callout__content { text-align: center; } #media screen and (min-width: 768px) { .callout .grid--1x2 { grid-template-columns: 1fr auto; } .callout__content { text-align: left; } .callout .btn { justify-self: start; margin: 0 2rem; } } /* COLLAPSIBLES */ .collapsible__header { display: flex; justify-content: space-between; } .collapsible__heading { margin-top: 0; font-size: 3rem; } .collapsible__chevron { transform: rotate(-90deg); transition: transform 0.3s; } .collapsible__content { max-height: 0; overflow: hidden; transition: all 0.3s; opacity: 0; } .collapsible--expanded .collapsible__chevron { transform: rotate(0); } .collapsible--expanded .collapsible__content { display: block; max-height: 100vh; opacity: 1; } /* Blocks */ .block { --padding-vertical: 6rem; padding: var(--padding-vertical) 2rem; } .block__heading { margin-top: 0; } .block--dark { background: black; color: #7b858b; } .block--dark .block__heading { color: white; } .block--skewed-right { clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 80%); padding-bottom: calc(var(--padding-vertical) + 4rem); } .block--skewed-left { clip-path: polygon(0% 0%, 100% 0%, 100% 80%, 0% 100%); padding-bottom: calc(var(--padding-vertical) + 4rem); } .block__header { text-align: center; } /* nav */ .nav { background: black; display: flex; justify-content: space-between; flex-wrap: wrap; padding: 0 1rem; align-items: center; } .nav__list { width: 100%; margin: 0; } .nav__item { padding: 0.5rem 2rem; border-bottom: 1px solid #222; } .nav__item > a { color: #d2d0db; transition: color 0.3s; } .nav__item > a:hover { color: #fff; } .nav__toggler { opacity: 0.5; transition: box-shadow 0.15s; cursor: pointer; } .nav.collapsible--expanded .nav__toggler { opacity: 1; box-shadow: 0 0 0 3px #666; border-radius: 5px; } #media screen and (min-width: 768px) { .nav__toggler { display: none; } .nav__list { width: auto; display: flex; visibility: ; } } <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <link rel="preconnect" href="https://fonts.gstatic.com" /> <link href="https://fonts.googleapis.com/css2?family=Inter:wght#400;600;700&display=swap" rel="stylesheet" /> <link rel="stylesheet" href="/css/normalize.css" /> <link rel="stylesheet" href="/css/styles.css" /> </head> <body> <nav class="nav collapsible"> <img src="/images/logo.svg" alt="" /> <svg class="icon icon--white nav__toggler"> <use xlink:href="images/sprite.svg#menu"></use> </svg> <ul class="list nav__list collapsible__content"> <li class="nav__item">Hosting</li> <li class="nav__item">VPS</li> <li class="nav__item">Domain</li> <li class="nav__item">Pricing</li> </ul> </nav> <script src="/js/main.js"></script> </body> </html>
Problem was solved by adding max-height: 100%; opacity:1 to the .nav__list rule in CSS.
How to style dropdown with styled-components
I am using React JS + Typescript for my app. For styling I am using styled-components. I am really new in styled components. I have created one dropdown. The logic works fine but the UI looks horrible. I uploaded my code in Code sand box. I want design my Dropdown like Tailwind. But since I am new styled-components, I just don't know how to do that. This is my dropdown component import React, { useState } from "react"; import styled from "styled-components"; import Arrow from './Arrow.svg' const Wrapper = styled.div< { active: boolean; } >` text-align: left; width: 100%; color: #bfc5cd; font-size: 16px; font-weight: 300; position: relative; margin: 2em 0; #media (min-width: 400px) { max-width: 300px; } svg { fill: #798697; transition: all 0.2s ease; } ${props => props.active ? ` svg { transform: rotate(180deg); } ` : ``} `; const MenuLabel = styled.span` display:inline-block; color: grey; border: 1px solid green; background: white; box-shadow: 0 0 5px -1px rgba(0,0,0,0.2); cursor:pointer; vertical-align:middle; max-width: 100px; padding: 40px 40px; font-size: 12px; text-align: center; border: 1px solid ${({ theme }) => theme.inputBorderColor}; &:focus { outline: none; box-shadow: 0px 0px 0px 1px ${({ theme }) => theme.inputBorderColorActive}; border: 1px solid ${({ theme }) => theme.inputBorderColorActive}; } `; const ItemList = styled.div` color: #798697; background: white; line-height: 30px; padding: .25em 2em .25em 2em; cursor: defaul; user-select: none; transition: all .25s ease; &:hover, &.selected { background: #F7F7F7; color: #4A4A4A; } `; export interface IOptions { label: string; value: number; } export interface IDropdown { labelDefault: string; options: IOptions[]; } const Dropdown = ({ labelDefault, options }: IDropdown) => { const [isOpened, setIsOpened] = useState(false); const [selectedOption, setSelectedOption] = useState(""); const [label, setLabel] = useState(""); const handleSelectedItem = (obj: any) => { setSelectedOption(obj.value); setLabel(obj.label); setIsOpened(!isOpened); }; return ( <Wrapper active={isOpened}> <MenuLabel onClick={() => setIsOpened(!isOpened)}> {selectedOption ? label : labelDefault} </MenuLabel> <ul style={ isOpened ? { display: "block", listStyleType: "none" } : { display: "none" } } > {options.map(el => ( <ItemList key={el.value.toString()} onClick={() => handleSelectedItem(el)} > {el.label} </ItemList> ))} </ul> </Wrapper> ); } export default Dropdown; This is the parent component import * as React from "react"; import Dropdown from "./dropdown"; const MockData = [ { label: "one", value: 1 }, { label: "two", value: 2 }, { label: "three", value: 3 } ]; export default function App() { return ( <div className="App"> <h1>Hello CodeSandbox</h1> <Dropdown labelDefault="Select a label" options={MockData} /> </div> ); }
xamarin forms Jsonreaderexception
I have a list showing stores on a page, upon clicking each store, corresponding categories and products are shown on a lists in another page. Stores, categories and products are displayed using Api calls.I am getting everything correct, but while navigating back and forth many times between store page and product page,Getting this error: Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. Using breakpoint, not able to see the source of exception. How to handle this exception? Edit: I am getting this html just before exception <!doctype html> <html lang="en"> <head> <title>Too Many Requests</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Fonts --> <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet" type="text/css"> <!-- Styles --> <style> html { line-height: 1.15; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; } body { margin: 0; } header, nav, section { display: block; } figcaption, main { display: block; } a { background-color: transparent; -webkit-text-decoration-skip: objects; } strong { font-weight: inherit; } strong { font-weight: bolder; } code { font-family: monospace, monospace; font-size: 1em; } dfn { font-style: italic; } svg:not(:root) { overflow: hidden; } button, input { font-family: sans-serif; font-size: 100%; line-height: 1.15; margin: 0; } button, input { overflow: visible; } button { text-transform: none; } button, html [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { border-style: none; padding: 0; } button:-moz-focusring, [type="button"]:-moz-focusring, [type="reset"]:-moz-focusring, [type="submit"]:-moz-focusring { outline: 1px dotted ButtonText; } legend { -webkit-box-sizing: border-box; box-sizing: border-box; color: inherit; display: table; max-width: 100%; padding: 0; white-space: normal; } [type="checkbox"], [type="radio"] { -webkit-box-sizing: border-box; box-sizing: border-box; padding: 0; } [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } [type="search"] { -webkit-appearance: textfield; outline-offset: -2px; } [type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-file-upload-button { -webkit-appearance: button; font: inherit; } menu { display: block; } canvas { display: inline-block; } template { display: none; } [hidden] { display: none; } html { -webkit-box-sizing: border-box; box-sizing: border-box; font-family: sans-serif; } *, *::before, *::after { -webkit-box-sizing: inherit; box-sizing: inherit; } p { margin: 0; } button { background: transparent; padding: 0; } button:focus { outline: 1px dotted; outline: 5px auto -webkit-focus-ring-color; } *, *::before, *::after { border-width: 0; border-style: solid; border-color: #dae1e7; } button, [type="button"], [type="reset"], [type="submit"] { border-radius: 0; } button, input { font-family: inherit; } input::-webkit-input-placeholder { color: inherit; opacity: .5; } input:-ms-input-placeholder { color: inherit; opacity: .5; } input::-ms-input-placeholder { color: inherit; opacity: .5; } input::placeholder { color: inherit; opacity: .5; } button, [role=button] { cursor: pointer; } .bg-transparent { background-color: transparent; } .bg-white { background-color: #fff; } .bg-teal-light { background-color: #64d5ca; } .bg-blue-dark { background-color: #2779bd; } .bg-indigo-light { background-color: #7886d7; } .bg-purple-light { background-color: #a779e9; } .bg-no-repeat { background-repeat: no-repeat; } .bg-cover { background-size: cover; } .border-grey-light { border-color: #dae1e7; } .hover\:border-grey:hover { border-color: #b8c2cc; } .rounded-lg { border-radius: .5rem; } .border-2 { border-width: 2px; } .hidden { display: none; } .flex { display: -webkit-box; display: -ms-flexbox; display: flex; } .items-center { -webkit-box-align: center; -ms-flex-align: center; align-items: center; } .justify-center { -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; } .font-sans { font-family: Nunito, sans-serif; } .font-light { font-weight: 300; } .font-bold { font-weight: 700; } .font-black { font-weight: 900; } .h-1 { height: .25rem; } .leading-normal { line-height: 1.5; } .m-8 { margin: 2rem; } .my-3 { margin-top: .75rem; margin-bottom: .75rem; } .mb-8 { margin-bottom: 2rem; } .max-w-sm { max-width: 30rem; } .min-h-screen { min-height: 100vh; } .py-3 { padding-top: .75rem; padding-bottom: .75rem; } .px-6 { padding-left: 1.5rem; padding-right: 1.5rem; } .pb-full { padding-bottom: 100%; } .absolute { position: absolute; } .relative { position: relative; } .pin { top: 0; right: 0; bottom: 0; left: 0; } .text-black { color: #22292f; } .text-grey-darkest { color: #3d4852; } .text-grey-darker { color: #606f7b; } .text-2xl { font-size: 1.5rem; } .text-5xl { font-size: 3rem; } .uppercase { text-transform: uppercase; } .antialiased { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .tracking-wide { letter-spacing: .05em; } .w-16 { width: 4rem; } .w-full { width: 100%; } #media (min-width: 768px) { .md\:bg-left { background-position: left; } .md\:bg-right { background-position: right; } .md\:flex { display: -webkit-box; display: -ms-flexbox; display: flex; } .md\:my-6 { margin-top: 1.5rem; margin-bottom: 1.5rem; } .md\:min-h-screen { min-height: 100vh; } .md\:pb-0 { padding-bottom: 0; } .md\:text-3xl { font-size: 1.875rem; } .md\:text-15xl { font-size: 9rem; } .md\:w-1\/2 { width: 50%; } } #media (min-width: 992px) { .lg\:bg-center { background-position: center; } } </style> </head> <body class="antialiased font-sans"> <div class="md:flex min-h-screen"> <div class="w-full md:w-1/2 bg-white flex items-center justify-center"> <div class="max-w-sm m-8"> <div class="text-black text-5xl md:text-15xl font-black"> 429 </div> <div class="w-16 h-1 bg-purple-light my-3 md:my-6"></div> <p class="text-grey-darker text-2xl md:text-3xl font-light mb-8 leading-normal"> Sorry, you are making too many requests to our servers. </p> <a href="http://beta.cybasetech.com/hotcool"> <button class="bg-transparent text-grey-darkest font-bold uppercase tracking-wide py-3 px-6 border-2 border-grey-light hover:border-grey rounded-lg"> Go Home </button> </a> </div> </div> <div class="relative pb-full md:flex md:pb-0 md:min-h-screen w-full md:w-1/2"> <div style="background-image: url('/svg/403.svg');" class="absolute pin bg-cover bg-no-repeat md:bg-left lg:bg-center"> </div> </div> </div> </body> </html>
The server is returning an error because you are making too many requests. You should check the response code of your HTTP request, if it is not 200 then do not attempt to parse it. You may also want to try caching some of your data locally so you are not repeatedly requesting the same data from the server.
Issue mixing variable with mixin with keyframe animation?
First time using SCSS, and testing my knowledge from the Sass-Lang.com guide. According to the guide, it is possible to both set variables and use mixins to simplify your CSS. I was coding an animation where the div is clipped from bottom to top. I used variables to set the initial and final clip-path settings, and used them while calling a mixin. Yet I get the error, 'Invalid CSS after "...slider-initial)": expected "{", was "; }"'. What am I doing wrong? Here is my code: <body> <section id='main'> <div id='left'></div> <div id='right'></div> <section> </body> $slider-initial: inset(0 0 0 0); $slider-final: inset(0 0 100% 0); #mixin slider-clip($slider-state) { -webkit-clip-path: $slider-state; clip-path: $slider-state; } body { height: 100%; width: 100%; margin: 0 auto; } #main { height: 64vh; width: 38vw; margin: 0 auto; margin-top: 10%; position: relative; display: flex; flex-direction: row; justify-content: center; border: 1vh solid black; } #left { order: 1; width: 4%; height: 100%; margin-left: 46%; background: green; } #right { opacity: 1; order: 2; width: 4%; height: 100%; margin: auto; margin-left: 0; animation-name: dropdown; animation-duration: 4s; background: red; } #keyframes dropdown { from { #mixin slider-clip($slider-initial); } to { #mixin slider-clip($slider-final); } }
You called your mixin in a wrong way: #keyframes dropdown { from { #mixin slider-clip($slider-initial); } to { #mixin slider-clip($slider-final); } } In the guide on sass-lang.com, you can see the following example of how to include a mixin: .box { #include border-radius(10px); } Applied to your case, your code should look like this: #keyframes dropdown { from { #include slider-clip($slider-inital); } to { #include slider-clip($slider-final); } }
Zoom In and Out Transition in Codenameone
Inspired by native Android zoomOut for form transitions and iOS app launching zoom effect, which are both really cool... How do I go about implementing zoom In or Out transition for Forms, Dialogs and Containers in Codenameone? I want the transition to have zooming animation like below: #charset "UTF-8"; *, :before, :after { margin: 0; padding: 0; position: relative; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } input, select, button, textarea { -webkit-appearance: none; -moz-appearance: none; appearance: none; font: inherit; color: inherit; } .butt, .input { padding: .75rem; margin: .375rem; background-color: transparent; border-radius: 4px; } .butt:focus, .input:focus { outline: none; } .butt { border: 2px solid #f35626; line-height: 1.375; padding-left: 1.5rem; padding-right: 1.5rem; font-weight: 700; color: #f35626; cursor: pointer; -webkit-animation: hue 60s infinite linear; } .butt--primary { background-color: #f35626; color: #fff; } .input { border: 1px solid #c0c8c9; border-radius: 4px; } .input--dropdown { background-image: url("images/ddown.png"); background-image: url("images/ddown.svg?3"), none; background-repeat: no-repeat; background-size: 1.5rem 1rem; background-position: right center; } h1, .alpha { margin-bottom: 1.5rem; font-size: 3rem; font-weight: 100; line-height: 1; letter-spacing: -.05em; } h2, .beta { margin-bottom: .75rem; font-weight: 400; font-size: 1.5rem; line-height: 1; } #media (min-width: 650px) { .mega { font-size: 6rem; line-height: 1; } } .subhead, .meta { color: #7b8993; } .promo { text-align: center; } p, hr, form { margin-bottom: 1.5rem; } hr { border: none; margin-top: -1px; height: 1px; background-color: #c0c8c9; background-image: -webkit-linear-gradient(0deg, #fff, #c0c8c9, #fff); } a { color: inherit; text-decoration: underline; -webkit-animation: hue 60s infinite linear; } a:hover { color: #f35626; } .wrap { max-width: 38rem; margin: 0 auto; } .island { padding: 1.5rem; } .isle { padding: .75rem; } .spit { padding: .375rem; } html { font: 100%/1.5"Roboto", Verdana, sans-serif; color: #3d464d; background-color: #fff; -webkit-font-smoothing: antialiased; width: 100%; overflow: hidden-x; text-align: center; } #media (min-width: 650px) { html { height: 100%; } html:before { content: ''; display: inline-block; height: 100%; vertical-align: middle; margin-right: -0.25em; } body { display: inline-block; vertical-align: middle; max-width: 38rem; } } .site__header { -webkit-animation: bounceInUp 1s; } .site__title { color: #f35626; background-image: -webkit-linear-gradient(92deg, #f35626, #feab3a); -webkit-background-clip: text; -webkit-text-fill-color: transparent; -webkit-animation: hue 60s infinite linear; } .site__content { -webkit-animation: bounceInUp 1s; -webkit-animation-delay: .1s; } .site__content form { -webkit-animation: bounceInUp 1s; -webkit-animation-delay: .1s; } .animated { -webkit-animation-duration: 1s; animation-duration: 1s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .animated.infinite { -webkit-animation-iteration-count: infinite; animation-iteration-count: infinite; } .animated.hinge { -webkit-animation-duration: 2s; animation-duration: 2s; } .animated.bounceIn, .animated.bounceOut { -webkit-animation-duration: .75s; animation-duration: .75s; } .animated.flipOutX, .animated.flipOutY { -webkit-animation-duration: .75s; animation-duration: .75s; } #-webkit-keyframes zoomIn { from { opacity: 0; -webkit-transform: scale3d(.3, .3, .3); transform: scale3d(.3, .3, .3); } 50% { opacity: 1; } } #keyframes zoomIn { from { opacity: 0; -webkit-transform: scale3d(.3, .3, .3); transform: scale3d(.3, .3, .3); } 50% { opacity: 1; } } .zoomIn { -webkit-animation-name: zoomIn; animation-name: zoomIn; } #-webkit-keyframes zoomOut { from { opacity: 1; } 50% { opacity: 0; -webkit-transform: scale3d(.3, .3, .3); transform: scale3d(.3, .3, .3); } to { opacity: 0; } } #keyframes zoomOut { from { opacity: 1; } 50% { opacity: 0; -webkit-transform: scale3d(.3, .3, .3); transform: scale3d(.3, .3, .3); } to { opacity: 0; } } .zoomOut { -webkit-animation-name: zoomOut; animation-name: zoomOut; } <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1, minimal-ui" /> <link rel="dns-prefetch" href="//fonts.googleapis.com" /> <link rel="dns-prefetch" href="//code.jquery.com" /> <link href='//fonts.googleapis.com/css?family=Roboto:400,100,400italic,700italic,700' rel='stylesheet' type='text/css'> </head> <body> <header class="site__header island"> <div class="wrap"> <span id="animationSandbox" style="display: block;"><h1 class="site__title mega">Zoom me in and out</h1></span> </div> </header> <!-- /.site__header --> <main class="site__content island" role="content"> <div class="wrap"> <form> <select class="input input--dropdown js--animations"> <optgroup label="Zoom Entrances"> <option value="zoomIn">zoomIn</option> </optgroup> <optgroup label="Zoom Exits"> <option value="zoomOut">zoomOut</option> </optgroup> </select> <button class="butt js--triggerAnimation">Animate it</button> </form> <hr /> </div> </main> <!-- /.site__content --> <script src="//code.jquery.com/jquery-1.10.2.min.js"></script> <script> function testAnim(x) { $('#animationSandbox').removeClass().addClass(x + ' animated').one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() { $(this).removeClass(); }); }; $(document).ready(function() { $('.js--triggerAnimation').click(function(e) { e.preventDefault(); var anim = $('.js--animations').val(); testAnim(anim); }); $('.js--animations').change(function() { var anim = $(this).val(); testAnim(anim); }); }); </script> </body> </html>
Probably the closest thing to some of the Android effects is the Morph transition between forms that allows a component to grow into the next form http://www.codenameone.com/blog/mighty-morphing-components.html If you want something closer to the above code you can just position the component in the right location and make it smaller then use animateLayout() to make it grow into place. In the old days we had a FlyIn transition which mapped to this exactly but it used old 3D code. I think it should be trivial to implement though with the affine transform and scale similarly to the FlipTransition.