1// Copyright (C) 2023 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import m from 'mithril'; 16import {classNames} from '../classnames'; 17import {Icon} from './icon'; 18import {Popup} from './popup'; 19 20interface CommonAttrs { 21 // Always show the button as if the "active" pseudo class were applied, which 22 // makes the button look permanently pressed. 23 // Useful for when the button represents some toggleable state, such as 24 // showing/hiding a popup menu. 25 // Defaults to false. 26 active?: boolean; 27 // Use minimal padding, reducing the overall size of the button by a few px. 28 // Defaults to false. 29 compact?: boolean; 30 // Reduces button decorations. 31 // Defaults to false. 32 minimal?: boolean; 33 // Make the button appear greyed out block any interaction with it. No events 34 // will be fired. 35 // Defaults to false. 36 disabled?: boolean; 37 // Optional right icon. 38 rightIcon?: string; 39 // List of space separated class names forwarded to the icon. 40 className?: string; 41 // Allow clicking this button to close parent popups. 42 // Defaults to false. 43 dismissPopup?: boolean; 44 // Remaining attributes forwarded to the underlying HTML <button>. 45 [htmlAttrs: string]: any; 46} 47 48interface IconButtonAttrs extends CommonAttrs { 49 // Icon buttons require an icon. 50 icon: string; 51} 52 53interface LabelButtonAttrs extends CommonAttrs { 54 // Label buttons require a label. 55 label: string; 56 // Label buttons can have an optional icon. 57 icon?: string; 58} 59 60export type ButtonAttrs = LabelButtonAttrs|IconButtonAttrs; 61 62export class Button implements m.ClassComponent<ButtonAttrs> { 63 view({attrs}: m.CVnode<ButtonAttrs>) { 64 const { 65 label, 66 icon, 67 active = false, 68 compact = false, 69 minimal = false, 70 disabled = false, 71 rightIcon, 72 className, 73 dismissPopup = false, 74 ...htmlAttrs 75 } = attrs; 76 77 const classes = classNames( 78 'pf-button', 79 active && 'pf-active', 80 compact && 'pf-compact', 81 minimal && 'pf-minimal', 82 (icon && !label) && 'pf-icon-only', 83 dismissPopup && Popup.DISMISS_POPUP_GROUP_CLASS, 84 className, 85 ); 86 87 return m( 88 'button' + (disabled ? '[disabled]' : ''), 89 { 90 class: classes, 91 ...htmlAttrs, 92 }, 93 icon && m(Icon, {className: 'pf-left-icon', icon}), 94 rightIcon && m(Icon, {className: 'pf-right-icon', icon: rightIcon}), 95 label || '\u200B', // Zero width space keeps button in-flow 96 ); 97 } 98} 99