我正在为设计系统创建一个 React 库并styled-jsx
用作 CSS-in-JS 解决方案。我们的 Web 应用程序由我们提供支持,Next.js
并且我们可以高效地使用,styled-jsx
并且因为 Vercel 也是背后的公司,styled-jsx
我们考虑在我们的设计系统 React 库中使用这个库。
我已经按照这篇文章来引导 React 库,唯一的区别是使用styled-jsx
而不是styled components
.
问题在于这styled-jsx
并没有将 CSS 的范围限制在组件级别。我创建了一个Text
组件,它基本上是排版的包装器。这是我编写的组件的代码。
索引.tsx
/* eslint-disable no-use-before-define */
import React from 'react';
import { ThemeContext } from '../context/index';
import { RAVEN, SWAN } from '../colors/index';
type TextProps = {
children: string;
className?: string;
textColor?: string;
margin?: string;
variant: string;
};
function Text(props: TextProps) {
let className = 'text';
switch (props.variant) {
case 'h1': {
className += ' text-heading-1';
break;
}
case 'h2': {
className += ' text-heading-2';
break;
}
case 'h3': {
className += ' text-heading-3';
break;
}
case 'h4': {
className += ' text-heading-4';
break;
}
case 'h5': {
className += ' text-heading-5';
break;
}
case 'h6': {
className += ' text-heading-6';
break;
}
case 'body': {
className += ' text-body';
break;
}
case 'ol': {
className += ' text-overline';
break;
}
case 'button': {
className += ' text-button';
break;
}
case 'button2': {
className += ' text-button-2';
break;
}
case 'caption': {
className += ' text-caption';
break;
}
case 'st1': {
className += ' text-subtitle-1';
break;
}
case 'st2': {
className += ' text-subtitle-2';
break;
}
default: {
className += ' text-body';
break;
}
}
return (
<ThemeContext.Consumer>
{(theme) => (
<p className={`${className} ${props.className}`}>
{props.children}
<style jsx>
{`
.text {
width: fit-content;
margin: ${props.margin ? props.margin : '0'};
color: ${props.textColor
? props.textColor
: theme === 'swan'
? RAVEN.EXTRA_DARK
: SWAN.LIGHT};
font-family: 'Kanit', sans-serif;
text-transform: lowercase;
}
.text-heading-1 {
font-size: 61px;
font-weight: 400;
line-height: 92px;
}
.text-heading-2 {
font-size: 48.8px;
font-weight: 400;
line-height: 76px;
}
.text-heading-3 {
font-size: 39px;
font-weight: 400;
line-height: 60px;
}
.text-heading-4 {
font-size: 31.25px;
font-weight: 500;
line-height: 48px;
}
.text-heading-5 {
font-size: 25px;
font-weight: 600;
line-height: 40px;
}
.text-heading-6 {
font-size: 20px;
font-weight: 500;
line-height: 32px;
}
.text-body {
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
.text-overline {
font-size: 12.8px;
font-weight: 500;
line-height: 20px;
}
.text-button {
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
.text-button-2 {
font-size: 20px;
font-weight: 700;
line-height: 32px;
}
.text-caption {
font-size: 12.8px;
font-weight: 400;
font-style: italic;
line-height: 20px;
}
.text-subtitle-1 {
font-size: 16px;
font-weight: 500;
line-height: 24px;
}
.text-subtitle-2 {
font-size: 12.8px;
font-weight: 700;
line-height: 20px;
}
`}
</style>
</p>
)}
</ThemeContext.Consumer>
);
}
export { TextProps, Text };
现在我尝试在我们的 Web 应用程序中使用这个组件,这里是我使用它的页面的代码。
测试版.tsx
import React from 'react';
import { Container, Text, ThemeContext } from '@deriva-inc/davinci-react';
function BETA() {
return (
<ThemeContext.Provider value="raven">
<Container>
<Text margin="0" variant="h1">
h1. heading 1
</Text>
<Text margin="0" variant="h2">
h2. heading 2
</Text>
<Text
margin="0"
variant="h3"
className="heading-3-custom-1"
textColor="#FF0000"
>
h3. heading 3
</Text>
<Text
margin="0"
variant="h3"
className="heading-3-custom-2"
textColor="#00FF00"
>
h3. heading 3
</Text>
<Text
margin="0"
variant="h3"
className="heading-3-custom-3"
textColor="#0000FF"
>
h3. heading 3
</Text>
<Text margin="0" variant="h4">
h4. heading 4
</Text>
<Text margin="0" variant="h5">
h5. heading 5
</Text>
<Text margin="0" variant="h6">
h6. heading 6
</Text>
<Text margin="0" variant="body">
body
</Text>
<Text margin="0" variant="ol">
overline
</Text>
<Text margin="0" variant="button">
button
</Text>
<Text margin="0" variant="button2">
button 2
</Text>
<Text margin="0" variant="caption">
caption
</Text>
<Text margin="0" variant="st1">
subtitle 1
</Text>
<Text margin="0" variant="st2">
subtitle 2
</Text>
<p className="text text-aayush">Aayush</p>
</Container>
<style jsx>
{`
.text {
color: #00ff00;
}
`}
</style>
<style jsx global>
{`
main {
margin: 60px;
}
.heading-3-custom-1::selection {
background: #43bd99;
}
.heading-3-custom-2::selection {
background: #03865f;
}
.heading-3-custom-3::selection {
background: #409978;
}
`}
</style>
</ThemeContext.Provider>
);
}
export default BETA;
这是页面的呈现方式。
如您所见,我通过道具为所有三个标题 3 文本应用了不同的颜色,但在主题上下文中都以默认颜色呈现(即White
)。当我调试页面时,我发现了这一点。
所以,我发现了问题。组件通过 prop 获取颜色,但由于 CSS 不限于组件,所有Text
组件都在全局范围内呈现它们的 CSS,并且我们知道最后应用的 CSS 将按优先顺序排列,因此所有组件正在拿Text
组件渲染的 CSS Subtitle 2
。我不知道我在这里缺少什么或为什么它没有按预期工作。
我知道我们可以切换到styled-components
,如果我们找不到解决这个问题的方法,我们就会这样做。任何帮助,将不胜感激。谢谢。