Open kylpo opened 4 years ago
And a more complicated Link component:
<box
tag={Link}
tag-to={props.to}
grow={props.grow}
padding={{
$: props.kind,
_: 20, // default case when props.kind isn't 'filled' or 'transparent'
filled: "20px 40px",
transparent: 16,
}}
style={{
borderRadius: { varyOn: props.kind, filled: 50 },
backgroundColor: {
varyOn: `${props.kind}_${props.color}`,
filled_white: WHITE,
},
boxShadow: {
varyOn: (props) => props.kind === "outlined" && props.color,
white: {
_: `0 0 0 4px ${WHITE}`,
":hover": `0 0 0 6px ${WHITE}`,
},
grey: {
_: `0 0 0 4px ${GREY}`,
":hover": `0 0 0 6px ${GREY}`,
},
},
}}
className={props.className}
>
<txt
bold
center
as="div"
style="t4"
color={WHITE}
transform={props.kind === "outlined" && "uppercase"}
>
{props.children}
</txt>
</box>
Think of the varyOn
/$
/_variant
as a switch statement, and the keys below are cases.
Could use template literals for a new syntax?
padding={`
${props.kind}: {
filled: "20px 40px",
transparent: 16,
}
`}
And function(ish) form
padding={`
${props.kind === "outlined" && props.color}: {
filled: "20px 40px",
transparent: 16,
}
`}
Here's the normal Linaria Text to compare against:
import React from "react"
import { css, cx } from "linaria"
import { MEDIUM, LARGE_UP } from "../util/breakpoints"
import {
BlACK,
WHITE,
SILVER,
GREY,
PRIMARY,
SECONDARY,
SECONDARY_ACCENT,
DARK,
} from "../util/colors"
import { IS_DEV } from "../util/environment"
/* Prop -> property maps */
const TEXT_FONT = "Arial, Helvetica, sans-serif"
// const HEADING_FONT = "Arial Black, sans-serif"
const HEADING_FONT = "Arial, Helvetica, sans-serif"
const BOLD_CLASS = css`
font-weight: bold;
`
const CENTER_CLASS = css`
text-align: center;
`
const ALL_CAPS_CLASS = css`
text-transform: uppercase;
`
const styles = {
t: css`
font-family: ${TEXT_FONT};
`,
t1: css`
font-family: ${TEXT_FONT};
font-size: 20px;
line-height: 24px;
@media ${MEDIUM} {
font-size: 24px;
line-height: 32px;
}
@media ${LARGE_UP} {
font-size: 26px;
line-height: 34px;
}
`,
t2: css`
font-family: ${TEXT_FONT};
font-size: 18px;
line-height: 28px;
@media ${MEDIUM} {
font-size: 20px;
line-height: 24px;
}
@media ${LARGE_UP} {
font-size: 24px;
line-height: 32px;
}
`,
t3: css`
font-family: ${TEXT_FONT};
font-size: 16px;
/* line-height: 18px; */
line-height: 20px;
letter-spacing: 0.3px;
@media ${MEDIUM} {
font-size: 18px;
line-height: 28px;
}
@media ${LARGE_UP} {
font-size: 20px;
/* line-height: 28px; */
line-height: 30px;
}
`,
t4: css`
font-family: ${TEXT_FONT};
font-size: 16px;
line-height: 24px;
@media ${LARGE_UP} {
font-size: 18px;
line-height: 28px;
}
`,
t5: css`
font-family: ${TEXT_FONT};
font-size: 14px;
line-height: 20px;
@media ${LARGE_UP} {
font-size: 16px;
line-height: 24px;
}
`,
t6: css`
font-family: ${TEXT_FONT};
font-size: 13px;
line-height: 20px;
`,
h1: css`
font-family: ${HEADING_FONT};
font-weight: bold;
font-size: 44px;
line-height: 52px;
@media ${MEDIUM} {
font-size: 60px;
line-height: 68px;
}
@media ${LARGE_UP} {
font-size: 84px;
line-height: 96px;
}
`,
h2: css`
font-family: ${HEADING_FONT};
font-weight: bold;
font-size: 32px;
line-height: 36px;
@media ${MEDIUM} {
font-size: 44px;
line-height: 52px;
}
@media ${LARGE_UP} {
font-size: 64px;
line-height: 72px;
}
`,
h3: css`
font-family: ${HEADING_FONT};
font-weight: bold;
font-size: 32px;
line-height: 34px;
@media ${MEDIUM} {
font-size: 36px;
line-height: 44px;
}
@media ${LARGE_UP} {
font-size: 50px;
line-height: 52px;
}
`,
h4: css`
font-family: ${HEADING_FONT};
font-weight: bold;
font-size: 26px;
line-height: 34px;
@media ${MEDIUM} {
font-size: 32px;
line-height: 40px;
}
@media ${LARGE_UP} {
font-size: 40px;
line-height: 48px;
}
`,
h5: css`
font-family: ${HEADING_FONT};
font-weight: bold;
font-size: 24px;
line-height: 32px;
@media ${MEDIUM} {
font-size: 26px;
line-height: 34px;
}
@media ${LARGE_UP} {
font-size: 32px;
line-height: 40px;
}
`,
h6: css`
font-family: ${HEADING_FONT};
font-weight: bold;
font-size: 20px;
line-height: 28px;
@media ${LARGE_UP} {
font-size: 26px;
line-height: 34px;
}
`,
}
const colors = {
white: css`
color: ${WHITE};
`,
black: css`
color: ${BlACK};
`,
dark: css`
color: ${DARK};
`,
silver: css`
color: ${SILVER};
`,
grey: css`
color: ${GREY};
`,
primary: css`
color: ${PRIMARY};
`,
secondary: css`
color: ${SECONDARY};
`,
secondaryAccent: css`
color: ${SECONDARY_ACCENT};
`,
unset: undefined,
}
interface Props {
style: keyof typeof styles
children: React.ReactNode
color?: keyof typeof colors
className?: string
bold?: boolean
center?: boolean
allCaps?: boolean
html?: boolean
inlineStyle?: React.CSSProperties
as?: keyof JSX.IntrinsicElements
}
export const Text = ({
as: Comp = "span",
color = "dark",
...props
}: Props) => (
<Comp
className={cx(
styles[props.style],
colors[color],
props.bold && BOLD_CLASS,
props.center && CENTER_CLASS,
props.allCaps && ALL_CAPS_CLASS,
props.className
)}
style={props.inlineStyle}
data-text-style={IS_DEV ? props.style : undefined}
>
{props.html ? (
<span
dangerouslySetInnerHTML={{
__html: `${props.children}`,
}}
/>
) : (
props.children
)}
</Comp>
)
How to Use Block Variations in WordPress | CSS-Tricks
4Catalyzer/astroturf: An "artificial" CSS-in-JS for those that want it all.
function Button({ variant, children }) {
return (
<button
variant={variant}
css={css`
color: black;
border: 1px solid black;
background-color: white;
&.variant-primary {
color: blue;
border: 1px solid blue;
}
&.variant-secondary {
color: green;
}
`}
>
{children}
</button>
);
}
variants: {
color: {
white: {
backgroundColor: 'transparent',
color: 'hsl(206,10%,44%)',
':hover': {
backgroundColor: 'white',
color: 'hsl(206,10%,5%)',
},
},
}
}
Chakra uses base
for its default:
<Box width={{ base: 1, sm: 1 / 2, md: 1 / 4 }} />
Chakra UI | Design System built with React
And variants defined in a config:
const theme = extendTheme({
components: {
Button: {
// 1. We can update the base styles
baseStyle: {
fontWeight: "bold", // Normally, it's "semibold"
},
// 2. We can add a new button size or extend existing
sizes: {
xl: {
h: "56px",
fontSize: "lg",
px: "32px",
},
},
// 3. We can add a new visual variant
variants: {
"with-shadow": {
bg: "red.400",
boxShadow: "0 0 2px 2px #efdfde",
},
// 4. We can override existing variants
solid: (props) => ({
bg: "red.400",
}),
},
},
},
})
Sitches has some cool ideas, too: Variants — Stitches
Including compoundVariant
, boolean, and default variants.
The Future of the Front-End (with Pedro Duarte) – Stitches CSS-in-JS Demo - YouTube might be worth a re-watch.
https://cva.style/docs/getting-started/variants
// components/button.ts
import { cva } from "class-variance-authority";
const button = cva("…", {
variants: {
intent: { primary: "…", secondary: "…" },
size: { small: "…", medium: "…" },
},
compoundVariants: [
// Applied via:
// `button({ intent: "primary", size: "medium" })`
// or
// `button({ intent: "secondary", size: "medium" })`
{
intent: ["primary", "secondary"],
size: "medium",
class: "…",
},
],
});
2 kinds of dynamic:
Helpful links/ideas:
Here are some of my attempts for syntax:
A
$
version:an array solution: