Browse Source

feat: button组件

zy19940510 5 years ago
parent
commit
39426022da

+ 11 - 0
.prettierignore

@@ -0,0 +1,11 @@
+**/*.html
+**/*.txt
+**/*.md
+**/*.svg
+**/*.ttf
+**/*.woff
+**/*.eot
+package.json
+lib/plugin/cli/site/doc/page
+lib/plugin/cli/site/doc/view
+node_modules

+ 9 - 0
.prettierrc

@@ -0,0 +1,9 @@
+{
+  "singleQuote": true,
+  "semi": true,
+  "bracketSpacing": true,
+  "tabWidth": 2,
+  "printWidth": 150,
+  "useTabs": false,
+  "htmlWhitespaceSensitivity": "strict"
+}

+ 1 - 0
package.json

@@ -31,6 +31,7 @@
     "CHANGELOG.md"
   ],
   "scripts": {
+    "dev": "vue-cli-service serve",
     "serve": "vue-cli-service serve",
     "build": "vue-cli-service build",
     "lint": "vue-cli-service lint"

+ 34 - 19
src/packages/button/demo.vue

@@ -1,42 +1,57 @@
 <template>
   <div class="demo">
-    <div class="title">类型</div>
-    <div class="card">
+    <div class="title">按钮类型</div>
+    <div class="demo-button-row">
       <nut-button type="primary">主要按钮</nut-button>
-      <nut-button type="success">成功按钮</nut-button>
+      <nut-button type="info">信息按钮</nut-button>
       <nut-button type="default">默认按钮</nut-button>
-      <nut-button type="warning">警告按钮</nut-button>
-      <nut-button type="danger">危险按钮</nut-button>
     </div>
-    <div class="title">通栏</div>
-    <div class="card">
-      <nut-button block>通栏按钮 Normer</nut-button>
-      <nut-button block>通栏按钮 Pressed</nut-button>
-      <nut-button block disabled>通栏按钮 Disabled</nut-button>
+    <div class="demo-button-row2">
+      <nut-button type="danger">危险按钮</nut-button>
+      <nut-button type="warning">警告按钮</nut-button>
+      <nut-button type="success">成功按钮</nut-button>
     </div>
+    <div class="title">边框按钮</div>
+
+    <div class="title">禁用状态</div>
+
+    <div class="title">按钮形状</div>
+
+    <div class="title">加载状态</div>
+
+    <div class="title">图标按钮</div>
+
+    <div class="title">按钮尺寸</div>
+    <nut-button block type="primary">通栏按钮</nut-button>
+    <nut-button>普通按钮</nut-button>
+    <nut-button>小型按钮</nut-button>
   </div>
 </template>
 
 <script lang="ts">
-import Button from "@/packages/button/index.vue";
-import { createDemoComponent } from "@/utils/create";
-export default createDemoComponent("button")({
+import Button from '@/packages/button/index.vue';
+import { createDemoComponent } from '@/utils/create';
+export default createDemoComponent('button')({
   props: {
     text: String
   },
-  components: { "nut-button": Button },
-  emits: ["click"],
-  setup(props, { emit, slots }) {
-    console.log(props);
-  }
+  components: { 'nut-button': Button },
+  emits: ['click']
 });
 </script>
 
 <style lang="scss" scoped>
+.demo-button-row {
+  margin-bottom: 20px;
+}
+.demo-button-row2 {
+  margin-bottom: 10px;
+}
 .nut-button {
-  margin-bottom: 21px;
+  margin-right: 15px;
   &:last-child {
     margin-bottom: 0;
+    margin-right: 0;
   }
 }
 </style>

+ 136 - 5
src/packages/button/index.scss

@@ -1,10 +1,141 @@
 .nut-button {
-    display: block;
-    background: $button-default-bg-color;
+  position: relative;
+  display: inline-block;
+  height: $button-default-height;
+  box-sizing: border-box;
+  margin: 0;
+  padding: 0;
+  line-height: $button-default-line-height;
+  font-size: $button-default-font-size;
+  text-align: center;
+  cursor: pointer;
+  transition: opacity 0.2s;
+  -webkit-appearance: none;
+  user-select: none;
+  touch-action: manipulation;
+  &::before {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    width: 100%;
+    height: 100%;
+    background-color: $black;
+    border: inherit;
+    border-color: $black;
+    border-radius: inherit;
+    transform: translate(-50%, -50%);
+    opacity: 0;
+    content: ' ';
+  }
+  &:active::before {
+    opacity: 0.1;
+  }
+
+  &--loading,
+  &--disabled {
+    &::before {
+      display: none;
+    }
+  }
+  &--default {
     color: $button-default-color;
+    background: $button-default-bg-color;
+    border: $button-border-width solid $button-default-border-color;
+  }
+
+  &--primary {
+    color: $button-primary-color;
+    background: $button-primary-background-color;
+    border: $button-border-width solid transparent;
+  }
+
+  &--info {
+    color: $button-info-color;
+    background: $button-info-background-color;
+    border: $button-border-width solid transparent;
+  }
+
+  &--success {
+    color: $button-success-color;
+    background: $button-success-background-color;
+    border: $button-border-width solid transparent;
+  }
+
+  &--danger {
+    color: $button-danger-color;
+    background: $button-danger-background-color;
+    border: $button-border-width solid transparent;
+  }
+
+  &--warning {
+    color: $button-warning-color;
+    background: $button-warning-background-color;
+    border: $button-border-width solid transparent;
+  }
+
+  &--plain {
+    background-color: $button-plain-background-color;
+
+    &.van-button--primary {
+      color: $button-primary-background-color;
+    }
+
+    &.van-button--success {
+      color: $button-success-background-color;
+    }
+
+    &.van-button--danger {
+      color: $button-danger-background-color;
+    }
+
+    &.van-button--warning {
+      color: $button-warning-background-color;
+    }
+  }
+
+  &--large {
+    width: 100%;
+    height: $button-large-height;
+  }
+
+  &--normal {
+    padding: 0 18px;
     font-size: $button-default-font-size;
-    line-height: $button-default-height;
-    height: $button-default-height;
+  }
+
+  &--small {
+    height: $button-small-height;
+    padding: 0 $padding-xs;
+    font-size: $font-size-1;
+  }
+
+  &__loading {
+    color: inherit;
+    font-size: inherit;
+  }
+
+  &--block {
+    display: block;
+    width: 100%;
+    height: $button-block-height;
+    line-height: $button-block-line-height;
+    font-size: $font-size-3;
+  }
+
+  &--disabled {
+    cursor: not-allowed;
+    opacity: $button-disabled-opacity;
+  }
+
+  &--loading {
+    cursor: default;
+  }
+
+  &--round {
     border-radius: $button-border-radius;
-    text-align: center;
+  }
+
+  &--square {
+    border-radius: 0;
+  }
 }

+ 80 - 18
src/packages/button/index.vue

@@ -1,41 +1,103 @@
 <template>
-  <view class="nut-button" :disabled="disabled" @click="clickHandler">
+  <view :class="classes" @click="handleClick">
+    <!-- <i class="nut-icon-loading" v-if="loading"></i> -->
+    <!-- <i :class="icon" v-if="icon && !loading"></i> -->
     <slot></slot>
   </view>
 </template>
 
 <script lang="ts">
-import { PropType } from "vue";
-import { createComponent } from "@/utils/create";
-export type ButtonType =
-  | "default"
-  | "primary"
-  | "success"
-  | "warning"
-  | "danger";
-export type ButtonSize = "large" | "normal" | "small" | "mini";
-export default createComponent("button")({
+import { PropType, CSSProperties, toRefs, computed } from 'vue';
+import { createComponent } from '@/utils/create';
+export type ButtonType = 'default' | 'primary' | 'info' | 'success' | 'warning' | 'danger';
+export type ButtonSize = 'large' | 'normal' | 'small';
+export type ButtonShape = 'square' | 'round';
+export default createComponent('button')({
   props: {
-    text: String,
     color: String,
-    disabled: Boolean,
+    shape: {
+      type: String as PropType<ButtonShape>,
+      default: 'round'
+    },
+    plain: {
+      type: Boolean,
+      default: false
+    },
+    loading: {
+      type: Boolean,
+      default: false
+    },
+    disabled: {
+      type: Boolean,
+      default: false
+    },
     type: {
       type: String as PropType<ButtonType>,
-      default: "default"
+      default: 'default'
     },
     size: {
       type: String as PropType<ButtonSize>,
-      default: "normal"
+      default: 'normal'
+    },
+    block: {
+      type: Boolean,
+      default: false
     }
   },
   components: {},
-  emits: ["click"],
+  emits: ['click'],
   setup(props, { emit, slots }) {
-    console.log(props);
+    // setup内部只能访问这4个属性,值得注意的是props必须在上面声明才能在这里取到
+    console.log('props', props, 'emit', emit, 'slots', slots);
+    const { type, size, shape, disabled, loading, color, plain, block } = toRefs(props);
+    // console.log("type", type, "size", size);
+
+    const handleClick = (event: MouseEvent) => {
+      if (!loading.value && !disabled.value) {
+        emit('click', event);
+      }
+    };
+
+    const classes = computed(() => {
+      const prefixCls = 'nut-button';
+      return {
+        'nut-button': true,
+        [`${prefixCls}--${type.value}`]: type.value,
+        [`${prefixCls}--${size.value}`]: size.value,
+        [`${prefixCls}--${shape.value}`]: shape.value,
+        [`${prefixCls}--block`]: block.value
+      };
+    });
+
+    const getStyle = computed(() => {
+      if (color?.value) {
+        const style: CSSProperties = {};
+
+        if (plain.value) {
+          style.color = color.value;
+          style.background = '#fff';
+          if (!color.value?.includes('gradient')) {
+            style.borderColor = color.value;
+          }
+        } else {
+          style.color = '#fff';
+          style.background = color.value;
+        }
+
+        return style;
+      }
+    });
+
+    return {
+      handleClick,
+      disabled,
+      classes,
+      getStyle
+    };
   }
 });
 </script>
 
 <style lang="scss">
-@import "index.scss";
+@import 'index.scss';
 </style>

+ 12 - 9
src/sites/mobile/App.vue

@@ -1,16 +1,16 @@
 <template>
-  <div id="nav">{{title}}</div>
+  <div id="nav">{{ title }}</div>
   <router-view />
 </template>
 <script lang="ts">
-import { defineComponent } from "vue";
-import { isMobile } from "@/sites/assets/util";
+import { defineComponent } from 'vue';
+import { isMobile } from '@/sites/assets/util';
 export default defineComponent({
-  name: "app",
+  name: 'app',
   components: {},
   data() {
     return {
-      title: "NutUI"
+      title: 'NutUI'
     };
   },
   watch: {
@@ -20,7 +20,7 @@ export default defineComponent({
         window.top.location.replace(`${origin}${pathname}#/${to.name}`);
         this.title = to.name;
       } else {
-        this.title = "";
+        this.title = '';
       }
     }
   }
@@ -54,13 +54,16 @@ export default defineComponent({
   }
 
   .demo {
-    padding-top: 57px;
     height: 100%;
     background: #f7f8fa;
     overflow-y: auto;
-
+    padding: 0 25px;
+    padding-top: 57px;
+    &::-webkit-scrollbar {
+      width: 0;
+      background: transparent;
+    }
     .title {
-      padding-left: 25px;
       height: 56px;
       line-height: 56px;
       font-size: 14px;

+ 46 - 5
src/styles/variables.scss

@@ -12,6 +12,10 @@ $text-color: #808080 !default;
 // 特殊禁用色
 $disable-color: #cccccc !default;
 $white: #fff;
+$black: #000;
+
+// padding
+$padding-xs: 8px 12px;
 
 // Font
 $font-size-1: 12px;
@@ -22,8 +26,45 @@ $font-weight-bold: 400;
 
 // button
 $button-border-radius: 25px;
-$button-default-bg-color: linear-gradient(135deg, $primary-color 0%, $primary-color-end 100%);
-$button-default-height: 48px;
-$button-default-line-height: 1.2;
-$button-default-font-size: $font-size-3;
-$button-default-color: $white;
+$button-border-width: 1px;
+$button-default-bg-color: #fff;
+$button-default-border-color: rgba(204, 204, 204, 1);
+$button-default-color: rgba(102, 102, 102, 1);
+$button-small-height: 28px;
+$button-default-height: 38px;
+$button-large-height: 48px;
+$button-block-height: 48px;
+$button-default-line-height: 36px;
+$button-block-line-height: 46px;
+$button-default-font-size: $font-size-2;
+$button-disabled-opacity: 0.68;
+$button-primary-color: #fff;
+$button-primary-background-color: linear-gradient(
+  135deg,
+  rgba(250, 44, 25, 1) 0%,
+  rgba(250, 63, 25, 1) 45%,
+  rgba(250, 89, 25, 1) 83%,
+  rgba(250, 100, 25, 1) 100%
+);
+$button-info-color: #fff;
+$button-info-background-color: linear-gradient(315deg, rgba(73, 143, 242, 1) 0%, rgba(73, 101, 242, 1) 100%);
+$button-success-color: #fff;
+$button-success-background-color: linear-gradient(
+  135deg,
+  rgba(38, 191, 38, 1) 0%,
+  rgba(39, 197, 48, 1) 45%,
+  rgba(40, 207, 63, 1) 83%,
+  rgba(41, 212, 70, 1) 100%
+);
+
+$button-danger-color: #fff;
+$button-danger-background-color: rgba(250, 44, 25, 1);
+$button-warning-color: #fff;
+$button-warning-background-color: linear-gradient(
+  135deg,
+  rgba(255, 158, 13, 1) 0%,
+  rgba(255, 167, 13, 1) 45%,
+  rgba(255, 182, 13, 1) 83%,
+  rgba(255, 190, 13, 1) 100%
+);
+$button-plain-background-color: #fff;