【Nova UI】十三、打造组件库之按钮组件(中):样式雕琢全攻略

序言

在上一篇文章中,我们已成功搭建起 Vue 按钮组件的基本架构 🏗️,赋予其强大的核心功能与流畅的交互逻辑。此刻,一个功能完备的按钮雏形已然呈现。然而,在追求卓越用户体验的道路上,仅有功能远远不够,样式的精心雕琢同样关键。就如同打造一辆超级跑车,强大的引擎是基础,但炫酷的外观才是吸引众人目光的焦点。接下来,我们将一同踏入按钮组件样式的奇幻世界,探索如何通过色彩 🌈、形状 🔳、阴影 🖤 等元素,赋予按钮独特魅力,使其在前端界面中脱颖而出。

样式 UI 图:设计蓝图引领方向 🗺️

在正式动工之前,还是先给大家展示一下 Element 样式 UI 图。从不同场景下按钮的颜色搭配,到按钮的整体形状,每一个细节都一目了然。

按钮基础样式实现:构建坚实的基石 🧱

在组件库的开发中,为了保证一致性,有些样式往往是统一规范的,例如高度、内外边距以及字体大小等。我们先实现按钮组件那些基本不变的样式,代码如下:

scss 复制代码
@include b(button) {
  display: inline-flex;
  vertical-align: middle;
  justify-content: center;
  align-items: center;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  outline: none;
  user-select: none;
  transition: 0.1s;
  
  padding: 0 getVariableValue('space');
  height: getVariableValue('size');
  font-size: getVariableValue('font-size');
  
  border-width: getVariableValue('border-width');
  border-style: getVariableValue('border-style');
  border-radius: getVariableValue('border-radius');

  & + & {
    margin-left: getVariableValue('space');
  }
}

这里利用了全局定义的变量,通过 getVariableValue 函数来获取对应的属性值,就如同从一个装满各种样式配件的宝库中,精准地取出我们需要的零件,为按钮打造出统一、规范的基础样式。实现后的样式效果如下图,可以看到,按钮已经初步具备了整齐、有序的外观,为后续的个性化样式设计奠定了坚实的基础。

实现思路:颜色变幻的魔法密码 🔮

我们知道,按钮在不同场景下的样式区别主要体现在边框颜色、字体颜色以及背景颜色上,并且在默认、禁用、悬停这三种情况下,会展示出不同深度的颜色。那如何实现这种神奇的颜色变化呢?答案就是通过定义变量,巧妙地修改变量的颜色来实现各种情况下的样式变化。接下来,让我们一步步揭开这个魔法的奥秘。

初始化变量、默认值:为魔法准备材料 📦

scss 复制代码
$button: () !default;
$button: map.merge(
  (
    'font-color': getVariableValue('font-color'),
    'border-color': getVariableValue('border-color'),
    'background-color': getVariableValue('fill-color'),

    'hover-font-color': getVariableValue('font-color', 'hover'),
    'hover-border-color': getVariableValue('color', 'primary', 'light-7'),
    'hover-background-color': getVariableValue('color', 'primary', 'light-9'),

    'disabled-font-color': getVariableValue('font-color', 'disabled'),
    'disabled-border-color': getVariableValue('border-color', 'light'),
    'disabled-background-color': getVariableValue('fill-color'),
  ),
  $button
);
@include b(button) {
  @include set-all-variable-from-map('button', $button);
}

首先,咱们来看看代码开头部分的变量定义与合并操作。
$button: ()!default; 这行代码声明了一个名为 $button 的 SCSS 变量,初始它被设置为空映射(map),这里的 !default 标记意味着如果这个变量在别处已经被定义过了,那它就会保留之前的值,否则就使用当前这个空映射的初始设定,这样的写法增加了代码的灵活性和可扩展性。

紧接着,$button: map.merge(...) 这部分可是关键所在。map.merge 是将两个映射合并成一个新的映射,并且后面传入的映射参数会覆盖前面相同键名的值。

然后各个属性通过getVariableValue函数获取默认值。最后通过 set-all-variable-from-map('button', $button)将这些映射的属性设置成变量,如'font-color': getVariableValue('font-color'),属性将会编译成--n-button-font-color: var(--n-font-color)var(--n-font-color)就是getVariableValue('font-color')拿到的具体的变量值。

设置初始样式:点亮魔法的第一束光 🌟

scss 复制代码
@include b(button) {
  color: getVariableValue('button', 'font-color');
  border-color: getVariableValue('button', 'border-color');
  background-color: getVariableValue('button', 'background-color');
  &:hover {
    color: getVariableValue('button', 'hover-font-color');
    border-color: getVariableValue('button', 'hover-border-color');
    background-color: getVariableValue('button', 'hover-background-color');
  }}

color: getVariableValue('button', 'font-color')这个属性举例,最后会编译成color: var(--n-button-font-color)。这段代码让按钮在默认状态下呈现出我们设定的颜色,并且在鼠标悬停时,能够巧妙地变换颜色,给用户带来直观的交互反馈。到此我们的基本工作已经做完。实现的效果如下图:

scene场景样式具体实现:场景变换的魔法盛宴 🎉

接下来,我们要为按钮在不同场景下赋予独特的色彩风格,让它能够根据不同的使用场景,展现出最合适的外观。

辅助混入:魔法配方的秘籍 📜

scss 复制代码
@mixin button-action-scene-color($scene) {
  $scene-color-types: (
    '': (
      'font-color': (
        'color',
        'white'
      ),
      'border-color': (
        'color',
        $scene
      ),
      'background-color': (
        'color',
        $scene,
      ),
    ),
    'hover': (
      'font-color': (
        'color',
        'white'
      ),
      'border-color': (
        'color',
        $scene,
        'light-3',
      ),
      'background-color': (
        'color',
        $scene,
        'light-3',
      ),
    ),
    'disabled': (
      'font-color': (
        'color',
        'white'
      ),
      'border-color': (
        'color',
        $scene,
        'light-5',
      ),
      'background-color': (
        'color',
        $scene,
        'light-5',
      ),
    )
  );
  @each $action, $colorMap in $scene-color-types {
    @each $color, $list in $colorMap {
      @include set-variable-from-global((button, $action, $color), $list);
    }
  }
}

这个名为 button-action-scene-color 的混入接收 $scene 参数,用来指定具体场景。

在混入内部,定义了 $scene-color-types 这个映射,它划分了默认、悬停、禁用三种状态,且针对每种状态设置了字体、边框、背景颜色的相关取值规则。比如默认状态下,边框和背景颜色会依据 $scene 参数来确定,悬停和禁用状态则在此基础上结合如 light-3light-5 等深浅标识获取相应颜色值。

而后通过两层嵌套的 @each 循环,调用 set-variable-from-global ,将各状态下设定好的颜色值应用到按钮对应的属性上,从而实现不同场景及状态下按钮颜色的准确呈现,助力打造出美观又符合交互逻辑的按钮样式。

场景循环:魔法的华丽绽放 🔥

在按钮组件样式设定中,下面这段 "场景循环" 代码有着关键作用。

scss 复制代码
@each $scene in $sceneTypes {
    @include m($scene) {
      @include button-action-scene-color($scene);
    }
  }

这里的 @each 循环会遍历 $sceneTypes 里的元素。在每次循环时,先是通过 @include m($scene),接着 @include button-action-scene-color($scene) 会依据该场景进一步设置如默认、悬停、禁用等不同状态下的颜色样式,以此让按钮在各个场景下都能展现出合适的外观,整体实现了场景样式的有序且合理的应用。

编译后的代码大致如下:

scss 复制代码
.n-button--primary {
  --n-button-font-color: var(--n-color-white);
  --n-button-border-color: var(--n-color-primary);
  --n-button-background-color: var(--n-color-primary);
  --n-button-hover-font-color: var(--n-color-white);
  --n-button-hover-border-color: var(--n-color-primary-light-3);
  --n-button-hover-background-color: var(--n-color-primary-light-3);
  --n-button-disabled-font-color: var(--n-color-white);
  --n-button-disabled-border-color: var(--n-color-primary-light-5);
  --n-button-disabled-background-color: var(--n-color-primary-light-5);
}

不同场景下的样式如下图: 可以看到,按钮在不同场景下,如 primarysuccess 等,都展现出了独特的颜色风格,无论是正常状态、悬停还是禁用,都能给用户带来清晰的视觉区分和良好的交互体验。

完整组件样式:魔法成品的惊艳呈现 🌟

其它的样式实现与上文实现类似,具体的不一一赘述了,可以到下方提到的仓库中查看具体代码。最后完整实现如下图:

此时的按钮组件,已经成为了一个功能与颜值并存的完美作品,它在不同场景下都能展现出独特的魅力,为用户带来流畅、美观的交互体验。

最后在packages/components/button目录下新增index.ts作为组件的入口文件,负责整合组件。

🦀🦀感谢看官看到这里,如果觉得文章不错的话🙌,点个关注不迷路⭐。

诚邀您加入我的微信技术交流群🎉,群里都是志同道合的开发者👨‍💻,大家能一起交流分享摸鱼🐟。期待与您在群里相见🚀,咱们携手在开发路上共同进步✨ ! 👉点我
感谢各位大侠一路相伴,实在感激! 不瞒您说,在下还有几个开源项目 📦,它们就像精心培育的幼苗 🌱,急需您的浇灌。要是您瞧着还不错,麻烦动动手指,给它们点亮几颗 Star ⭐,您的支持就是它们成长的最大动力,在此谢过各位大侠啦!

相关推荐
brzhang几秒前
告别『上线裸奔』!一文带你配齐生产级 Web 应用的 10 大核心组件
前端·后端·架构
程序员Bears几秒前
深入理解CSS3:Flex/Grid布局、动画与媒体查询实战指南
前端·css3·媒体·visual studio code
工呈士7 分钟前
CSS in JS:机遇与挑战的思考
javascript·css
至尊童9 分钟前
五个JavaScript 应用技巧
javascript
David凉宸12 分钟前
凉宸推荐给大家的一些开源项目
前端
举个栗子dhy14 分钟前
编辑器、代码块、大模型AI对话中代码复制功能实现
javascript
袋鱼不重14 分钟前
Cursor 最简易上手体验:谷歌浏览器插件开发3s搞定!
前端·后端·cursor
hyyyyy!14 分钟前
《从分遗产说起:JS 原型与继承详解》
前端·javascript·原型模式
竹苓15 分钟前
从一个想法到上线,一万字记录我开发浏览器插件的全过程
前端
小桥风满袖16 分钟前
Three.js-硬要自学系列19 (曲线颜色渐变、渐变插值、查看设置gltf顶点、山脉高度可视化)
前端·css·three.js