mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-24 14:58:36 +08:00
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:
11
packages/core/src/components.d.ts
vendored
11
packages/core/src/components.d.ts
vendored
@ -362,16 +362,11 @@ declare global {
|
|||||||
itemButton?: boolean,
|
itemButton?: boolean,
|
||||||
href?: string,
|
href?: string,
|
||||||
buttonType?: string,
|
buttonType?: string,
|
||||||
large?: boolean,
|
size?: 'small' | 'large',
|
||||||
small?: boolean,
|
|
||||||
default?: boolean,
|
|
||||||
disabled?: boolean,
|
disabled?: boolean,
|
||||||
outline?: boolean,
|
fill?: 'clear' | 'outline' | 'solid' | 'default',
|
||||||
clear?: boolean,
|
|
||||||
solid?: boolean,
|
|
||||||
round?: boolean,
|
round?: boolean,
|
||||||
block?: boolean,
|
expand?: 'full' | 'block',
|
||||||
full?: boolean,
|
|
||||||
strong?: boolean,
|
strong?: boolean,
|
||||||
color?: string,
|
color?: string,
|
||||||
mode?: 'ios' | 'md'
|
mode?: 'ios' | 'md'
|
||||||
|
@ -1,7 +1,56 @@
|
|||||||
import { Component, CssClassMap, Element, Prop } from '@stencil/core';
|
import { Component, Element, Prop } from '@stencil/core';
|
||||||
import { getElementClassObject } from '../../utils/theme';
|
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({
|
@Component({
|
||||||
tag: 'ion-button',
|
tag: 'ion-button',
|
||||||
styleUrls: {
|
styleUrls: {
|
||||||
@ -27,22 +76,10 @@ export class Button {
|
|||||||
@Prop() buttonType: string = 'button';
|
@Prop() buttonType: string = 'button';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @input {boolean} If true, activates the large button size.
|
* @input {string} The button size.
|
||||||
* Type: size
|
* Possible values are: `"small"`, `"large"`.
|
||||||
*/
|
*/
|
||||||
@Prop() large: boolean = false;
|
@Prop() size: 'small' | 'large';
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @input {boolean} If true, sets the button into a disabled state.
|
* @input {boolean} If true, sets the button into a disabled state.
|
||||||
@ -50,22 +87,11 @@ export class Button {
|
|||||||
@Prop() disabled: boolean = false;
|
@Prop() disabled: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @input {boolean} If true, activates a transparent button style with a border.
|
* @input {string} Set to `"clear"` for a transparent button, to `"outline"` for a transparent
|
||||||
* Type: style
|
* 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;
|
@Prop() fill: 'clear' | 'outline' | 'solid' | 'default' = 'default';
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @input {boolean} If true, activates a button with rounded corners.
|
* @input {boolean} If true, activates a button with rounded corners.
|
||||||
@ -74,17 +100,10 @@ export class Button {
|
|||||||
@Prop() round: boolean = false;
|
@Prop() round: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @input {boolean} If true, activates a button style that fills the available width.
|
* @input {string} Set to `"block"` for a full-width button or to `"full"` for a full-width button
|
||||||
* Type: display
|
* without left and right borders.
|
||||||
*/
|
*/
|
||||||
@Prop() block: boolean = false;
|
@Prop() expand: 'full' | 'block';
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @input {boolean} If true, activates a button with a heavier font weight.
|
* @input {boolean} If true, activates a button with a heavier font weight.
|
||||||
@ -106,45 +125,36 @@ export class Button {
|
|||||||
*/
|
*/
|
||||||
@Prop() mode: 'ios' | 'md';
|
@Prop() mode: 'ios' | 'md';
|
||||||
|
|
||||||
render() {
|
protected render() {
|
||||||
const buttonType = this.buttonType;
|
|
||||||
const mode = this.mode;
|
|
||||||
|
|
||||||
const size =
|
const {
|
||||||
(this.large ? 'large' : null) ||
|
buttonType,
|
||||||
(this.small ? 'small' : null) ||
|
itemButton,
|
||||||
(this.default ? 'default' : null);
|
color,
|
||||||
|
expand,
|
||||||
|
fill,
|
||||||
|
mode,
|
||||||
|
round,
|
||||||
|
size,
|
||||||
|
strong
|
||||||
|
} = this;
|
||||||
|
|
||||||
const shape = (this.round ? 'round' : null);
|
const elementClasses: string[] = []
|
||||||
|
|
||||||
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 = []
|
|
||||||
.concat(
|
.concat(
|
||||||
getButtonClassList(buttonType, mode),
|
getButtonClassList(buttonType, mode),
|
||||||
getClassList(buttonType, shape, mode),
|
getClassList(buttonType, expand, mode),
|
||||||
getClassList(buttonType, display, mode),
|
|
||||||
getClassList(buttonType, size, mode),
|
getClassList(buttonType, size, mode),
|
||||||
getClassList(buttonType, decorator, mode),
|
getClassList(buttonType, round ? 'round' : null, mode),
|
||||||
getStyleClassList(mode, this.color, buttonType, this.outline, this.clear, this.solid),
|
getClassList(buttonType, strong ? 'strong' : null, mode),
|
||||||
getItemClassList(this.itemButton, size)
|
getColorClassList(buttonType, color, fill, mode),
|
||||||
)
|
getItemClassList(itemButton, size)
|
||||||
.reduce((prevValue, cssClass) => {
|
);
|
||||||
prevValue[cssClass] = true;
|
|
||||||
return prevValue;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
const TagType = this.href ? 'a' : 'button';
|
const TagType = this.href ? 'a' : 'button';
|
||||||
|
|
||||||
const buttonClasses = {
|
const buttonClasses = {
|
||||||
...hostClasses,
|
...getElementClassObject(this.el.classList),
|
||||||
...elementClasses
|
...getElementClassObject(elementClasses)
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -191,55 +201,33 @@ function getClassList(buttonType: string, type: string, mode: string): string[]
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function getColorClassList(buttonType: string, color: string, fill: string, mode: string): string[] {
|
||||||
* Get the classes for the color
|
let className = buttonType;
|
||||||
*/
|
|
||||||
function getColorClassList(color: string, buttonType: string, style: string, mode: string): string[] {
|
|
||||||
style = (buttonType !== 'bar-button' && style === 'solid') ? 'default' : style;
|
|
||||||
|
|
||||||
let className =
|
if (buttonType !== 'bar-button' && fill === 'solid') {
|
||||||
buttonType +
|
fill = 'default';
|
||||||
((style && style !== 'default') ?
|
}
|
||||||
'-' + style.toLowerCase() :
|
|
||||||
'');
|
if (fill && fill !== 'default') {
|
||||||
|
className += `-${fill.toLowerCase()}`;
|
||||||
|
}
|
||||||
|
|
||||||
// special case for a default bar button
|
// special case for a default bar button
|
||||||
// if the bar button is default it should get the style
|
// if the bar button is default it should get the fill
|
||||||
// but if a color is passed the style shouldn't be added
|
// but if a color is passed the fill shouldn't be added
|
||||||
if (buttonType === 'bar-button' && style === 'default') {
|
if (buttonType === 'bar-button' && fill === 'default') {
|
||||||
className = buttonType;
|
className = buttonType;
|
||||||
if (!color) {
|
if (!color) {
|
||||||
className += '-' + style.toLowerCase();
|
className += '-' + fill.toLowerCase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [`${className}-${mode}`].concat(
|
return [`${className}-${mode}`].concat(
|
||||||
style !== 'default' ? `${className}` : [],
|
fill !== 'default' ? `${className}` : [],
|
||||||
color ? `${className}-${mode}-${color}` : []
|
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) {
|
function getItemClassList(itemButton: boolean, size: string) {
|
||||||
return itemButton && !size ? ['item-button'] : [];
|
return itemButton && !size ? ['item-button'] : [];
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
<ion-toolbar color="primary">
|
<ion-toolbar color="primary">
|
||||||
<ion-buttons slot="mode-start">
|
<ion-buttons slot="mode-start">
|
||||||
<ion-button class="closeButton" clear>
|
<ion-button class="closeButton" fill="clear">
|
||||||
Close
|
Close
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-button>
|
<ion-button>
|
||||||
@ -94,17 +94,17 @@
|
|||||||
|
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-buttons slot="mode-start">
|
<ion-buttons slot="mode-start">
|
||||||
<ion-button solid>
|
<ion-button fill="solid">
|
||||||
<ion-icon slot="icon-only" name="contact"></ion-icon>
|
<ion-icon slot="icon-only" name="contact"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-button solid>
|
<ion-button fill="solid">
|
||||||
<ion-icon name="contact" slot="start"></ion-icon>
|
<ion-icon name="contact" slot="start"></ion-icon>
|
||||||
Solid
|
Solid
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>Solid</ion-title>
|
<ion-title>Solid</ion-title>
|
||||||
<ion-buttons slot="mode-end">
|
<ion-buttons slot="mode-end">
|
||||||
<ion-button solid color="secondary">
|
<ion-button fill="solid" color="secondary">
|
||||||
Help
|
Help
|
||||||
<ion-icon name="help-circle" slot="end"></ion-icon>
|
<ion-icon name="help-circle" slot="end"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
@ -113,17 +113,17 @@
|
|||||||
|
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-buttons slot="mode-start">
|
<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-icon slot="icon-only" name="contact"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-button solid class="activated">
|
<ion-button fill="solid" class="activated">
|
||||||
<ion-icon name="contact" slot="start"></ion-icon>
|
<ion-icon name="contact" slot="start"></ion-icon>
|
||||||
Solid
|
Solid
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>Solid Activated</ion-title>
|
<ion-title>Solid Activated</ion-title>
|
||||||
<ion-buttons slot="mode-end">
|
<ion-buttons slot="mode-end">
|
||||||
<ion-button solid color="secondary" class="activated">
|
<ion-button fill="solid" color="secondary" class="activated">
|
||||||
Help
|
Help
|
||||||
<ion-icon name="help-circle" slot="end"></ion-icon>
|
<ion-icon name="help-circle" slot="end"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
@ -132,16 +132,16 @@
|
|||||||
|
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-buttons slot="mode-start">
|
<ion-buttons slot="mode-start">
|
||||||
<ion-button outline>
|
<ion-button fill="outline">
|
||||||
<ion-icon slot="icon-only" name="contact"></ion-icon>
|
<ion-icon slot="icon-only" name="contact"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-button outline>
|
<ion-button fill="outline">
|
||||||
<ion-icon name="star" slot="start"></ion-icon>
|
<ion-icon name="star" slot="start"></ion-icon>
|
||||||
Star
|
Star
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-buttons slot="mode-end">
|
<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-icon slot="icon-only" name="contact"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
@ -150,16 +150,16 @@
|
|||||||
|
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-buttons slot="mode-start">
|
<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-icon slot="icon-only" name="contact"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-button outline class="activated">
|
<ion-button fill="outline" class="activated">
|
||||||
<ion-icon name="star" slot="start"></ion-icon>
|
<ion-icon name="star" slot="start"></ion-icon>
|
||||||
Star
|
Star
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-buttons slot="mode-end">
|
<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-icon slot="icon-only" name="contact"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
|
@ -344,7 +344,7 @@ export class Searchbar {
|
|||||||
<ion-button
|
<ion-button
|
||||||
onClick={this.cancelSearchbar.bind(this)}
|
onClick={this.cancelSearchbar.bind(this)}
|
||||||
onMouseDown={this.cancelSearchbar.bind(this)}
|
onMouseDown={this.cancelSearchbar.bind(this)}
|
||||||
clear
|
fill="clear"
|
||||||
color='dark'
|
color='dark'
|
||||||
class='searchbar-md-cancel'>
|
class='searchbar-md-cancel'>
|
||||||
<ion-icon name='md-arrow-back'></ion-icon>
|
<ion-icon name='md-arrow-back'></ion-icon>
|
||||||
@ -362,7 +362,7 @@ export class Searchbar {
|
|||||||
autoCorrect={this.autocorrect}
|
autoCorrect={this.autocorrect}
|
||||||
spellCheck={this.spellcheck}/>
|
spellCheck={this.spellcheck}/>
|
||||||
<ion-button
|
<ion-button
|
||||||
clear
|
fill="clear"
|
||||||
class='searchbar-clear-icon'
|
class='searchbar-clear-icon'
|
||||||
onClick={this.clearInput.bind(this)}
|
onClick={this.clearInput.bind(this)}
|
||||||
onMouseDown={this.clearInput.bind(this)}>
|
onMouseDown={this.clearInput.bind(this)}>
|
||||||
@ -370,7 +370,7 @@ export class Searchbar {
|
|||||||
</div>,
|
</div>,
|
||||||
<ion-button
|
<ion-button
|
||||||
tabindex={this.activated ? 1 : -1}
|
tabindex={this.activated ? 1 : -1}
|
||||||
clear
|
fill="clear"
|
||||||
onClick={this.cancelSearchbar.bind(this)}
|
onClick={this.cancelSearchbar.bind(this)}
|
||||||
onMouseDown={this.cancelSearchbar.bind(this)}
|
onMouseDown={this.cancelSearchbar.bind(this)}
|
||||||
class='searchbar-ios-cancel'>
|
class='searchbar-ios-cancel'>
|
||||||
|
@ -197,7 +197,7 @@ export class Toast {
|
|||||||
? <div class='toast-message'>{this.message}</div>
|
? <div class='toast-message'>{this.message}</div>
|
||||||
: null}
|
: null}
|
||||||
{this.showCloseButton
|
{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'}
|
{this.closeButtonText || 'Close'}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
: null}
|
: null}
|
||||||
|
@ -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
|
* 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 = {};
|
let classObj: CssClassMap = {};
|
||||||
|
|
||||||
for (var i = 0; i < classList.length; i++) {
|
for (var i = 0; i < classList.length; i++) {
|
||||||
classObj[classList.item(i)] = true;
|
classObj[classList[i]] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return classObj;
|
return classObj;
|
||||||
|
Reference in New Issue
Block a user