Browse Source

feat(configprovider): add theme & dark style

richard1015 3 years ago
parent
commit
d1feca995e
35 changed files with 833 additions and 6 deletions
  1. 13 1
      src/config.json
  2. 7 1
      src/packages/__VUE/cell/index.scss
  3. 10 0
      src/packages/__VUE/checkbox/index.scss
  4. 13 0
      src/packages/__VUE/configprovider/__tests__/configprovider.spec.ts
  5. 18 0
      src/packages/__VUE/configprovider/common.ts
  6. 206 0
      src/packages/__VUE/configprovider/demo.vue
  7. 89 0
      src/packages/__VUE/configprovider/doc.en-US.md
  8. 89 0
      src/packages/__VUE/configprovider/doc.md
  9. 2 0
      src/packages/__VUE/configprovider/index.scss
  10. 6 0
      src/packages/__VUE/configprovider/index.taro.vue
  11. 6 0
      src/packages/__VUE/configprovider/index.vue
  12. 12 0
      src/packages/__VUE/formitem/index.scss
  13. 11 0
      src/packages/__VUE/griditem/index.scss
  14. 13 0
      src/packages/__VUE/input/index.scss
  15. 21 0
      src/packages/__VUE/inputnumber/index.scss
  16. 9 0
      src/packages/__VUE/navbar/index.scss
  17. 19 0
      src/packages/__VUE/pagination/index.scss
  18. 18 0
      src/packages/__VUE/radio/index.scss
  19. 19 0
      src/packages/__VUE/range/index.scss
  20. 21 0
      src/packages/__VUE/searchbar/index.scss
  21. 1 0
      src/packages/__VUE/switch/index.scss
  22. 0 1
      src/packages/__VUE/tabbar/__test__/index.spec.ts
  23. 5 0
      src/packages/__VUE/tabbar/index.scss
  24. 1 1
      src/packages/__VUE/tabbar/index.taro.vue
  25. 1 1
      src/packages/__VUE/tabbar/index.vue
  26. 7 0
      src/packages/__VUE/tabbaritem/index.scss
  27. 5 0
      src/packages/__VUE/tabpane/index.scss
  28. 22 0
      src/packages/__VUE/tabs/index.scss
  29. 8 0
      src/packages/__VUE/textarea/index.scss
  30. 7 0
      src/packages/styles/variables-jdb.scss
  31. 7 0
      src/packages/styles/variables-jdt.scss
  32. 7 0
      src/packages/styles/variables.scss
  33. 8 1
      src/sites/mobile-taro/vue/src/app.config.ts
  34. 1 0
      src/sites/mobile-taro/vue/src/base/pages/configprovider/index.config.ts
  35. 151 0
      src/sites/mobile-taro/vue/src/base/pages/configprovider/index.vue

+ 13 - 1
src/config.json

@@ -127,6 +127,17 @@
           "show": true,
           "desc": "弹出层容器,用于展示弹窗、信息提示等内容,支持多个弹出层叠加展示",
           "author": "szg2008"
+        },
+        {
+          "version": "3.0.0",
+          "name": "ConfigProvider",
+          "cType": "基础组件",
+          "cName": "全局配置",
+          "desc": "用于配置NutUI组件全局",
+          "show": true,
+          "tarodoc": false,
+          "type": "component",
+          "author": "richard1015"
         }
       ]
     },
@@ -1171,7 +1182,8 @@
           "exportEmpty": true,
           "author": "liqiong43",
           "taro": true
-        },{
+        },
+        {
           "name": "Comment",
           "cType": "特色组件",
           "cName": "商品评论",

+ 7 - 1
src/packages/__VUE/cell/index.scss

@@ -1,10 +1,16 @@
+.nut-theme-dark {
+  .nut-cell {
+    background: $dark-background;
+    color: $dark-color;
+  }
+}
 .nut-cell {
   position: relative;
   display: flex;
   width: 100%;
   line-height: $cell-line-height;
   padding: $cell-padding;
-  background: $white;
+  background: $cell-background;
   border-radius: $cell-border-radius;
   box-shadow: 0px 1px 7px 0px rgba(237, 238, 241, 1);
   font-size: $cell-title-font;

+ 10 - 0
src/packages/__VUE/checkbox/index.scss

@@ -1,3 +1,13 @@
+.nut-theme-dark {
+  .nut-checkbox {
+    &__label {
+      color: $dark-color;
+      &--disabled {
+        color: $checkbox-label-disable-color;
+      }
+    }
+  }
+}
 .nut-checkbox {
   display: flex;
   align-items: center;

+ 13 - 0
src/packages/__VUE/configprovider/__tests__/configprovider.spec.ts

@@ -0,0 +1,13 @@
+import { mount } from '@vue/test-utils';
+import ConfigProvider from '../index.vue';
+
+test('prop theme & tag', async () => {
+  const wrapper = mount(ConfigProvider, {
+    props: {
+      theme: 'dark',
+      tag: 'div'
+    }
+  });
+  const html = expect(wrapper.html());
+  expect(wrapper.find<HTMLElement>('.nut-theme-dark'));
+});

+ 18 - 0
src/packages/__VUE/configprovider/common.ts

@@ -0,0 +1,18 @@
+import { h, PropType } from 'vue';
+export const component = {
+  props: {
+    theme: { type: String, default: '' },
+    tag: { type: String as PropType<keyof HTMLElementTagNameMap>, default: 'div' }
+  },
+  setup(props: any, { slots }: any) {
+    return () => {
+      return h(
+        props.tag,
+        {
+          class: `nut-theme-${props.theme}`
+        },
+        slots.default?.()
+      );
+    };
+  }
+};

+ 206 - 0
src/packages/__VUE/configprovider/demo.vue

@@ -0,0 +1,206 @@
+<template>
+  <div class="demo">
+    <h2>{{ translate('basic') }}</h2>
+    <nut-config-provider :theme="theme">
+      <nut-cell :title="translate('title1')">
+        <template v-slot:link>
+          <nut-switch v-model="switchChecked" @change="switchChange" />
+        </template>
+      </nut-cell>
+      <nut-cell :title="translate('title2')" :sub-title="translate('title3')" :desc="translate('desc')"></nut-cell>
+
+      <nut-form>
+        <nut-form-item :label="translate('switch')">
+          <nut-switch v-model="formData2.switch"></nut-switch>
+        </nut-form-item>
+        <nut-form-item :label="translate('checkbox')">
+          <nut-checkbox v-model="formData2.checkbox">{{ translate('checkbox') }}</nut-checkbox>
+        </nut-form-item>
+        <nut-form-item :label="translate('radiogroup')">
+          <nut-radiogroup direction="horizontal" v-model="formData2.radio">
+            <nut-radio label="1">{{ translate('option', 1) }}</nut-radio>
+            <nut-radio disabled label="2">{{ translate('option', 2) }}</nut-radio>
+            <nut-radio label="3">{{ translate('option', 3) }}</nut-radio>
+          </nut-radiogroup>
+        </nut-form-item>
+        <nut-form-item :label="translate('rate')">
+          <nut-rate v-model="formData2.rate" />
+        </nut-form-item>
+        <nut-form-item :label="translate('inputnumber')">
+          <nut-inputnumber v-model="formData2.number" />
+        </nut-form-item>
+        <nut-form-item :label="translate('range')">
+          <nut-range hidden-tag v-model="formData2.range"></nut-range>
+        </nut-form-item>
+        <nut-form-item :label="translate('uploader')">
+          <nut-uploader url="http://apiurl" v-model:file-list="formData2.defaultFileList" maximum="3" multiple>
+          </nut-uploader>
+        </nut-form-item>
+        <nut-form-item :label="translate('address')">
+          <input
+            class="nut-input-text"
+            v-model="formData2.address"
+            @click="addressModule.methods.show"
+            readonly
+            :placeholder="translate('addressTip1')"
+            type="text"
+          />
+          <!-- nut-address -->
+          <nut-address
+            v-model:visible="addressModule.state.show"
+            :province="addressModule.state.province"
+            :city="addressModule.state.city"
+            :country="addressModule.state.country"
+            :town="addressModule.state.town"
+            @change="addressModule.methods.onChange"
+            :custom-address-title="translate('addressTip2')"
+          ></nut-address>
+        </nut-form-item>
+      </nut-form>
+    </nut-config-provider>
+  </div>
+</template>
+<script lang="ts">
+import { createComponent } from '@/packages/utils/create';
+const { createDemo, translate } = createComponent('configprovider');
+import { useTranslate } from '@/sites/assets/util/useTranslate';
+import { reactive, ref } from 'vue';
+useTranslate({
+  'zh-CN': {
+    basic: '基本用法',
+    title1: '切换暗黑',
+    title2: '我是标题',
+    title3: '副标题描述',
+    desc: '描述文字',
+    address: '地址',
+    addressTip: '请输入地址',
+    addressTip1: '请选择地址',
+    addressTip2: '请选择所在地区',
+    remarks: '备注',
+    remarksTip: '请输入备注',
+    switch: '开关',
+    checkbox: '复选框',
+    radiogroup: '单选按钮',
+    option: (v: string) => '选项' + v,
+    rate: '评分',
+    inputnumber: '步进器',
+    range: '滑块',
+    uploader: '文件上传',
+    success: '上传成功',
+    uploading: '上传中...',
+    asyncValidator: '模拟异步验证中'
+  },
+  'en-US': {
+    basic: 'Basic Usage',
+    title1: 'Switch Dark Mode',
+    title2: 'Title',
+    title3: 'Subtitle Description',
+    desc: 'Description',
+    nameTip: 'Please enter your name',
+    address: 'Address',
+    addressTip: 'Please enter address',
+    addressTip1: 'Please select an address',
+    addressTip2: 'Please select your region',
+    remarks: 'Remarks',
+    remarksTip: 'Please enter remarks',
+    switch: 'Switch',
+    checkbox: 'Checkbox',
+    radiogroup: 'Radiogroup',
+    option: (v: string) => 'Option' + v,
+    rate: 'Rate',
+    inputnumber: 'Inputnumber',
+    range: 'Range',
+    uploader: 'Upload file',
+    success: 'Upload successful',
+    uploading: 'Uploading',
+    asyncValidator: 'Simulating asynchronous verification'
+  }
+});
+export default createDemo({
+  props: {},
+  setup() {
+    const switchChecked = ref(false);
+    const theme = ref('');
+    const switchChange = (v: boolean) => {
+      theme.value = v ? 'dark' : '';
+    };
+    const formData2 = reactive({
+      switch: false,
+      checkbox: false,
+      radio: 0,
+      number: 0,
+      rate: 3,
+      range: 30,
+      address: '',
+      defaultFileList: [
+        {
+          name: 'file 1.png',
+          url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif',
+          status: 'success',
+          message: translate('success'),
+          type: 'image'
+        },
+        {
+          name: 'file 2.png',
+          url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif',
+          status: 'uploading',
+          message: translate('uploading'),
+          type: 'image'
+        }
+      ]
+    });
+
+    const addressModule = reactive({
+      state: {
+        show: false,
+        province: [
+          { id: 1, name: '北京' },
+          { id: 2, name: '广西' },
+          { id: 3, name: '江西' },
+          { id: 4, name: '四川' }
+        ],
+        city: [
+          { id: 7, name: '朝阳区' },
+          { id: 8, name: '崇文区' },
+          { id: 9, name: '昌平区' },
+          { id: 6, name: '石景山区' }
+        ],
+        country: [
+          { id: 3, name: '八里庄街道' },
+          { id: 9, name: '北苑' },
+          { id: 4, name: '常营乡' }
+        ],
+        town: []
+      },
+      methods: {
+        show() {
+          addressModule.state.show = !addressModule.state.show;
+          if (addressModule.state.show) {
+            formData2.address = '';
+          }
+        },
+        onChange({ custom, next, value }: any) {
+          formData2.address += value.name;
+          const name = addressModule.state[next];
+          if (name.length < 1) {
+            addressModule.state.show = false;
+          }
+        }
+      }
+    });
+
+    return {
+      formData2,
+      addressModule,
+      switchChecked,
+      switchChange,
+      theme,
+      translate
+    };
+  }
+});
+</script>
+<style lang="scss" scoped>
+.demo {
+}
+</style>

+ 89 - 0
src/packages/__VUE/configprovider/doc.en-US.md

@@ -0,0 +1,89 @@
+# ConfigProvider
+
+### Intro
+
+It is used to globally configure nutui components and provides dark mode.
+
+### Install
+
+```javascript
+
+import { createApp } from 'vue';
+// vue
+import { ConfigProvider } from '@nutui/nutui';
+// taro
+import { ConfigProvider } from '@nutui/nutui-taro';
+
+const app = createApp();
+app.use(ConfigProvider);
+
+```
+
+### dark mode
+
+Dark mode can be enabled by setting the `theme` property of the ConfigProvider component to `dark`.
+
+Dark mode takes effect globally, making all NutUI components on the page dark.
+
+:::demo
+
+```html
+<template>
+  <nut-config-provider :theme="theme">
+      <nut-cell title="Switch Dark Mode">
+        <template v-slot:link>
+          <nut-switch v-model="switchChecked" @change="switchChange" />
+        </template>
+      </nut-cell>
+      <nut-cell title="Title" sub-title="Subtitle Description" desc="Description"></nut-cell>
+  </nut-config-provider>
+</template>
+<script lang="ts">
+  import { ref } from 'vue';
+  export default {
+    setup() {
+      const switchChecked = ref(false);
+      const theme = ref('');
+      const switchChange = (v: boolean) => {
+        theme.value = v ? 'dark' : '';
+      };
+
+      return { translate, switchChecked, switchChange, theme };
+    }
+  };
+</script>
+```
+
+:::
+
+## API
+
+### Props
+
+| Attribute | Description                                                          | Type   | Default |
+|-----------|----------------------------------------------------------------------|--------|---------|
+| theme     | Theme style, set to `dark` to enable dark mode, take effect globally | String | -       |
+| tag       | HTML Tag of root element                                             | String | div     |
+
+
+## Dark mode adaptation progress
+
+At present, only the following components support dark mode, other components are still being improved, please pay attention to the follow-up release:
+
+- Button  
+- Cell  
+- Icon  
+- OverLay  
+- Popup  
+- Layout  
+- Sticky  
+- Divider  
+- Grid  
+- Navbar  
+- FixedNav  
+- Menu  
+- Tabbar  
+- Elevator  
+- Pagination  
+- Tabs  
+- Form...

+ 89 - 0
src/packages/__VUE/configprovider/doc.md

@@ -0,0 +1,89 @@
+# ConfigProvider 全局配置
+
+### 介绍
+
+用于全局配置 NutUI 组件,提供暗黑模式。
+
+### 安装
+
+```javascript
+
+import { createApp } from 'vue';
+// vue
+import { ConfigProvider } from '@nutui/nutui';
+// taro
+import { ConfigProvider } from '@nutui/nutui-taro';
+
+const app = createApp();
+app.use(ConfigProvider);
+
+```
+
+### 深色模式
+
+将 ConfigProvider 组件的 `theme` 属性设置为 `dark`,可以开启深色模式。
+
+深色模式会全局生效,使页面上的所有 NutUI 组件变为深色风格。
+
+:::demo
+
+```html
+<template>
+  <nut-config-provider :theme="theme">
+      <nut-cell title="切换暗黑">
+        <template v-slot:link>
+          <nut-switch v-model="switchChecked" @change="switchChange" />
+        </template>
+      </nut-cell>
+      <nut-cell title="我是标题" sub-title="副标题描述" desc="描述文字"></nut-cell>
+  </nut-config-provider>
+</template>
+<script lang="ts">
+  import { ref } from 'vue';
+  export default {
+    setup() {
+      const switchChecked = ref(false);
+      const theme = ref('');
+      const switchChange = (v: boolean) => {
+        theme.value = v ? 'dark' : '';
+      };
+
+      return { translate, switchChecked, switchChange, theme };
+    }
+  };
+</script>
+```
+
+:::
+
+## API
+
+### Props
+
+| 参数  | 说明                                             | 类型   | 默认值 |
+|-------|--------------------------------------------------|--------|--------|
+| theme | 主题风格,设置为 `dark` 来开启深色模式,全局生效 | String | -      |
+| tag   | 根节点对应的 HTML 标签名                         | String | div    |
+
+
+## 暗黑模式适配进度
+
+目前,只有以下组件支持了暗黑模式,其他组件还在持续完善中,请关注后续的发布 欢迎 PR 共建:
+
+- Button  
+- Cell  
+- Icon  
+- OverLay  
+- Popup  
+- Layout  
+- Sticky  
+- Divider  
+- Grid  
+- Navbar  
+- FixedNav  
+- Menu  
+- Tabbar  
+- Elevator  
+- Pagination  
+- Tabs  
+- Form...

+ 2 - 0
src/packages/__VUE/configprovider/index.scss

@@ -0,0 +1,2 @@
+.nut-configprovider {
+}

+ 6 - 0
src/packages/__VUE/configprovider/index.taro.vue

@@ -0,0 +1,6 @@
+<script lang="ts">
+import { createComponent } from '@/packages/utils/create';
+const { componentName, create } = createComponent('config-provider');
+import { component } from './common';
+export default create(component);
+</script>

+ 6 - 0
src/packages/__VUE/configprovider/index.vue

@@ -0,0 +1,6 @@
+<script lang="ts">
+import { createComponent } from '@/packages/utils/create';
+const { componentName, create } = createComponent('config-provider');
+import { component } from './common';
+export default create(component);
+</script>

+ 12 - 0
src/packages/__VUE/formitem/index.scss

@@ -1,3 +1,14 @@
+.nut-theme-dark {
+  .nut-form-item {
+    &__body {
+      &__slots {
+        .nut-input-text {
+          color: $dark-color;
+        }
+      }
+    }
+  }
+}
 .nut-form-item {
   display: flex;
   &::before {
@@ -51,6 +62,7 @@
         outline: 0 none;
         border: 0;
         text-decoration: none;
+        background: transparent;
       }
       .nut-range-container {
         min-height: 24px;

+ 11 - 0
src/packages/__VUE/griditem/index.scss

@@ -1,3 +1,14 @@
+.nut-theme-dark {
+  .nut-grid-item {
+    &__content {
+      background: $dark-background;
+      color: $dark-color;
+    }
+    &__text {
+      color: $dark-color;
+    }
+  }
+}
 .nut-grid-item {
   position: relative;
   box-sizing: border-box;

+ 13 - 0
src/packages/__VUE/input/index.scss

@@ -1,3 +1,15 @@
+.nut-theme-dark {
+  .nut-input {
+    background: $dark-background;
+    &-label {
+      color: $dark-color;
+    }
+    .input-text,
+    &__text--readonly {
+      color: $dark-color;
+    }
+  }
+}
 input,
 textarea {
   font: inherit;
@@ -37,6 +49,7 @@ textarea {
     outline: 0 none;
     border: 0;
     text-decoration: none;
+    background: transparent;
     resize: none;
   }
 

+ 21 - 0
src/packages/__VUE/inputnumber/index.scss

@@ -1,3 +1,24 @@
+.nut-theme-dark {
+  .nut-inputnumber {
+    &__icon {
+      color: $dark-color;
+      &--disabled {
+        color: $dark-color-gray;
+      }
+    }
+    input,
+    &__text--readonly {
+      background-color: $dark-background;
+      color: $dark-color;
+      border: 1px solid $dark-color-gray;
+    }
+    &--disabled {
+      input {
+        color: $dark-color-gray;
+      }
+    }
+  }
+}
 .nut-inputnumber {
   display: flex;
   align-items: center;

+ 9 - 0
src/packages/__VUE/navbar/index.scss

@@ -1,3 +1,12 @@
+.nut-theme-dark {
+  .nut-navbar {
+    background: $dark-background;
+    color: $dark-color;
+    .title {
+      color: $dark-color;
+    }
+  }
+}
 .nut-navbar {
   position: relative;
   display: flex;

+ 19 - 0
src/packages/__VUE/pagination/index.scss

@@ -1,3 +1,22 @@
+.nut-theme-dark {
+  .nut-pagination {
+    &-prev,
+    &-item,
+    &-next {
+      background: $dark-background;
+      border-color: $dark-color-gray;
+    }
+    &-simple {
+      background: $dark-background;
+    }
+    .simple-border {
+      border-color: $dark-color-gray;
+    }
+    .disabled {
+      background: $dark-background;
+    }
+  }
+}
 .nut-pagination {
   display: flex;
   font-size: $pagination-font-size;

+ 18 - 0
src/packages/__VUE/radio/index.scss

@@ -1,3 +1,21 @@
+.nut-theme-dark {
+  .nut-radio {
+    &__label {
+      color: $dark-color;
+      &--disabled {
+        color: $radio-label-disable-color;
+      }
+    }
+    &__button {
+      background: $dark-background;
+      color: $dark-color;
+      &--disabled {
+        color: $radio-label-disable-color;
+        border: 1px solid $radio-label-disable-color;
+      }
+    }
+  }
+}
 .nut-radio {
   display: flex;
   align-items: center;

+ 19 - 0
src/packages/__VUE/range/index.scss

@@ -1,3 +1,22 @@
+.nut-theme-dark {
+  .nut-range-container {
+    background: $dark-background;
+    .min,
+    .max {
+      color: $dark-color-gray;
+    }
+    .nut-range {
+      &-mark-text {
+        color: $dark-color-gray;
+      }
+      &-button {
+        .number {
+          color: $dark-color;
+        }
+      }
+    }
+  }
+}
 .nut-range-container {
   display: flex;
   position: relative;

+ 21 - 0
src/packages/__VUE/searchbar/index.scss

@@ -1,3 +1,24 @@
+.nut-theme-dark {
+  .nut-searchbar {
+    background: $dark-background;
+    &__search-label {
+      color: $dark-color;
+    }
+    .nut-searchbar__input-clear {
+      & .nut-searchbar__nut-icon-mask-close {
+        color: $dark-color;
+        &:hover {
+          cursor: pointer;
+          color: $dark-color;
+        }
+      }
+    }
+    &__right-search-icon,
+    &__left-search-icon {
+      color: $dark-color;
+    }
+  }
+}
 .nut-searchbar {
   display: flex;
   align-items: center;

+ 1 - 0
src/packages/__VUE/switch/index.scss

@@ -40,6 +40,7 @@
     min-width: $switch-width;
     height: $switch-height;
     line-height: $switch-line-height;
+    overflow: hidden;
     .switch-button {
       height: $switch-inside-height;
       width: $switch-inside-width;

+ 0 - 1
src/packages/__VUE/tabbar/__test__/index.spec.ts

@@ -83,7 +83,6 @@ test('should render custom check and icon size when using visible', async () =>
   });
   await nextTick();
   const tabbarItem = wrapper.findAll<HTMLElement>('.nut-tabbar-item');
-  expect(tabbarItem[0].element.style.color).toEqual('rgb(0, 0, 0)');
   expect(tabbarItem[1].element.style.color).toEqual('blue');
   expect(wrapper.find<HTMLElement>('.nut-icon').element.style.fontSize).toEqual('18px');
 });

+ 5 - 0
src/packages/__VUE/tabbar/index.scss

@@ -1,3 +1,8 @@
+.nut-theme-dark {
+  .nut-tabbar {
+    background: $dark-background;
+  }
+}
 .nut-tabbar {
   border: 0px;
   box-shadow: $tabbar-box-shadow;

+ 1 - 1
src/packages/__VUE/tabbar/index.taro.vue

@@ -28,7 +28,7 @@ export default create({
     },
     unactiveColor: {
       type: String,
-      default: '#000000'
+      default: ''
     },
     activeColor: {
       type: String,

+ 1 - 1
src/packages/__VUE/tabbar/index.vue

@@ -28,7 +28,7 @@ export default create({
     },
     unactiveColor: {
       type: String,
-      default: '#000000'
+      default: ''
     },
     activeColor: {
       type: String,

+ 7 - 0
src/packages/__VUE/tabbaritem/index.scss

@@ -1,3 +1,10 @@
+.nut-theme-dark {
+  .nut-tabbar-item {
+    &__icon--unactive {
+      color: $dark-color-gray;
+    }
+  }
+}
 .nut-tabbar-item {
   flex: 1;
   text-align: center;

+ 5 - 0
src/packages/__VUE/tabpane/index.scss

@@ -1,3 +1,8 @@
+.nut-theme-dark {
+  .nut-tabpane {
+    background: $dark-background2;
+  }
+}
 .nut-tabpane {
   width: 100%;
   flex-shrink: 0;

+ 22 - 0
src/packages/__VUE/tabs/index.scss

@@ -1,3 +1,25 @@
+.nut-theme-dark {
+  .nut-tabs {
+    &__titles {
+      background: $dark-background3;
+      &-item {
+        color: $dark-color-gray;
+        &.active {
+          color: $dark-color;
+        }
+      }
+    }
+    &.vertical {
+      .nut-tabs__titles {
+        &-item {
+          &.active {
+            background-color: $dark-background2;
+          }
+        }
+      }
+    }
+  }
+}
 .nut-tabs {
   display: flex;
   overflow: hidden;

+ 8 - 0
src/packages/__VUE/textarea/index.scss

@@ -1,3 +1,11 @@
+.nut-theme-dark {
+  .nut-textarea {
+    background: $dark-background;
+    &__textarea {
+      color: $dark-color;
+    }
+  }
+}
 .nut-textarea {
   position: relative;
   width: 100%;

+ 7 - 0
src/packages/styles/variables-jdb.scss

@@ -87,6 +87,12 @@ $white: #fff !default;
 $black: #000 !default;
 $required-color: #fa2c19 !default;
 
+$dark-background: #1a1919 !default;
+$dark-background2: #1d1b1c !default;
+$dark-background3: #141414 !default;
+$dark-color: $white !default;
+$dark-color-gray: $text-color !default;
+
 $font-family: PingFang SC, Microsoft YaHei, Helvetica, Hiragino Sans GB, SimSun, sans-serif !default;
 
 // ---- Animation ----
@@ -173,6 +179,7 @@ $cell-line-height: 20px !default;
 $cell-after-right: 16px !default;
 $cell-after-border-bottom: 2px solid #f5f6f7 !default;
 $cell-default-icon-margin: 0 4px 0 0px !default;
+$cell-background: $white !default;
 
 // cell-group
 

+ 7 - 0
src/packages/styles/variables-jdt.scss

@@ -17,6 +17,12 @@ $white: #fff !default;
 $black: #000 !default;
 $required-color: #fa2c19 !default;
 
+$dark-background: #1a1919 !default;
+$dark-background2: #1d1b1c !default;
+$dark-background3: #141414 !default;
+$dark-color: $white !default;
+$dark-color-gray: $text-color !default;
+
 $font-family: PingFang SC, Microsoft YaHei, Helvetica, Hiragino Sans GB, SimSun, sans-serif !default;
 
 // ---- Animation ----
@@ -94,6 +100,7 @@ $cell-default-icon-margin: 0 4px 0 0px !default;
 $cell-large-title-font: $font-size-large !default;
 $cell-large-title-desc-font: $font-size-base !default;
 $cell-large-padding: 15px 16px !default;
+$cell-background: $white !default;
 
 // cell-group
 

+ 7 - 0
src/packages/styles/variables.scss

@@ -18,6 +18,12 @@ $white: #fff !default;
 $black: #000 !default;
 $required-color: #fa2c19 !default;
 
+$dark-background: #1a1919 !default;
+$dark-background2: #1d1b1c !default;
+$dark-background3: #141414 !default;
+$dark-color: $white !default;
+$dark-color-gray: $text-color !default;
+
 $font-family: PingFang SC, Microsoft YaHei, Helvetica, Hiragino Sans GB, SimSun, sans-serif !default;
 
 // ---- Animation ----
@@ -107,6 +113,7 @@ $cell-default-icon-margin: 0 4px 0 0px !default;
 $cell-large-title-font: $font-size-large !default;
 $cell-large-title-desc-font: $font-size-base !default;
 $cell-large-padding: 15px 16px !default;
+$cell-background: $white !default;
 
 // cell-group
 

+ 8 - 1
src/sites/mobile-taro/vue/src/app.config.ts

@@ -1,7 +1,14 @@
 const subPackages = [
   {
     root: 'base',
-    pages: ['pages/button/index', 'pages/cell/index', 'pages/icon/index', 'pages/overlay/index', 'pages/popup/index']
+    pages: [
+      'pages/button/index',
+      'pages/cell/index',
+      'pages/icon/index',
+      'pages/overlay/index',
+      'pages/popup/index',
+      'pages/configprovider/index'
+    ]
   },
   {
     root: 'layout',

+ 1 - 0
src/sites/mobile-taro/vue/src/base/pages/configprovider/index.config.ts

@@ -0,0 +1 @@
+export default { navigationBarTitleText: 'ConfigProvider' };

+ 151 - 0
src/sites/mobile-taro/vue/src/base/pages/configprovider/index.vue

@@ -0,0 +1,151 @@
+<template>
+  <div class="demo">
+    <h2>基础使用</h2>
+    <nut-config-provider :theme="theme">
+      <nut-cell title="切换暗黑">
+        <template v-slot:link>
+          <nut-switch v-model="switchChecked" @change="switchChange" />
+        </template>
+      </nut-cell>
+      <nut-cell title="我是标题" sub-title="副标题描述" desc="描述文字"></nut-cell>
+
+      <nut-form>
+        <nut-form-item label="开关">
+          <nut-switch v-model="formData2.switch"></nut-switch>
+        </nut-form-item>
+        <nut-form-item label="复选框">
+          <nut-checkbox v-model="formData2.checkbox">复选框</nut-checkbox>
+        </nut-form-item>
+        <nut-form-item label="单选按钮">
+          <nut-radiogroup direction="horizontal" v-model="formData2.radio">
+            <nut-radio label="1">选项1</nut-radio>
+            <nut-radio disabled label="2">选项2</nut-radio>
+            <nut-radio label="3">选项3</nut-radio>
+          </nut-radiogroup>
+        </nut-form-item>
+        <nut-form-item label="评分">
+          <nut-rate v-model="formData2.rate" />
+        </nut-form-item>
+        <nut-form-item label="步进器">
+          <nut-inputnumber v-model="formData2.number" />
+        </nut-form-item>
+        <nut-form-item label="滑块">
+          <nut-range hidden-tag v-model="formData2.range"></nut-range>
+        </nut-form-item>
+        <nut-form-item label="文件上传">
+          <nut-uploader url="http://服务地址" v-model:file-list="formData2.defaultFileList" maximum="3" multiple>
+          </nut-uploader>
+        </nut-form-item>
+        <nut-form-item label="地址">
+          <input
+            class="nut-input-text"
+            v-model="formData2.address"
+            @click="addressModule.methods.show"
+            readonly
+            placeholder="请选择地址"
+            type="text"
+          />
+          <!-- nut-address -->
+          <nut-address
+            v-model:visible="addressModule.state.show"
+            :province="addressModule.state.province"
+            :city="addressModule.state.city"
+            :country="addressModule.state.country"
+            :town="addressModule.state.town"
+            @change="addressModule.methods.onChange"
+            custom-address-title="请选择所在地区"
+          ></nut-address>
+        </nut-form-item>
+      </nut-form>
+    </nut-config-provider>
+  </div>
+</template>
+<script lang="ts">
+import { reactive, ref } from 'vue';
+export default {
+  props: {},
+  setup() {
+    const switchChecked = ref(false);
+    const theme = ref('');
+    const switchChange = (v: boolean) => {
+      theme.value = v ? 'dark' : '';
+    };
+    const formData2 = reactive({
+      switch: false,
+      checkbox: false,
+      radio: 0,
+      number: 0,
+      rate: 3,
+      range: 30,
+      address: '',
+      defaultFileList: [
+        {
+          name: 'file 1.png',
+          url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif',
+          status: 'success',
+          message: '上传成功',
+          type: 'image'
+        },
+        {
+          name: 'file 2.png',
+          url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif',
+          status: 'uploading',
+          message: '上传中...',
+          type: 'image'
+        }
+      ]
+    });
+
+    const addressModule = reactive({
+      state: {
+        show: false,
+        province: [
+          { id: 1, name: '北京' },
+          { id: 2, name: '广西' },
+          { id: 3, name: '江西' },
+          { id: 4, name: '四川' }
+        ],
+        city: [
+          { id: 7, name: '朝阳区' },
+          { id: 8, name: '崇文区' },
+          { id: 9, name: '昌平区' },
+          { id: 6, name: '石景山区' }
+        ],
+        country: [
+          { id: 3, name: '八里庄街道' },
+          { id: 9, name: '北苑' },
+          { id: 4, name: '常营乡' }
+        ],
+        town: []
+      },
+      methods: {
+        show() {
+          addressModule.state.show = !addressModule.state.show;
+          if (addressModule.state.show) {
+            formData2.address = '';
+          }
+        },
+        onChange({ custom, next, value }: any) {
+          formData2.address += value.name;
+          const name = addressModule.state[next];
+          if (name.length < 1) {
+            addressModule.state.show = false;
+          }
+        }
+      }
+    });
+
+    return {
+      formData2,
+      addressModule,
+      switchChecked,
+      switchChange,
+      theme
+    };
+  }
+};
+</script>
+<style lang="scss" scoped>
+.demo {
+}
+</style>