DropdownButton とは?
Qiita のこれですね!

Qiita と同じように 限定公開
←→ 一般公開
...etc 的なUIが作りたくて 「どんなのが良いかなぁ」 と考えた結果、 DropdownButton なら綺麗にまとまりそう! って思ったので自作することにしました。
今回のライブ Demo はこちら → https://stackblitz.com/edit/angular-miln1y
チラ見用 gif も置いておきます
どうやって作ろうか
とりあえずググってみると、DropdownMenu を渇望している 公式の issue を発見。
そうそう これが欲しかったんだよ!
しかし...、今のところ実装予定ではなさそうですね・・・
しゃーなぃ 自分で作るかぁ・・ ん?
- mat-menu
- mat-button-toggle-group
とかで実装したというコメントを発見
…なるほど、確かに組み合わせればそれっぽいのできそう!
ありがとう コメントの人!
実装してみる
html
- だいたいこんな感じの構造かなぁ とイメージを膨らませつつ書く
<mat-menu #menu="matMenu">
<button mat-menu-item *ngFor="let item of selectItems" (click)="onSelect(item)">
<mat-icon *ngIf="item.icon">{{ item.icon }}</mat-icon>
<span>{{ item.text }}</span>
</button>
</mat-menu>
<mat-button-toggle-group class="dropdown-button" [class.dropdown-button--disabled]="isDisabled()">
<mat-button-toggle mat-ripple [disabled]="disabled" class="dropdown-button__main" [matRippleDisabled]="isDisabled()" (click)="onClick()">
{{ selectedItem.text }}
</mat-button-toggle>
<mat-button-toggle mat-ripple class="dropdown-button__trigger" [matMenuTriggerFor]="menu">
<mat-icon>arrow_drop_down</mat-icon>
</mat-button-toggle>
</mat-button-toggle-group>
- mat-menu と mat-button-toggle を基本として構成
- ripple エフェクトも angular-material から お借りしました
-
mat-ripple
をつけるだけで、簡単にリッチ感漂う UI を実装できます 凄いです(*゚O゚)
css
-
::ng-deep
で padding 等を矯正しつつ、お好みのスタイルを当てます
%default-theme {
color: #fff;
background-color: #00897b;
transition: all 0.3s ease-out;
cursor: pointer;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
%disabled-theme {
color: rgba(0, 0, 0, 0.5);
background-color: rgba(0, 0, 0, 0.12);
}
.dropdown-button {
position: relative;
transform: translateY(-1px);
transition: all 0.3s ease-out;
&--disabled {
box-shadow: none;
transform: translateY(1px);
.dropdown-button {
&__main {
@extend %disabled-theme;
}
&__trigger {
@extend %disabled-theme;
}
}
}
&__main {
@extend %default-theme;
& ::ng-deep .mat-button-toggle-label-content {
font-size: 12px;
font-weight: bold;
}
}
&__trigger {
@extend %default-theme;
& ::ng-deep .mat-button-toggle-label-content {
padding: 0;
}
}
}
- disable 時の
translateY(1px)
がこだわりポイント (・∀・) - 影が無くなるということは、物体はその分下に落ちる
- ↑ をさり気なく行うことで ワンランク上のエフェクトになる気がしています
- ホントは素直に 2px 移動させたいのですが、上下中央寄せされた際にずれが目立ってしまうので 1px と -1px にしました
ts
export interface DropdownButtonItem {
type: string;
text: string;
icon?: string;
isSelect?: boolean;
}
- 自分が欲しい機能を考慮して 注入する選択要素の interface を定義
- icon
- メニュー側で表示する際に mat-icon を付ける
- isSelect
- 最初に選択されている要素(必要なら)
これをこんな感じで定義して
selectedItems: DropdownButtonItem[] = [
{ icon: 'create', type: DropdownButtonItemTypes.Html, text: 'HTML' },
{ icon: 'save', type: DropdownButtonItemTypes.Css, text: 'CSS' },
{ icon: 'code', type: DropdownButtonItemTypes.Javascript, text: 'JS', isSelect: true }
];
作成した カスタムコンポーネント に渡します
<app-dropdown-button [disabled]="disabled" [selectItems]="selectedItems" (confirm)="onConfirm($event)"></app-dropdown-button>
- dropdown-button.component 自体はイベントの受け渡しをしているだけなので省略
完成!
angular-material2 の
- mat-menu
- mat-ripple
- mat-button-toggle
- mat-button-toggle-group
を組み合わせることで 簡単に 思い通りの DropdownButton を作成することができました (=゚▽゚)/
もし angular を使っていて DropdownButton が必要な方がいらっしゃいましたら チューニングしてお使いくださいm(__)m