z-ui 跨框架 2.5D 组件库 - 2. css 篇

388 阅读2分钟

互相学习,共同进步,才是王道

加好友回复 组件库 进群, 互相学习,共同进步

image.png

关联文章

搭建一个跨框架的 2.5D 组件库:0. 开篇

z-ui 跨框架 2.5D 组件库 - 1. 项目初始化

关于 CSS 的诉求

  • 编译 BEM 规范的 css。
  • 使用 Sass 作为 css 的预处理器。
  • 每个组件的 css 样式,可以单独打包。
  • 尽可能地减少组件库样式与用户样式的冲突。
  • 可以让用户方便地修改组件样式。
  • 能支持主题切换。

编写类名生成工具

希望 css 类名是遵循 BEM 规范的。大致是这样的写法

// block 代码块  element 元素   modifier  装饰   state 状态
// z-button
// z-button__element // 中间两个下划线
// z-button__element--disabled
// is-checked is-enabled

下面写一个工具类,可以快速生成这样的类名

export const createNamespace = (name: string) => {
  const prefixName = `z-${name}`;
  return createBEM(prefixName);
};

使用不同的函数生成不同组合的类名

const createBEM = (prefixName: string) => {
  const b = (blockSuffix: string) =>
    _bem({
      prefixName,
      blockSuffix,
    });

  const e = (element: string) =>
    element
      ? _bem({
          prefixName,
          element,
        })
      : '';

  const m = (modifier: string) =>
    modifier
      ? _bem({
          prefixName,
          modifier,
        })
      : '';

  const bm = (blockSuffix: string, modifier: string) =>
    blockSuffix && modifier
      ? _bem({
          prefixName,
          blockSuffix,
          modifier,
        })
      : '';

  const be = (blockSuffix: string, element: string) =>
    blockSuffix && element
      ? _bem({
          prefixName,
          blockSuffix,
          element,
        })
      : '';

  const em = (element: string, modifier: string) =>
    element && modifier
      ? _bem({
          prefixName,
          element,
          modifier,
        })
      : '';

  const bem = (blockSuffix: string, element: string, modifier: string) =>
    blockSuffix && element && modifier
      ? _bem({
          prefixName,
          blockSuffix,
          element,
          modifier,
        })
      : '';

  const is = (name: string, state: boolean) => (state ? `is-${name}` : '');

  return {
    b,
    e,
    m,
    be,
    bm,
    em,
    bem,
    is,
  };
};

根据传值进行拼接

const _bem = (options: {
  prefixName: string;
  blockSuffix?: string;
  element?: string;
  modifier?: string;
}) => {
  if (options.blockSuffix) {
    options.prefixName += `-${options.blockSuffix}`;
  }

  if (options.element) {
    options.prefixName += `__${options.element}`;
  }

  if (options.modifier) {
    options.prefixName += `--${options.modifier}`;
  }

  return options.prefixName;
};

测试一下,最终的结果是这样的

image.png

使用样式生成函数

<script lang="ts">
  import { createNamespace } from '../../../utils/create';
  const bem = createNamespace('button');
  const _class = [bem.b('')].join(' ');
</script>

<button
  class={_class}
  on:click
>
  <slot></slot>
</button>

使用 Sass 编写 css 样式

使用 Sass mixins 快速生成类名。

mixins/config.scss

$namespace: 'z';
$element-separator: '__';
$modifier-separator: '--';
$state-prefix: 'is-';

```scss
@use 'config' as *; // @use 和 import 的区别. @use 不会重复导入样式
@forward 'config'; // 暴漏 config 下的 css ,这样别的文件也可以使用

// .z-button()
@mixin b($block) {
  $B: $namespace + '-' + $block;
  .#{$B} {
    @content;
  }
}

// .z-button.is-xxx
@mixin when($state) {
  @at-root {
    &.#{$state-prefix + $state} {
      @content;
    }
  }
}

// &--primary => .z-button--primary
@mixin m($modifier) {
  @at-root {
    #{& + $modifier-separator + $modifier} {
      @content;
    }
  }
}

// &__header => .z-button__header
@mixin e($element) {
  @at-root {
    #{& + $element-separator + $element} {
      @content;
    }
  }
}

使用 Sass mixins 编写 css 样式

button.scss

@use 'mixins/mixins.scss' as *;

@include b(button) {
  color: #090909;
  padding: 8px 15px;
  width: 100%;
  height: 32px;
  font-size: 16px;
  border-radius: 0.5em;
  background: #e8e8e8;
  cursor: pointer;
  border: 1px solid #e8e8e8;
  transition: all 0.3s;
  box-shadow:
    6px 6px 12px #c5c5c5,
    -6px -6px 12px #ffffff;

  &:active {
    color: #666;
    box-shadow:
      inset 4px 4px 12px #c5c5c5,
      inset -4px -4px 12px #ffffff;
  }

  &:focus,
  &:hover {
    border: 0;
    outline: none;
  }
}

最终得到的按钮样式是这样的

Kapture 2024-09-24 at 23.19.31.gif

UI 风格

我希望写一套新拟物主义风格的 UI. 就像下面这样

button image.png

Card

image.png

switch

image.png

radio

image.png

input

image.png

更多组件,希望大家一起提供