MDC – Text field

前言

Angular Material 只有 Form field, 但 Material Design 有份 Text field 和 Form field, Form field 是给 checkbox 和 radio 用的, Text field 则是给 input, select 用的.

它就是一个框, 里头包含了 label 和 accessor (e.g. input, select, textarea 等)

封装了 floating label, error color, helper text 等等功能.

 

Input Text

先来一个最简单的 input text 的 field

Filled and Outlined

Material 3 中, 有 2 种 text field 设计, 一个是 filled 一个是 outlined, 下面以 outlined 作为例子.

HTML

<label class="mdc-text-field mdc-text-field--outlined">
  <span class="mdc-notched-outline">
    <span class="mdc-notched-outline__leading"></span>
    <span class="mdc-notched-outline__notch">
      <span class="mdc-floating-label">Your Name</span>
    </span>
    <span class="mdc-notched-outline__trailing"></span>
  </span>
  <input type="text" name="firstName" class="mdc-text-field__input"/>
</label>

它包含了 3 给组件.

1. text-field

2. notched-outline (notch 是 缺口, 槽口, 凹槽的意思)

3. floating-label

Yarn add

有 3 个组件所以需要安装 3 给 module. MDC 把组件分的非常细.

yarn add @material/textfield
yarn add @material/notched-outline
yarn add @material/floating-label

Scss

@use '@material/floating-label/mdc-floating-label';
@use '@material/notched-outline/mdc-notched-outline';
@use '@material/textfield';
@include textfield.core-styles;

or CSS Link

<link rel="stylesheet" href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css">

也是三剑客一起上

TypeScript

import { MDCTextField } from '@material/textfield';

document.querySelectorAll('.mdc-text-field').forEach(element => {
  new MDCTextField(element);
});

// 如果想通过 element 获取 instance, 也可以模仿 mdcAutoInit 的方式. 把 instance 放到 element 属性中
// document
//   .querySelectorAll<Element & { MDCTextField: MDCTextField }>('.mdc-text-field')
//   .forEach(element => {
//     element.MDCTextField = new MDCTextField(element);
//   });

记得, 绝大部分 MDC 的组件用法都是 HTML, Scss, TypeScript 三边都需要的 (除非没有交互才不需要 TypeScript)

效果

 

Autofill Floating Label Problem

Browser 会自动填写 password, 而 MDC 的 label 不会自动 floating...

解决方案应该是需要用到 :autofill CSS selector.

但我翻看了源码, 没有找到 autofill keyword, 唯一有关联的是在 changelog 的 issue1issue2.

anyway, 目前我的 workaround 思路是, 通过 :-webkit-autofill 找到 input 再找到 MDCTextField 

然后学它 focus 时 floating label 效果.

 关键就是那 3 行代码.

const foundation: any = field.MDCTextField.getDefaultFoundation();
foundation.notchOutline(true);
foundation.adapter.floatLabel(true);
foundation.styleFloating(true);

foundation 没有公开所有 floating label 体验的接口. adapter 是 protected, styleFloating 是 private. 所以只能 any 来使用.

 

Disabled

如果 form 有 conditional field, 那么 disabled 经常会被用到. 

文章里说需要添加 2 个地方

但其实只要在 input 添加 disabled 就可以了, text-field 的 class 会在 init 的时候自动被添加.

但是, 如果之后你通过 JS 修改 input 的 disabled. 它是不会同步的. 你会发现 MDCTextFiled.disabled 同步了, 但是却没有效果 (text-field 的 mdc-text-field--disabled 没有被移除)

原因是它的实现方式.

MDCTextFiled read disabled 是直接从 input 读的, 所以感觉是同步了.

但 set 的时候它还有一个过程去 set disabled style. 所以直接操作 input.disabled 是不行的. 必须操作 MDCTextField Instance 这个过程才会跑.

const textFiled = new MDCTextField(element);
textFiled.disabled = true;
textFiled.disabled = false;

如果你和我一样封装了 MDC (wrap 了一层), 要拿到 instance 可以参考 How to Get MDC Instance from Element

另一个方法是通过 MutationObserver 监听, 当 input attribute disabled 后去 set MDC 的 style. 这样的好处是可以封装起来. 但 MDC 的接口对扩展不是很友好

foundation 的 styleDisabled 是 private 方法, 而 setDisabled 则会去 set attribute. 虽然更新的值是一样的, 但 mutation 一样会触发, 这会导致死循环.

change event trigger > setDisabled() > update disabled > change event trigger again > setDisabled() > 死循环了.

所以需要另外做一个记入, 只有在真的发生值改变时才触发, 避开死循环.

代码大概长这样:

const textFieldInstance = new MDCTextField(element);
const input = element.querySelector<HTMLInputElement>('input')!;

let prevDisabled = input.disabled;
const mo = new MutationObserver(() => {
  if (prevDisabled !== input.disabled) {
    textFieldInstance.disabled = input.disabled;
    prevDisabled = input.disabled;
  }
});
mo.observe(input, {
  attributeFilter: ['disabled'],
});

setTimeout(() => {
  input.disabled = false;
  setTimeout(() => {
    input.disabled = true;
  }, 1000);
}, 3000);
View Code

 

Set Input Value

有时候我们会需要做 form value cache. 用户填写一半, refresh 后 value 依然存在.

如果我们直接操作 input.value = 'cache value'.

你会发现 label 不会 floating 起来.

解决方法和 disabled 差不多概念, 使用 MDCTextField instance.value = 'cache  value' 就可以了.

但是如果你想 hack 它也是可以的. 

input.value = 'hello world';
input.dispatchEvent(new Event('input'));

自己 dispatchEvent 就可以了. 因为 MDC 内部监听 input event 的. 

另外还有一个小问题, dispatch input 也会导致 input 有 focus 的 style. 所以最后还要加多一个 blur

input.dispatchEvent(new Event('blur'));

如果是 select 的话,它需要的不是 input 而是 change event 哦

select.dispatchEvent(new Event('change'));
select.dispatchEvent(new Event('blur'));

 

Error Design

Material Design 的体验是 inline error, 就是说尽可能快的让用户知道它 invalid 了.

比如上面这个 input 是 required 的, 当用户 blur 以后马上就会变红色.

required

MDC 对游览器原生的 validation 都有做处理. 比如 required

<input type="text" class="mdc-text-field__input" required />

当 input 有 required 属性时, label 会自动加上星号 *, 当用户没有填写内容 unblur 后框框会变红色.

以下是相关源码, 来自 MDCTextFieldFoundation class

从第三段可以看出, MDC 是通过游览器 native validation 实现验证的. MDC 本身并没有任何验证逻辑.

 

Helper Text

参考: Text field helper text

Helper text 就是框框下面的一行提示. 可以用来提示用户如何填写资料 (比如格式, 例子等等).

它是 text field 下的另一个 module 负责

HTML

<label class="mdc-text-field mdc-text-field--outlined">
  <span class="mdc-notched-outline">
    <span class="mdc-notched-outline__leading"></span>
    <span class="mdc-notched-outline__notch">
      <span class="mdc-floating-label">Your Name</span>
    </span>
    <span class="mdc-notched-outline__trailing"></span>
  </span>
  <input type="text" class="mdc-text-field__input" />
</label>
<div class="mdc-text-field-helper-line">
  <div class="mdc-text-field-helper-text">helper text</div>
</div>

helper-line element 需要放到 text field 的 next sibling, 位置很重要哦

text field 是通过 nextElementSibling 去找到它对应的 helper text 的

提醒: helper text 是 sibling, 很容易就会破坏 Flex / Grid 布局, 最好是把它们 wrap 起来, wrap 起来后 label 是 inline, input 有 default width (also depend on on font-size), 所以要把 label set 成 block element 或者 width 100% 哦

Scss

@use '@material/textfield/helper-text';
@include helper-text.helper-text-core-styles;

TypeScript

import { MDCTextFieldHelperText } from '@material/textfield/helper-text';

document.querySelectorAll('.mdc-text-field-helper-text').forEach(element => {
  new MDCTextFieldHelperText(element);
});

persistent

细看你会发现它默认的体验是: 当 focused, helper text 会出现, 当 blur 以后 helper text 会消失.

如果希望它一直出现, 可以加上 class "mdc-text-field-helper-text--persistent"

<div class="mdc-text-field-helper-text mdc-text-field-helper-text--persistent">helper text</div>

或用 TypeScript set

document.querySelectorAll('.mdc-text-field-helper-text').forEach(element => {
  const helperText = new MDCTextFieldHelperText(element);
  helperText.foundationForTextField.setPersistent(true);
});

效果

as error message

在 Material Design 手册中有说到, error message 和 helper text 是 share 同一个位置的.

也就是说当 error message 出现的时候 helper text 就必须被替换掉. MDC 没有直接提供这样的体验支持, 但是可以用 TS 动态 setup.

先看看没有 helper text 但是有 error message 的情况怎么写

<div class="mdc-text-field-helper-text mdc-text-field-helper-text--validation-msg">
  Name is required
</div>

加上 class "mdc-text-field-helper-text--validation-msg"

或者 TypeScript set

helperText.foundationForTextField.setValidation(true);

效果

如果想同时处理 error message 和 helper text 需要直接操作 helperText 对象

document.querySelectorAll('.mdc-text-field-helper-text').forEach(element => {
  const helperText = new MDCTextFieldHelperText(element);
  helperText.foundationForTextField.setContent('helper text');
  helperText.foundationForTextField.setPersistent(true);
  // 监听 form-field attr 出现 invalid 的 class 就切换到 error message
  helperText.foundationForTextField.setContent('Name is required');
  helperText.foundationForTextField.setValidation(true);
});

关键就是监听到 invalid 时切换成 error message. 流程大概是

1. 找到对应的 form field (它们是 sibling 关系, 所以找的到)

2. 用 mutation 监听 class 的变化, invalid 时 text field 会有 class "mdc-text-field--invalid" (依赖这个比较稳定)

3. 操作 helperText 对象, 却换成 error message 或者切换回来.

如果有 2 个验证, 比如 required + email 想针对不同 validation 时输出正确的 error message 他也没有 build-in 的. 需要用 TS 去换 error message.

另外我也发现了, Angular Material 虽然用了 MDC 的 text field 但它没有用 helper text. 反而是自己实现了一套.

character counter & max length

helper text 还有一个常用的场景就是 max length 提示

它是搭配 input maxlength 一起使用的

helper text 不需要写任何内容, MDC 会自动填上.

另外, character counter 和 helper text 是不冲突的哦, 因为一个在左边一个在右边

<div class="mdc-text-field-helper-line">
  <div class="mdc-text-field-helper-text">helper text</div>
  <div class="mdc-text-field-character-counter"></div>
</div>

 

Leading & Trailing Icon

参考: Docs – Text field icon

效果

通常是配搭 Material Icon 使用

Icon HTML

<i class="material-icons mdc-text-field__icon mdc-text-field__icon--leading" tabindex="0" role="button">event</i>

tabindex="0" role="button" 表示可点击, 如果不允许点击就把这 2 个 attributes 移除.

Scss

@use "@material/textfield/icon";

@include icon.icon-core-styles;

or CSS Link

<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />

TypeScript

import {MDCTextFieldIcon} from '@material/textfield/icon';

const icon = new MDCTextFieldIcon(document.querySelector('.mdc-text-field-icon'));

Text Field Leading icon

完整的 text field + leading icon

<label class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-leading-icon">
  <span class="mdc-notched-outline">
    <span class="mdc-notched-outline__leading"></span>
    <span class="mdc-notched-outline__notch">
      <span id="price" class="mdc-floating-label">Price</span>
    </span>
    <span class="mdc-notched-outline__trailing"></span>
  </span>
  <i class="material-icons mdc-text-field__icon mdc-text-field__icon--leading">attach_money</i>
  <input class="mdc-text-field__input" type="text" aria-labelledby="price">
</label>

注: label 多了一个 class mdc-text-field--with-leading-icon

Scss 和 TypeScript 就把 TextField 和 Icon 两组都放就可以了.

Text Field Trailing icon (with SVG)

<label class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-trailing-icon">
  <span class="mdc-notched-outline">
    <span class="mdc-notched-outline__leading"></span>
    <span class="mdc-notched-outline__notch">
      <span id="password" class="mdc-floating-label">Password</span>
    </span>
    <span class="mdc-notched-outline__trailing"></span>
  </span>
  <input class="mdc-text-field__input" type="password" aria-labelledby="password">
  <i style="font-size: 24px; color: rgba(0, 0, 0, 0.54)" class="mdc-text-field__icon mdc-text-field__icon--trailing" tabindex="0" role="button">
    <svg style="width: 1em; height: 1em;" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 96 960 960">
      <path d="M480.118 726Q551 726 600.5 676.382q49.5-49.617 49.5-120.5Q650 485 600.382 435.5q-49.617-49.5-120.5-49.5Q409 386 359.5 435.618q-49.5 49.617-49.5 120.5Q310 627 359.618 676.5q49.617 49.5 120.5 49.5Zm-.353-58Q433 668 400.5 635.265q-32.5-32.736-32.5-79.5Q368 509 400.735 476.5q32.736-32.5 79.5-32.5Q527 444 559.5 476.735q32.5 32.736 32.5 79.5Q592 603 559.265 635.5q-32.736 32.5-79.5 32.5ZM480 856q-146 0-264-83T40 556q58-134 176-217t264-83q146 0 264 83t176 217q-58 134-176 217t-264 83Zm0-300Zm-.169 240Q601 796 702.5 730.5 804 665 857 556q-53-109-154.331-174.5-101.332-65.5-222.5-65.5Q359 316 257.5 381.5 156 447 102 556q54 109 155.331 174.5 101.332 65.5 222.5 65.5Z" />
    </svg>
  </i>
</label>

注: label 多了一个 class mdc-text-field--with-leading-icon

不想引入 material icon, 也可以用自己的 svg. 直接放进 i tag 里, 配上一些 size, color styling 就可以了.

Listening Icon Event

const textFieldIcon = new MDCTextFieldIcon(icon);
textFieldIcon.listen('click', () => console.log('Hello World'));

 

Textarea

text field 里面也可以放 textarea

<label class="mdc-text-field mdc-text-field--outlined mdc-text-field--textarea">
  <span class="mdc-notched-outline">
    <span class="mdc-notched-outline__leading"></span>
    <span class="mdc-notched-outline__notch">
      <span class="mdc-floating-label">Your Name</span>
    </span>
    <span class="mdc-notched-outline__trailing"></span>
  </span>
  <span class="mdc-text-field__resizer">
    <textarea class="mdc-text-field__input" rows="4" cols="40"></textarea>
  </span>
</label>
View Code

和 input 的结构一样, 只是 text field 需要添加 class "mdc-text-field--textarea" 和里面使用一个 span wrap 着 textarea

这个 span wrapper 是为了让它支持 resize, 如果不需要 resize 可以省略掉这个 span

效果

有一个点需要注意, 它的 resize 是 apply 在 span 上, 而不是 textarea 哦

 

而且是双边 resize: both, 没有接口可以设置单边 resize, 只能通过 override 它的 style="resize: vertical"

 

Input Date

MDC 没有 datepicker, MWC 也没有 datepicker, 因为 Material Design 团队一直画不出他们满意的 datepicker 所以干脆就不画了.

一直等到 Material Design 3 才终于画出来了, 但是从稿到开发成型, 以 Material Design 团队的实力, 最少也需要 1 – 2 年的时间. 所以短期是肯定用不了的.

目前最好的方案是用原生的 input date 替代.

但是它也有许多问题哦. 我们来看看吧.

label missing

直接把 type 改成 date 就可以了

<input type="date" class="mdc-text-field__input" />

效果

第一个是正常的表现, 第二个的 label 不见了, 之所以会这样是因为

width = 0px 了, 相关代码如下

有点复杂, 我觉得大概率就是一个 bug 而已 (因为 Firefox 没有这个问题), 所以不用去理会它.

它应该是太早尝试获取 width 值了, 可能游览器还没有 render 好, 做一个 delay 是可以解决了

document.querySelectorAll('.mdc-text-field').forEach(element => {
  const textField = new MDCTextField(element);
  requestAnimationFrame(() => {
    textField.layout();
  });
});

icon mission

上面是原生 input date 的样子, Chrome 是有一个 icon 的. 因为它和 Firefox 的体验不同.

Chrome 只有点击 icon 才能召唤出 picker (在 laptop), Firefox 点击任何一个地方都会召唤出 picker.

也就是说使用 Chrome, 没有 icon = 没有 picker.

那为什么 MDC 没有 icon 呢? 

因为这个 icon 会破坏 Material Design, 而且不容易用 CSS 去调整它, 加上它不属于 W3C 规范, 所以 MDC 果断把它给关了. stackoverflow – Hide the calendar icon in Google Chrome

所以, laptop 没有 picker 用, 体验就掉了. 怎么办呢?

stackoverflow – Method to show native datepicker in Chrome

可以通过原生 API, input.showPicker() 召唤出 picker. 但需要很新的 browser 才支持 Can I use – showPicker

Chrome 99 (2022 年 3 月发布的)

trailing icons

参考: Text field icon

有了这个 API, 那么解决思路就是搞一个 calendar trailing icons, 点击以后调用 show.picker()

HTML

<input type="date" class="mdc-text-field__input" />
<i
  class="material-icons mdc-text-field__icon mdc-text-field__icon--leading"
  tabindex="0"
  role="button"
  >event</i
>

放到 input 的后面, 注意: tabindex="0" 一定要放哦, 不然是无法点击的.

Scss

@use "@material/textfield/icon";

@include icon.icon-core-styles;

or icon link 

<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />

TypeScript

const textFieldIcon = new MDCTextFieldIcon(document.querySelector('.mdc-text-field__icon')!);
textFieldIcon.listen('click', () => {
  (
    textFieldIcon.root.previousElementSibling! as unknown as { showPicker: () => void }
  ).showPicker();
});

效果

当发现游览器不支持

if ('showPicker' in HTMLInputElement.prototype) {
  // showPicker() is supported.
}

可以直接把 icon hide 起来或者 pointer-event: none. 不然点击率没有反应很尴尬.

Label Always Floating

input date 的 label 总是 floating 的. 这个在手机体验会比较差. 因为手机不会显示 dd/mm/yyyy. 它就是空白, 但 label 却是 floating 的.

其原因是 MDC Foundation 就是这样实现的...如果不希望这样那就要大费周章的去 override Component 和 Founddation 了... 想想都累...

 

 

Select

参考: Github – Select Menus

安装 module

yarn add @material/list
yarn add @material/menu-surface
yarn add @material/menu
yarn add @material/select

HTML

<div class="mdc-select mdc-select--outlined demo-width-class my-demo-select">
  <div class="mdc-select__anchor" aria-labelledby="outlined-select-label">
    <span class="mdc-notched-outline">
      <span class="mdc-notched-outline__leading"></span>
      <span class="mdc-notched-outline__notch">
        <span id="outlined-select-label" class="mdc-floating-label">Pick a Food Group</span>
      </span>
      <span class="mdc-notched-outline__trailing"></span>
    </span>
    <span class="mdc-select__selected-text-container">
      <span id="demo-selected-text" class="mdc-select__selected-text"></span>
    </span>
    <span class="mdc-select__dropdown-icon">
      <svg class="mdc-select__dropdown-icon-graphic" viewBox="7 10 10 5" focusable="false">
        <polygon
          class="mdc-select__dropdown-icon-inactive"
          stroke="none"
          fill-rule="evenodd"
          points="7 10 12 15 17 10"
        ></polygon>
        <polygon
          class="mdc-select__dropdown-icon-active"
          stroke="none"
          fill-rule="evenodd"
          points="7 15 12 10 17 15"
        ></polygon>
      </svg>
    </span>
  </div>

  <div class="mdc-select__menu mdc-menu mdc-menu-surface mdc-menu-surface--fullwidth">
    <ul class="mdc-deprecated-list" role="listbox" aria-label="Food picker listbox">
      <li
        class="mdc-deprecated-list-item mdc-deprecated-list-item--selected"
        aria-selected="true"
        data-value=""
        role="option"
      >
        <span class="mdc-deprecated-list-item__ripple"></span>
      </li>
      <li
        class="mdc-deprecated-list-item"
        aria-selected="false"
        data-value="grains"
        role="option"
      >
        <span class="mdc-deprecated-list-item__ripple"></span>
        <span class="mdc-deprecated-list-item__text"> Bread, Cereal, Rice, and Pasta </span>
      </li>
      <li
        class="mdc-deprecated-list-item mdc-deprecated-list-item--disabled"
        aria-selected="false"
        data-value="vegetables"
        aria-disabled="true"
        role="option"
      >
        <span class="mdc-deprecated-list-item__ripple"></span>
        <span class="mdc-deprecated-list-item__text"> Vegetables </span>
      </li>
      <li
        class="mdc-deprecated-list-item"
        aria-selected="false"
        data-value="fruit"
        role="option"
      >
        <span class="mdc-deprecated-list-item__ripple"></span>
        <span class="mdc-deprecated-list-item__text"> Fruit </span>
      </li>
    </ul>
  </div>
</div>
View Code

注意: 用 mdc-deprecated-list 是因为当前 MDC 正在升级中...

Scss

@use '@material/list/mdc-list';
@use '@material/menu-surface/mdc-menu-surface';
@use '@material/menu/mdc-menu';
@use '@material/select/styles';
@use '@material/select';

.demo-width-class {
  width: 400px;
}
.my-demo-select {
  @include select.outlined-density(-2); /* 注: 我用的是 outlined */
}

docs 有说, 需要 set width

TypeScript

import {MDCSelect} from '@material/select';

const select = new MDCSelect(document.querySelector('.mdc-select'));

select.listen('MDCSelect:change', () => {
  alert(`Selected option at index ${select.selectedIndex} with value "${select.value}"`);
});

效果

icon 没有旋转 animation

下面这个是官网 demo 的样子

右边的 icon 会有一个 180° 旋转, 但是我们做出来的却没有.

我看了一下它的 HTML 发现它俩实现根本就不一样. 我们的 icon 有 2 个, 一个上, 一个下. 切换.

demo 的只有一个 icon, 不是切换是旋转. 也不知道哪个是正确的.

Use in Form

要在 form 使用 select 的话, 需要加上一个 input hidden 作为 submit value, MDC 会同步它

<div class="mdc-select mdc-select--filled demo-width-class">
  <input type="hidden" name="demo-input">
  <div class="mdc-select__anchor">
    <!-- Rest of component omitted for brevity -->
  </div>
</div>

Default Value

在 list 加上 selected

同时在 display value 加上相同的值

The Validation Problem

虽然 select 支持 required validation

但毕竟不是原生 validation, 所以无法真的搭配 form 来使用, 比如 submit 的时候, by right 有 invalid 是不能成功的, 但是 select 的 invalid 是无法通知 form 的, 所以 form 能 submit 成功.

native form 没有类似 Angular Form 那样支持扩展 accessor, 所以要实现的话非常麻烦.

思路: 

拦截 form submit 

检查 select 是否 valid

invalid 就 prevent default

focus to select anchor element (这个是 tabindex 0)

set invalid (为了让它变红色和出 error message)

太麻烦了, 所以建议用 native select 来实现.

 

Native Select

no support native select

以前 MDC 是支持 native select 的, 但后来由于 maintain 不来, 所以 remove 掉了.

参考: Github Issue – Remove support for native select from MDC Select

虽然没有 build-in 的, 但是自己做也不会太难

HTML

<label class="mdc-text-field mdc-text-field--outlined">
  <span class="mdc-notched-outline">
    <span class="mdc-notched-outline__leading"></span>
    <span class="mdc-notched-outline__notch">
      <span class="mdc-floating-label">Full Name</span>
    </span>
    <span class="mdc-notched-outline__trailing"></span>
  </span>
  <select name="fullName" class="mdc-text-field__input" required>
    <option value=""></option>
    <option value="Dog">Dog</option>
    <option value="Cat">Cat</option>
    <option value="Banana">Banana</option>
  </select>
</label>
View Code

用 text field 把 input 换成 select 就可以了 (注意: 虽然是 select, 但 class 依然要放 mdc-text-field__input 哦)

Scss 和 TypeScript

和 input 一样, 我就不写了

箭头的问题

MDC 把箭头 hide 起来了

可以通过 override 的方式叫它出来

select {
  appearance: revert !important;
}

但它有缺陷, 颜色不美

不管什么情况下都是黑色, 如果体验要求不高的话, 可以算了.

我试过用 trailing icons 做 (类似上面做 datepicker 那样), 但 select 没有 showPicker 这个功能, 所以这个方向是错的.

正确的做法是 appearance: none, 然后用 background image 做箭头. 

参考: stackoverflow – Select arrow style change

 

Theme

参考: Theming Guide

text field 框的颜色是依据 them 的 primary color

Material Design 默认的颜色是紫色

想换颜色官方给的方法是通过 SCSS 的 variable 把 primary 换了.

@use '@material/theme' with (
  $primary: MediumBlue
);

效果

如果只是换 CSS Variable 会有意想不到的结果哦

原因是 label 的 Style 没有使用 CSS Variable, 它只是通过 SCSS Variable 生成

 

这种一半一半的做法, 也是醉了...

 

posted @ 2022-05-18 16:56  兴杰  阅读(269)  评论(0编辑  收藏  举报