feat(button) combine boolean fill/size/expand props to string (#13348)

* chore(utils) extend getElementClassObject to accept string array
* feat(button) combine boolean fill/size/span props to string
* feat(button) rename span prop to expand
* docs(button) remove default from listed size options
* docs(button) clarify default button fill styles
This commit is contained in:
Cam Wiegert
2017-11-28 10:40:59 -06:00
committed by GitHub
parent 285a99a6a0
commit 444b77add0
6 changed files with 118 additions and 135 deletions

View File

@@ -362,16 +362,11 @@ declare global {
itemButton?: boolean,
href?: string,
buttonType?: string,
large?: boolean,
small?: boolean,
default?: boolean,
size?: 'small' | 'large',
disabled?: boolean,
outline?: boolean,
clear?: boolean,
solid?: boolean,
fill?: 'clear' | 'outline' | 'solid' | 'default',
round?: boolean,
block?: boolean,
full?: boolean,
expand?: 'full' | 'block',
strong?: boolean,
color?: string,
mode?: 'ios' | 'md'

View File

@@ -1,7 +1,56 @@
import { Component, CssClassMap, Element, Prop } from '@stencil/core';
import { Component, Element, Prop } from '@stencil/core';
import { getElementClassObject } from '../../utils/theme';
/**
* @name Button
* @module ionic
* @description
* Buttons are simple components in Ionic. They can consist of text and icons
* and be enhanced by a wide range of attributes.
*
* @usage
*
* ```html
*
* <!-- Colors -->
* <ion-button>Default</ion-button>
* <ion-button color="secondary">Secondary</ion-button>
* <ion-button color="danger">Danger</ion-button>
* <ion-button color="light">Light</ion-button>
* <ion-button color="dark">Dark</ion-button>
*
* <!-- Shapes -->
* <ion-button expand="full">Full Button</ion-button>
* <ion-button expand="block">Block Button</ion-button>
* <ion-button round>Round Button</ion-button>
*
* <!-- Outline -->
* <ion-button expand="full" fill="outline">Outline + Full</ion-button>
* <ion-button expand="block" fill="outline">Outline + Block</ion-button>
* <ion-button round fill="outline">Outline + Round</ion-button>
*
* <!-- Icons -->
* <ion-button>
* <ion-icon slot="start" name="star"></ion-icon>
* Left Icon
* </ion-button>
*
* <ion-button>
* Right Icon
* <ion-icon slot="end" name="star"></ion-icon>
* </ion-button>
*
* <ion-button>
* <ion-icon slot="icon-only" name="star"></ion-icon>
* </ion-button>
*
* <!-- Sizes -->
* <ion-button size="large">Large</ion-button>
* <ion-button>Default</ion-button>
* <ion-button size="small">Small</ion-button>
* ```
*
*/
@Component({
tag: 'ion-button',
styleUrls: {
@@ -27,22 +76,10 @@ export class Button {
@Prop() buttonType: string = 'button';
/**
* @input {boolean} If true, activates the large button size.
* Type: size
* @input {string} The button size.
* Possible values are: `"small"`, `"large"`.
*/
@Prop() large: boolean = false;
/**
* @input {boolean} If true, activates the small button size.
* Type: size
*/
@Prop() small: boolean = false;
/**
* @input {boolean} If true, activates the default button size. Normally the default, useful for buttons in an item.
* Type: size
*/
@Prop() default: boolean = false;
@Prop() size: 'small' | 'large';
/**
* @input {boolean} If true, sets the button into a disabled state.
@@ -50,22 +87,11 @@ export class Button {
@Prop() disabled: boolean = false;
/**
* @input {boolean} If true, activates a transparent button style with a border.
* Type: style
* @input {string} Set to `"clear"` for a transparent button, to `"outline"` for a transparent
* button with a border, or to `"solid"`. The default style is `"solid"` except inside of
* `ion-navbar`, where the default is `"clear"`.
*/
@Prop() outline: boolean = false;
/**
* @input {boolean} If true, activates a transparent button style without a border.
* Type: style
*/
@Prop() clear: boolean = false;
/**
* @input {boolean} If true, activates a solid button style. Normally the default, useful for buttons in a toolbar.
* Type: style
*/
@Prop() solid: boolean = false;
@Prop() fill: 'clear' | 'outline' | 'solid' | 'default' = 'default';
/**
* @input {boolean} If true, activates a button with rounded corners.
@@ -74,17 +100,10 @@ export class Button {
@Prop() round: boolean = false;
/**
* @input {boolean} If true, activates a button style that fills the available width.
* Type: display
* @input {string} Set to `"block"` for a full-width button or to `"full"` for a full-width button
* without left and right borders.
*/
@Prop() block: boolean = false;
/**
* @input {boolean} If true, activates a button style that fills the available width without
* a left and right border.
* Type: display
*/
@Prop() full: boolean = false;
@Prop() expand: 'full' | 'block';
/**
* @input {boolean} If true, activates a button with a heavier font weight.
@@ -106,45 +125,36 @@ export class Button {
*/
@Prop() mode: 'ios' | 'md';
render() {
const buttonType = this.buttonType;
const mode = this.mode;
protected render() {
const size =
(this.large ? 'large' : null) ||
(this.small ? 'small' : null) ||
(this.default ? 'default' : null);
const {
buttonType,
itemButton,
color,
expand,
fill,
mode,
round,
size,
strong
} = this;
const shape = (this.round ? 'round' : null);
const display =
(this.block ? 'block' : null) ||
(this.full ? 'full' : null);
const decorator = (this.strong ? 'strong' : null);
const hostClasses = getElementClassObject(this.el.classList);
const elementClasses: CssClassMap = []
const elementClasses: string[] = []
.concat(
getButtonClassList(buttonType, mode),
getClassList(buttonType, shape, mode),
getClassList(buttonType, display, mode),
getClassList(buttonType, expand, mode),
getClassList(buttonType, size, mode),
getClassList(buttonType, decorator, mode),
getStyleClassList(mode, this.color, buttonType, this.outline, this.clear, this.solid),
getItemClassList(this.itemButton, size)
)
.reduce((prevValue, cssClass) => {
prevValue[cssClass] = true;
return prevValue;
}, {});
getClassList(buttonType, round ? 'round' : null, mode),
getClassList(buttonType, strong ? 'strong' : null, mode),
getColorClassList(buttonType, color, fill, mode),
getItemClassList(itemButton, size)
);
const TagType = this.href ? 'a' : 'button';
const buttonClasses = {
...hostClasses,
...elementClasses
...getElementClassObject(this.el.classList),
...getElementClassObject(elementClasses)
};
return (
@@ -191,55 +201,33 @@ function getClassList(buttonType: string, type: string, mode: string): string[]
];
}
/**
* Get the classes for the color
*/
function getColorClassList(color: string, buttonType: string, style: string, mode: string): string[] {
style = (buttonType !== 'bar-button' && style === 'solid') ? 'default' : style;
function getColorClassList(buttonType: string, color: string, fill: string, mode: string): string[] {
let className = buttonType;
let className =
buttonType +
((style && style !== 'default') ?
'-' + style.toLowerCase() :
'');
if (buttonType !== 'bar-button' && fill === 'solid') {
fill = 'default';
}
if (fill && fill !== 'default') {
className += `-${fill.toLowerCase()}`;
}
// special case for a default bar button
// if the bar button is default it should get the style
// but if a color is passed the style shouldn't be added
if (buttonType === 'bar-button' && style === 'default') {
// if the bar button is default it should get the fill
// but if a color is passed the fill shouldn't be added
if (buttonType === 'bar-button' && fill === 'default') {
className = buttonType;
if (!color) {
className += '-' + style.toLowerCase();
className += '-' + fill.toLowerCase();
}
}
return [`${className}-${mode}`].concat(
style !== 'default' ? `${className}` : [],
fill !== 'default' ? `${className}` : [],
color ? `${className}-${mode}-${color}` : []
);
}
/**
* Get the classes for the style
* e.g. outline, clear, solid
*/
function getStyleClassList(mode: string, color: string, buttonType: string, outline: boolean, clear: boolean, solid: boolean): string[] {
let classList = [].concat(
outline ? getColorClassList(color, buttonType, 'outline', mode) : [],
clear ? getColorClassList(color, buttonType, 'clear', mode) : [],
solid ? getColorClassList(color, buttonType, 'solid', mode) : []
);
if (classList.length === 0) {
classList = getColorClassList(color, buttonType, 'default', mode);
}
return classList;
}
/**
* Get the item classes for the button
*/
function getItemClassList(itemButton: boolean, size: string) {
return itemButton && !size ? ['item-button'] : [];
}

View File

@@ -43,7 +43,7 @@
<ion-toolbar color="primary">
<ion-buttons slot="mode-start">
<ion-button class="closeButton" clear>
<ion-button class="closeButton" fill="clear">
Close
</ion-button>
<ion-button>
@@ -94,17 +94,17 @@
<ion-toolbar>
<ion-buttons slot="mode-start">
<ion-button solid>
<ion-button fill="solid">
<ion-icon slot="icon-only" name="contact"></ion-icon>
</ion-button>
<ion-button solid>
<ion-button fill="solid">
<ion-icon name="contact" slot="start"></ion-icon>
Solid
</ion-button>
</ion-buttons>
<ion-title>Solid</ion-title>
<ion-buttons slot="mode-end">
<ion-button solid color="secondary">
<ion-button fill="solid" color="secondary">
Help
<ion-icon name="help-circle" slot="end"></ion-icon>
</ion-button>
@@ -113,17 +113,17 @@
<ion-toolbar>
<ion-buttons slot="mode-start">
<ion-button solid class="activated">
<ion-button fill="solid" class="activated">
<ion-icon slot="icon-only" name="contact"></ion-icon>
</ion-button>
<ion-button solid class="activated">
<ion-button fill="solid" class="activated">
<ion-icon name="contact" slot="start"></ion-icon>
Solid
</ion-button>
</ion-buttons>
<ion-title>Solid Activated</ion-title>
<ion-buttons slot="mode-end">
<ion-button solid color="secondary" class="activated">
<ion-button fill="solid" color="secondary" class="activated">
Help
<ion-icon name="help-circle" slot="end"></ion-icon>
</ion-button>
@@ -132,16 +132,16 @@
<ion-toolbar>
<ion-buttons slot="mode-start">
<ion-button outline>
<ion-button fill="outline">
<ion-icon slot="icon-only" name="contact"></ion-icon>
</ion-button>
<ion-button outline>
<ion-button fill="outline">
<ion-icon name="star" slot="start"></ion-icon>
Star
</ion-button>
</ion-buttons>
<ion-buttons slot="mode-end">
<ion-button color="secondary" outline>
<ion-button color="secondary" fill="outline">
<ion-icon slot="icon-only" name="contact"></ion-icon>
</ion-button>
</ion-buttons>
@@ -150,16 +150,16 @@
<ion-toolbar>
<ion-buttons slot="mode-start">
<ion-button outline class="activated">
<ion-button fill="outline" class="activated">
<ion-icon slot="icon-only" name="contact"></ion-icon>
</ion-button>
<ion-button outline class="activated">
<ion-button fill="outline" class="activated">
<ion-icon name="star" slot="start"></ion-icon>
Star
</ion-button>
</ion-buttons>
<ion-buttons slot="mode-end">
<ion-button color="secondary" outline class="activated">
<ion-button color="secondary" fill="outline" class="activated">
<ion-icon slot="icon-only" name="contact"></ion-icon>
</ion-button>
</ion-buttons>

View File

@@ -344,7 +344,7 @@ export class Searchbar {
<ion-button
onClick={this.cancelSearchbar.bind(this)}
onMouseDown={this.cancelSearchbar.bind(this)}
clear
fill="clear"
color='dark'
class='searchbar-md-cancel'>
<ion-icon name='md-arrow-back'></ion-icon>
@@ -362,7 +362,7 @@ export class Searchbar {
autoCorrect={this.autocorrect}
spellCheck={this.spellcheck}/>
<ion-button
clear
fill="clear"
class='searchbar-clear-icon'
onClick={this.clearInput.bind(this)}
onMouseDown={this.clearInput.bind(this)}>
@@ -370,7 +370,7 @@ export class Searchbar {
</div>,
<ion-button
tabindex={this.activated ? 1 : -1}
clear
fill="clear"
onClick={this.cancelSearchbar.bind(this)}
onMouseDown={this.cancelSearchbar.bind(this)}
class='searchbar-ios-cancel'>

View File

@@ -197,7 +197,7 @@ export class Toast {
? <div class='toast-message'>{this.message}</div>
: null}
{this.showCloseButton
? <ion-button clear color='light' class='toast-button' onClick={() => this.dismiss()}>
? <ion-button fill="clear" color='light' class='toast-button' onClick={() => this.dismiss()}>
{this.closeButtonText || 'Close'}
</ion-button>
: null}

View File

@@ -26,11 +26,11 @@ export function createThemedClasses(mode: string, color: string, classes: string
/**
* Get the classes from a class list and return them as an object
*/
export function getElementClassObject(classList: DOMTokenList): CssClassMap {
export function getElementClassObject(classList: DOMTokenList | string[]): CssClassMap {
let classObj: CssClassMap = {};
for (var i = 0; i < classList.length; i++) {
classObj[classList.item(i)] = true;
classObj[classList[i]] = true;
}
return classObj;