Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(www): Convert Pullquote to use theme-ui #25351

Merged
merged 4 commits into from
Jun 27, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
323 changes: 147 additions & 176 deletions www/src/components/shared/pullquote.js
Original file line number Diff line number Diff line change
@@ -1,194 +1,165 @@
import React from "react"
import PropTypes from "prop-types"
import styled from "@emotion/styled"

/** @jsx jsx */
import { jsx } from "theme-ui"
import { StarOrnament, QuotationMarkOrnament } from "../../assets/ornaments"
import { mediaQueries } from "gatsby-design-tokens/dist/theme-gatsbyjs-org"

const PullquoteRoot = styled(`blockquote`)`
border: 1px solid ${p => p.theme.colors.pullquote.borderColor};
border-radius: ${p => p.theme.radii[2]};
color: ${p => p.theme.colors.pullquote.color};
font-family: ${p => p.theme.fonts.heading};
font-size: ${p => p.theme.fontSizes[3]};
font-weight: bold;
padding: ${p => p.theme.space[7]} 3rem;
position: relative;
text-indent: ${p => p.theme.space[7]};
margin: ${p => p.theme.space[8]} 0;

/* needed for overriding typography.js style "p *:last-child {"" */
p > & {
margin: ${p => p.theme.space[8]} 0;
}

${mediaQueries.lg} {
line-height: ${p => p.theme.lineHeights.loose};
margin: ${p => p.theme.space[8]} ${p => (p.narrow ? 0 : `-3.5rem`)};
padding: 2.8rem 3.5rem;
text-indent: 1.8rem;

p > & {
margin: ${p => p.theme.space[8]} ${p => (p.narrow ? 0 : `-3.5rem`)};
}
}
`

const Citation = styled(`cite`)`
display: block;
font-style: italic;
font-weight: normal;
margin-top: ${p => p.theme.space[4]};
text-align: right;
`

const QuotationMark = styled(`span`)`
display: flex;
left: ${p => p.theme.space[8]};
position: absolute;
top: ${p => p.theme.space[7]};

svg {
fill: ${p => p.theme.colors.purple[80]};
}

${mediaQueries.lg} {
left: 3rem;
top: 2.8rem;

svg {
fill: ${p => p.theme.colors.purple[80]};
transform: scale(1.1);
}
}
`

const Star = styled(`span`)`
display: flex;
position: absolute;

svg {
height: 100%;
width: 100%;
}

:nth-of-type(1) {
height: 20px;
left: 0;
top: 1.8rem;
transform: translateX(-50%);
width: 20px;

svg {
fill: ${p => p.theme.colors.yellow[40]};
}

${mediaQueries.lg} {
height: 27px;
width: 27px;
}

.variantB & {
left: auto;
right: 0;
top: ${p => p.theme.space[7]};
transform: translate(50%, 0);
}
function Citation({ author }) {
return (
<cite
sx={{
display: `block`,
fontStyle: `italic`,
fontWeight: `normal`,
mt: 4,
textAlign: `right`,
}}
>
&mdash; {author}
</cite>
)
}

.variantC & {
bottom: 0;
left: auto;
right: 12rem;
top: auto;
transform: translate(0, 50%);
}
}
function QuotationMark() {
return (
<span
sx={{
display: `flex`,
position: `absolute`,
left: [8, null, null, 9],
top: [7, null, null, `2.8rem`],
}}
>
<QuotationMarkOrnament
sx={{
fill: `purple.80`,
transform: [null, null, null, `scale(1.1)`],
}}
/>
</span>
)
}

:nth-of-type(2) {
left: 5rem;
height: 14px;
top: 0;
transform: translateY(-50%);
width: 14px;
const starStyle = {
yellow: { size: [`20px`, null, null, `27px`], fill: `yellow.40` },
teal: { size: `14px`, fill: `teal.40` },
red: { size: `12px`, fill: `red.60` },
}

svg {
fill: ${p => p.theme.colors.teal[40]};
}
.variantB & {
bottom: 0;
left: auto;
right: 3rem;
top: auto;
transform: translate(0, 50%);
}
const starPositionStyles = [
{
yellow: { side: `left`, offset: `1.8rem` },
Copy link
Contributor Author

@tesseralis tesseralis Jun 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fk another thing we can do is switch these to percentage points.

So for this one, if offset: `50%` , it will always be 50% between the top and bottom regardless of how tall the pullquote is. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you think it still works out visually, go for it!

teal: { side: `top`, offset: `5rem` },
red: { side: `bottom`, offset: `4rem`, fromEnd: true },
},
{
yellow: { side: `right`, offset: `2rem` },
teal: { side: `bottom`, offset: `3rem`, fromEnd: true },
red: { side: `top`, offset: `7rem`, fromEnd: true },
},
{
yellow: { side: `bottom`, offset: `12rem`, fromEnd: true },
teal: { side: `top`, offset: `9rem`, fromEnd: true },
red: { side: `left`, offset: `3rem` },
},
]

// [X, Y] amount to translate the star for each side (in %)
const starTranslate = {
left: [-50, 0],
right: [50, 0],
top: [0, -50],
bottom: [0, 50],
}

.variantC & {
left: auto;
right: 9rem;
top: 0;
transform: translate(0, -50%);
}
// Get the cross axis of the side the star is on to calculate the offset.
// For example, is a star is on the left side, the star should be offset from the top.
// If `fromEnd` is true, the star will be aligned according to the end instead of the start.
// For example, if `side === left`, then the star is offset from the bottom instead of the top.
function crossAxis(side, fromEnd) {
if ([`left`, `right`].includes(side)) {
return fromEnd ? `bottom` : `top`
} else {
return fromEnd ? `right` : `left`
}
}

:nth-of-type(3) {
bottom: 0;
height: ${p => p.theme.space[3]};
right: 4rem;
transform: translateY(50%);
width: ${p => p.theme.space[3]};

svg {
fill: ${p => p.theme.colors.red[60]};
}

.variantB & {
bottom: auto;
left: auto;
right: 7rem;
top: 0;
transform: translate(0%, -50%);
}
function Star({ color, order }) {
const { size, fill } = starStyle[color]
const { side, offset, fromEnd } = starPositionStyles[order][color]
const translate = starTranslate[side]

.variantC & {
top: 3rem;
left: 0;
transform: translate(-50%, 0);
}
}
`
return (
<span
sx={{
display: `flex`,
position: `absolute`,
width: size,
height: size,
[side]: 0,
[crossAxis(side, fromEnd)]: offset,
transform: `translate(${translate[0]}%,${translate[1]}%)`,
}}
>
<StarOrnament sx={{ height: `100%`, width: `100%`, fill }} />
</span>
)
}

const variants = [`A`, `B`, `C`]
let instancesCounter = -1

const Pullquote = ({ citation, narrow = false, children }) => {
function Stars() {
// We want to vary the placement of the stars so consecutive pullquotes
// have stars in different positions.
instancesCounter += 1
const className = `variant${variants[instancesCounter % variants.length]}`

const order = instancesCounter % starPositionStyles.length
return (
<PullquoteRoot narrow={narrow} className={className}>
{children}
{citation && <Citation>&mdash; {citation}</Citation>}
<QuotationMark>
<QuotationMarkOrnament />
</QuotationMark>
<div>
<Star>
<StarOrnament />
</Star>
<Star>
<StarOrnament />
</Star>
<Star>
<StarOrnament />
</Star>
</div>
</PullquoteRoot>
<div>
{[`yellow`, `red`, `teal`].map(color => (
<Star key={color} color={color} order={order} />
))}
</div>
)
}

Pullquote.propTypes = {
children: PropTypes.node.isRequired,
narrow: PropTypes.bool,
/**
* A component used to call out a quote in the blog.
* It applies borders and styles that make a section of the content pop out to readers.
*
* @param citation the reference of the person or entity that made the quoted statement
* @param children the content to be quoted
* @param narrow
* Keep the pullquote inside the parent container.
* Should be used if using the pullquote in the docs to make sure it stays inside its container.
*/
export default function Pullquote({ citation, narrow = false, children }) {
return (
<blockquote
sx={{
borderWidth: `1px`,
borderStyle: `solid`,
borderColor: `pullquote.borderColor`,
borderRadius: 2,
color: `pullquote.color`,
fontFamily: `heading`,
fontSize: 3,
fontWeight: `bold`,
py: [7, null, null, `2.8rem`],
px: [9, null, null, 10],
position: `relative`,
textIndent: [t => t.space[7], null, null, `1.8rem`],
lineHeight: [null, null, null, `loose`],
my: 8,
mx: [null, null, null, narrow ? 0 : `-3.5rem`],
// Needed for overriding typography.js style "p *:last-child {"""
"p > &": {
my: 8,
mx: [null, null, null, narrow ? 0 : `-3.5rem`],
},
}}
>
{children}
{citation && <Citation author={citation} />}
<QuotationMark />
<Stars />
</blockquote>
)
}

export default Pullquote