Введение

В быстро развивающейся среде веб-разработки использование готовых библиотек компонентов стало основным средством создания эффективных и визуально привлекательных приложений. Одной из таких библиотек, которая выделяется, является Material Web Components (MWC) от Google, часто называемая @material/web. MWC предоставляет набор веб-компонентов, соответствующих рекомендациям Google Material Design, которые теперь дополнены новейшими функциями Material 3, такими как динамический цвет и улучшенные специальные возможности. Эти компоненты универсальны и безупречно работают в различных средах, таких как Lit, React, Vue и Svelte, а также в различных веб-средах, таких как Django и Wordpress.

Но что, если вы хотите создать что-то, чего Material-Web не предлагает «из коробки»? Цель этой статьи — провести вас через процесс создания настраиваемого поля ввода пароля с переключением видимости с использованием компонентов Material-Web. Мы также будем использовать возможности Lit, библиотеки, которая позволяет создавать стандартные пользовательские элементы с ограниченными стилями и реактивными свойствами.

Чтобы сделать его еще более удобным для разработчиков, мы будем использовать Vite в качестве инструмента сборки, создав проект TypeScript на основе Lit, чтобы инкапсулировать всю магию. Итак, давайте углубимся и создадим наше собственное поле пароля.

Настройка проекта

Прежде всего, давайте настроим наш проект. Откройте терминал и запустите:

npm create vite@latest my-project -- --template lit-ts

Этот однострочник предоставляет вам проект с поддержкой Lit и TypeScript. После завершения команды перейдите в папку нового проекта и запустите сервер разработки:

cd my-project
npm install
npm run dev

Образец элемента Lit вы найдете в файле src/my-element.ts. Это наша площадка для пользовательского поля пароля.

Добавление Material-Web в ваш проект

Далее давайте добавим в наш проект компоненты Material-Web. Установите библиотеку с помощью:

npm install @material/web

Для нашего пользовательского поля пароля мы сосредоточимся на двух компонентах: MdOutlinedTextField и MdIconButton. MdOutlinedTextField будет служить нашим полем для ввода пароля. Мы поместим MdIconButton внутри текстового поля, чтобы он работал как переключатель видимости пароля.

Создание поля пользовательского пароля

Давайте начнем создавать собственное поле пароля, шаг за шагом.

Расширение MdOutlinedTextField

Во-первых, VFPasswordField расширяет MdOutlinedTextField. Нам нужно установить в конструкторе некоторые значения по умолчанию, например this.type="password"; и this.hasTrailingIcon = true;. Эти строки устанавливают начальное состояние и сообщают компоненту, что внутри него должен появиться значок.

import { html, css } from 'lit'
import {customElement, query} from 'lit/decorators.js';
import {MdOutlinedTextField} from '@material/web/textfield/outlined-text-field';
import {MdIconButton} from '@material/web/iconbutton/icon-button';

@customElement('my-password-field')
export class MyPasswordField extends MdOutlinedTextField {
  constructor() {
    super();
    this.type="password";
    this.hasTrailingIcon = true;
    //...
  }
}

Используя декоратор @customElement, мы регистрируем наш компонент как пользовательский элемент HTML в браузере.

Добавление кнопки переключения

Чтобы вставить кнопку, мы переопределяем частный метод renderTrailingIcon из MdOutlinedTextField.

constructor() {
  super();
  this.type="password";
  this.hasTrailingIcon = true;
  (this as any).renderTrailingIcon = () => {
    return html`
      <span class="icon trailing" slot="end">
          <md-icon-button toggle @change="${this.handleClick}">
            <md-icon slot="selectedIcon">visibility_off</md-icon>
            <md-icon>visibility</md-icon>
          </md-icon-button>
        </span>
    `;
  }
}

Это дает нам кнопку переключения в поле пароля — чего нет в оригинальном MdOutlinedTextField.

Настройка стилей

Чтобы улучшить внешний вид, мы добавляем несколько стилей в раздел static styles. Эти стили будут включены в Shadow DOM и не будут иметь силы за пределами нашего компонента.

@customElement('my-password-field')
class MyPasswordField extends MdOutlinedTextField {
  static styles = [...MdOutlinedTextField.styles, css`
    md-icon-button {
      height: 26px;
      padding-right: 8px;
      min-inline-size: 16px;
    }
  `]
   // ...
}

Здесь мы расширяем MdOutlinedTextField.stylesи добавляем внутри нашу кнопку собственное правило

Обработка логики переключения

Наконец, давайте позаботимся о логике действия переключения. Мы используем декоратор @query, чтобы получить ссылку на элемент md-icon-button.

@query('md-icon-button')
button: MdIconButton | undefined;

С помощью этой ссылки мы реализуем метод handleClick для переключения типа ввода между text и password.

handleClick() {
  this.type = this.button?.selected ? "text" : "password";
}

Этот метод изменяет тип ввода в зависимости от состояния кнопки, раскрывая или скрывая пароль по выбору пользователя.

Завершение сборки

После создания собственного поля пароля осталось еще пара шагов, чтобы убедиться, что все работает без сбоев.

Нам необходимо импортировать, а затем экспортировать соответствующие компоненты. Это гарантирует, что они будут включены в окончательную сборку.

import {MdIconButton} from '@material/web/iconbutton/icon-button';
import {MdIcon} from '@material/web/icon/icon';
export {
  MyPasswordField,
  MdIconButton,
  MdIcon,
}

Загрузка шрифтов значков. Чтобы отобразить значки, добавьте в свой index.html следующую строку:

<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet" />

При этом загрузится шрифт «Символы материала», благодаря чему значки видимости в нашем настраиваемом поле пароля будут отображаться правильно.

На последнем шаге добавим собственный компонент на html-страницу.

<body>
  <my-password-field 
    label="Password"
    supporting-text="password field demo">
   </my-password-field>
 </body>

Запуск проекта

если вы еще этого не сделали, запустите сервер разработки.

npm run dev

Ваше пользовательское поле пароля теперь должно быть доступно по адресу http://localhost:5173 или аналогичному URL-адресу в зависимости от ваших настроек.

Заключение

Итак, вот оно — специальное поле пароля для материала, созданное с особой тщательностью. Мы расширили функциональность компонентов Google Material-Web, в частности MdOutlinedTextField, и добавили удобный переключатель видимости. Хотя Material-Web все еще находится в активной разработке, это уже невероятно полезный инструмент. Его модульная конструкция не только обеспечивает плавную интеграцию, но и обеспечивает прочную основу для создания автономных, хорошо структурированных пользовательских компонентов. По мере развития библиотеки потенциал создания надежных и удобных для пользователя компонентов только растет.