我们如何放弃使用样式系统来创建组件并发明自己的自行车

大家好!我叫Sasha,我是Quarkly的联合创始人兼兼职首席开发人员。在本文中,我想谈谈我们坚持的原子CSS概念,再加上Styled-System功能的缺点(以及Rebass,作为使用此库的特例),如何鼓励我们创建自己的工具,我们称之为Atomize。

小序言。我们的Quarkly项目是图形编辑器(例如Figma,Sketch)和站点设计器(例如Webflow)的结合,并附加了经典IDE固有的功能。关于Quarkly,我们将写一个单独的文章,有要说的内容和要显示的内容,但是今天我们将讨论上面提到的Atomize。

Atomize是整个项目的基础,它使我们能够解决使用Styled-System和Rebass无法解决或难以解决的问题。至少,该解决方案将不太优雅。

如果现在没有时间压倒整个文章,那么您可以在我们的GitHub上更加熟悉Atomize

为了使相识更加愉快,我们发起了使用Atomize组装反应组件的竞赛。有关更多信息,请参见文章末尾。

一切如何开始


开始开发Quarkly,我们同意,我们希望使用户能够在组件上进行排版,而无需使用单独的CSS文件。与内联样式相比,使代码尽可能简化,但保留所有CSS功能。

这项任务不是创新性的,乍一看,借助Styled-System和Rebass可以完全解决。但是,此功能对我们来说还不够,此外,我们还遇到以下问题:

  • 有断点的不舒服的工作;
  • 缺乏为状态悬停,焦点等编写样式的能力;
  • 在我们看来,处理主题的机制不够灵活。

什么是原子化(简要)


图片

在Atomize的关键功能中,我们可以重点介绍以下内容:

  • 使用复合css-properties中主题的变量的能力;
  • 支持悬停和任何其他伪类;
  • 每个属性的短别名(如emmet中一样);
  • 能够为特定断点指定样式的能力,同时保持标记的可读性;
  • 简约的界面。

Atomize有两个主要目的:

  • 创建支持原子CSS和主题的组件;
  • 在Quarkly项目中创建用于交互式编辑的小部件。

雾化使用说明


在开始之前,您必须建立依赖关系:

npm i react react-dom styled-components @quarkly/atomize @quarkly/theme

Atomize是样式化组件的包装,并具有类似的API。使用所需元素的名称来调用方法就足够了:

import atomize from '@quarkly/atomize';
 
const MyBox = atomize.div();

在输出中,我们获得了一个react组件,可以接受任何CSS作为道具。
为了易于使用,开发了属性别名系统。例如,bgc === backgroundColor

ReactDOM.render(<MyBox bgc="red" />, root);

可在此处找到属性和别名的完整列表

还提供了React继承机制:

const MySuperComponent = ({ className }) => {
   // some logic here
   return <div className={className} />;
};
 
const MyWrappedComponent = atomize(MySuperComponent);

处理主题


在我看来,关于这一点,有必要告诉更多。Quarkly中的主题基于CSS变量。关键功能是能够重用道具和主题本身的变量,而无需以模板函数的形式进行其他抽象以及用户随后进行的其他处理。

要使用主题中的变量,只需在主题中描述属性并使用前缀“-”引用此属性即可。

变量可以像在JSX中一样使用:

import Theme from "@quarkly/theme";
 
const theme = {
   colors: {
       dark: "#04080C",
   },
};
export const MyComp = () => (
   <Theme>
       <Box bgc="--colors-dark" height="100px" width="100px" />
   </Theme>
);

(颜色-04080C可通过--colors-dark属性获得)

因此,在主题本身中:

import Theme from "@quarkly/theme";
 
const theme = {
   colors: {
       dark: "#04080C",
   },
   borders: {
       dark: "5px solid --colors-dark",
   },
};
export const MyComp = () => (
   <Theme>
       <Box border="--borders-dark" height="100px" width="100px" />
   </Theme>
);

(我们重用了颜色中的变量,将其连接到borders主题)

对于JSX标记中的颜色,提供了一种简化的语法:

import Theme from "@quarkly/theme";
 
const theme = {
   colors: {
       dark: "#04080C",
   },
};
export const MyComp = () => (
   <Theme>
       <Box bgc="--dark" height="100px" width="100px" />
   </Theme>
);

对于使用媒体表达,主题有一个断点。
您可以以断点键名的形式向任何属性添加前缀。

import Theme from "@quarkly/theme";
 
const theme = {
   breakpoints: {
       sm: [{ type: "max-width", value: 576 }],
       md: [{ type: "max-width", value: 768 }],
       lg: [{ type: "max-width", value: 992 }],
   },
   colors: {
       dark: "#04080C",
   },
   borders: {
       dark: "5px solid --colors-dark",
   },
};
export const MyComp = () => (
   <Theme>
       <Box
           md-bgc="--dark"
           border="--borders-dark"
           height="100px"
           width="100px"
       />
   </Theme>
);

主题的源代码可以在这里找到

特效


Atomize和样式化系统之间的主要区别是“效果”。它是什么,为什么需要它?
假设您创建了一个Button组件,更改了其颜色和边框,但是如何将样式分配给悬停,焦点等呢?在这里,这些效果可以挽救。

创建组件时,只需使用配置传送对象:

const MySuperButton = atomize.button({
 effects: {
   hover: ":hover",
   focus: ":focus",
   active: ":active",
   disabled: ":disabled",
 },
});

键是道具名称中的前缀,值是CSS选择器。因此,我们关闭了对所有伪类的需求。

现在,如果我们将悬停前缀指定给任何CSS属性,那么它将以一定的效果应用。例如,当您将鼠标悬停在上方时:

ReactDOM.render(<MySuperButton hover-bgc="blue" />, root);

您还可以将效果与媒体表达式结合使用:

ReactDOM.render(<MySuperButton md-hover-bgc="blue" />, root);

一些例子


为了可视化上面的信息,现在让我们组装一些有趣的组件。我们准备了两个示例:


在第二个示例中,我们使用了大多数功能以及一个外部API。

但这还不是全部


如上所述,Atomize的第二个目的是基于自定义react组件在Quarkly中创建小部件。

为此,只需将组件包装在Atomize中并描述其配置,以便Quarkly可以了解可以交互编辑的属性:

export default atomize(PokemonCard)(
 {
   name: "PokeCard",
   effects: {
     hover: ":hover",
   },
   description: {
     // past here description for your component
     en: "PokeCard — my awesome component",
   },
   propInfo: {
     // past here props description for your component
     name: {
       control: "input",
     },
   },
 },
 { name: "pikachu" }
);

组件的配置字段如下所示:

  • 特效 -定义浏览器伪类(悬停,焦点等);
  • description-光标悬停在其名称上方时将显示的组件的描述;
  • propInfo-控件的配置,这些控件将显示在右侧面板(“ props”选项卡)中。

如何确定将在右侧面板(“ props”选项卡)上显示的道具:

propInfo: {
   yourCustomProps: { //  
       description: { en: "test" }, //    
       control: "input" //  
   }
}

可能的控制选项:

  • 输入
  • 选择
  • 颜色
  • 字形
  • 阴影
  • 过渡
  • 转变
  • 过滤,
  • 背景
  • 复选框图标,
  • 无线电图标
  • 广播组
  • 复选框。

再举一个例子。在这里,我们将组件添加到系统中,现在我们可以进行交互编辑了:


感谢那些精通本书的人!对于造成的混淆,我事先表示歉意,这是撰写此类文章的首次经验。对此我表示感谢。

现在是比赛!


为了使社区对与Atomize的更近距离接触更加感兴趣,我们决定遵循简单易懂的方式(例如Atomize本身)-我们正在发起竞赛!

有关条款,规则和奖品的所有信息都可以在竞赛官方网站上找到

简而言之:要参与并赢得胜利,您需要在React上提出(或找到一个现成的)有趣且有用的组件,并使它适应Atomize的需求。我们将一次选择并授予多个类别的获奖者。如果将您的组件添加到Quarkly,则我们的团队还会提供其他奖励。

All Articles