feat(components): add core avatar and button components

This commit is contained in:
Brandy Carney
2017-06-13 15:22:30 -04:00
parent e5b658c36b
commit 5571c8ff8a
14 changed files with 365 additions and 32 deletions

View File

@ -57,16 +57,18 @@ export function createTempTsConfig(includeGlob: string[], target: string, module
} }
config.include = includeGlob; config.include = includeGlob;
const componentsToExclude = [ const componentsToExclude = [
'avatar',
'badge', 'badge',
'button',
'card', 'card',
'card-content', 'card-content',
'card-header', 'card-header',
'card-title', 'card-title',
'gesture',
'icon', 'icon',
'scroll', 'scroll',
'slides', 'slides',
'toggle', 'toggle'
'gesture'
]; ];
config.exclude = componentsToExclude.map(cmp => path.join(PROJECT_ROOT, `src/components/${cmp}`) + `/*.ts`) config.exclude = componentsToExclude.map(cmp => path.join(PROJECT_ROOT, `src/components/${cmp}`) + `/*.ts`)

View File

@ -0,0 +1,6 @@
@import "../../themes/ionic.globals.ios";
@import "./avatar";
// iOS Avatar
// --------------------------------------------------

View File

@ -0,0 +1,6 @@
@import "../../themes/ionic.globals.md";
@import "./avatar";
// Material Design Avatar
// --------------------------------------------------

View File

@ -0,0 +1,9 @@
@import "../../themes/ionic.globals";
// Avatar
// --------------------------------------------------
ion-avatar {
display: block;
}

View File

@ -0,0 +1,27 @@
import { Component, h } from '../index';
/**
* @name Avatar
* @module ionic
* @description
* An Avatar is a component that creates a circular image for an item.
* Avatars can be placed on the left or right side of an item with the `item-start` or `item-end` directive.
* @see {@link /docs/components/#avatar-list Avatar Component Docs}
*/
@Component({
tag: 'ion-avatar',
styleUrls: {
ios: 'avatar.ios.scss',
md: 'avatar.md.scss',
wp: 'avatar.wp.scss'
},
host: {
theme: 'avatar'
}
})
export class Avatar {
render() {
return <slot></slot>;
}
}

View File

@ -0,0 +1,6 @@
@import "../../themes/ionic.globals.wp";
@import "./avatar";
// Windows Avatar
// --------------------------------------------------

View File

@ -3,29 +3,19 @@
// Button Icons // Button Icons
// -------------------------------------------------- // --------------------------------------------------
// Icons inside of buttons with text .button ion-icon[slot="start"] {
@mixin button-icon { @include button-icon();
font-size: 1.4em;
line-height: .67;
pointer-events: none;
}
[icon-left] ion-icon, // deprecated
[icon-start] ion-icon {
@include button-icon;
@include padding-horizontal(null, .3em); @include padding-horizontal(null, .3em);
} }
[icon-right] ion-icon, // deprecated .button ion-icon[slot="end"] {
[icon-end] ion-icon { @include button-icon();
@include button-icon;
@include padding-horizontal(.4em, null); @include padding-horizontal(.4em, null);
} }
.button[icon-only] { [icon-only] .button {
@include padding(0); @include padding(0);
min-width: .9em; min-width: .9em;
@ -38,4 +28,4 @@
line-height: .67; line-height: .67;
pointer-events: none; pointer-events: none;
} }

View File

@ -1,4 +1,5 @@
@import "../../themes/ionic.globals.ios"; @import "../../themes/ionic.globals.ios";
@import "./button";
// iOS Button // iOS Button
// -------------------------------------------------- // --------------------------------------------------
@ -267,7 +268,7 @@ $button-ios-strong-font-weight: 600 !default;
} }
} }
.button-small-ios[icon-only] ion-icon { [icon-only] .button-small-ios ion-icon {
font-size: $button-ios-small-icon-font-size; font-size: $button-ios-small-icon-font-size;
} }

View File

@ -1,8 +1,10 @@
@import "../../themes/ionic.globals.md"; @import "../../themes/ionic.globals.md";
@import "./button";
// Material Design Button // Material Design Button
// -------------------------------------------------- // --------------------------------------------------
// deprecated // deprecated
$button-md-margin: null !default; $button-md-margin: null !default;
@ -325,7 +327,7 @@ $button-md-strong-font-weight: bold !default;
} }
} }
.button-small-md[icon-only] ion-icon { [icon-only] .button-small-md ion-icon {
font-size: $button-md-small-icon-font-size; font-size: $button-md-small-icon-font-size;
} }
@ -459,7 +461,7 @@ $button-md-strong-font-weight: bold !default;
} }
} }
.button-md [icon-only] { [icon-only] .button-md {
@include padding(0); @include padding(0);
} }
@ -487,7 +489,6 @@ $button-md-strong-font-weight: bold !default;
@include multi-dir() { @include multi-dir() {
// scss-lint:disable PropertySpelling // scss-lint:disable PropertySpelling
top: 0; top: 0;
left: 0; left: 0;
} }
} }

View File

@ -1,4 +1,5 @@
@import "../../themes/ionic.globals"; @import "../../themes/ionic.globals";
@import "button-icon";
// Buttons // Buttons
// -------------------------------------------------- // --------------------------------------------------
@ -26,6 +27,9 @@ $button-round-border-radius: 64px !default;
@include text-align(center); @include text-align(center);
@include appearance(none); @include appearance(none);
visibility: visible;
border: 0;
position: relative; position: relative;
z-index: 0; z-index: 0;
display: inline-block; display: inline-block;

View File

@ -0,0 +1,288 @@
import { Component, h, Prop } from '../index';
import { CssClassObject } from '../../util/interfaces';
/**
* @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 full>Full Button</ion-button>
*
* <ion-button block>Block Button</ion-button>
*
* <ion-button round>Round Button</ion-button>
*
* <!-- Outline -->
* <ion-button full outline>Outline + Full</ion-button>
*
* <ion-button block outline>Outline + Block</ion-button>
*
* <ion-button round outline>Outline + Round</ion-button>
*
* <!-- Icons -->
* <ion-button icon-start>
* <ion-icon name="star"></ion-icon>
* Left Icon
* </ion-button>
*
* <ion-button icon-end>
* Right Icon
* <ion-icon name="star"></ion-icon>
* </ion-button>
*
* <ion-button icon-only>
* <ion-icon name="star"></ion-icon>
* </ion-button>
*
* <!-- Sizes -->
* <ion-button large>Large</ion-button>
*
* <ion-button>Default</ion-button>
*
* <ion-button small>Small</ion-button>
* ```
*
*/
@Component({
tag: 'ion-button',
styleUrls: {
ios: 'button.ios.scss',
md: 'button.md.scss',
wp: 'button.wp.scss'
}
})
export class Button {
@Prop() itemButton: boolean = false;
@Prop() href: string;
/**
* @Prop {string} The type of button.
* Possible values are: `"button"`, `"bar-button"`.
*/
@Prop() buttonType: string = 'button';
/**
* @Prop {boolean} If true, activates the large button size.
* Type: size
*/
@Prop() large: boolean = false;
/**
* @Prop {boolean} If true, activates the small button size.
* Type: size
*/
@Prop() small: boolean = false;
/**
* @Prop {boolean} If true, activates the default button size. Normally the default, useful for buttons in an item.
* Type: size
*/
@Prop() default: boolean = false;
/**
* @Prop {boolean} If true, sets the button into a disabled state.
*/
@Prop() disabled: boolean = false;
/**
* @Prop {boolean} If true, activates a transparent button style with a border.
* Type: style
*/
@Prop() outline: boolean = false;
/**
* @Prop {boolean} If true, activates a transparent button style without a border.
* Type: style
*/
@Prop() clear: boolean = false;
/**
* @Prop {boolean} If true, activates a solid button style. Normally the default, useful for buttons in a toolbar.
* Type: style
*/
@Prop() solid: boolean = false;
/**
* @Prop {boolean} If true, activates a button with rounded corners.
* Type: shape
*/
@Prop() round: boolean = false;
/**
* @Prop {boolean} If true, activates a button style that fills the available width.
* Type: display
*/
@Prop() block: boolean = false;
/**
* @Prop {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 {boolean} If true, activates a button with a heavier font weight.
* Type: decorator
*/
@Prop() strong: boolean = false;
/**
* @Prop {string} The mode determines which platform styles to use.
* Possible values are: `"ios"`, `"md"`, or `"wp"`.
* For more information, see [Platform Styles](/docs/theming/platform-specific-styles).
*/
@Prop() mode: 'ios' | 'md' | 'wp';
/**
* @Prop {string} The color to use from your Sass `$colors` map.
* Default options are: `"primary"`, `"secondary"`, `"danger"`, `"light"`, and `"dark"`.
* For more information, see [Theming your App](/docs/theming/theming-your-app).
*/
@Prop() color: string;
/**
* @hidden
*/
getElementClassList(buttonType: string, mode: string): string[] {
if (!buttonType) {
return [];
}
return [
buttonType,
`${buttonType}-${mode}`
];
}
/**
* @hidden
*/
getClassList(buttonType: string, type: string, mode: string): string[] {
if (!type) {
return [];
}
type = type.toLocaleLowerCase();
return [
`${buttonType}-${type}`,
`${buttonType}-${type}-${mode}`
];
}
/**
* @hidden
*/
getColorClassList(color: string, buttonType: string, style: string, mode: string): string[] {
style = (buttonType !== 'bar-button' && style === 'solid') ? 'default' : style;
let className =
buttonType +
((style && style !== 'default') ?
'-' + style.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') {
className = buttonType;
if (!color) {
className += '-' + style.toLowerCase();
}
}
return [`${className}-${mode}`].concat(
color ? `${className}-${mode}-${color}` : []
);
}
/**
* @hidden
*/
getStyleClassList(buttonType: string): string[] {
let classList = [].concat(
this.outline ? this.getColorClassList(this.color, buttonType, 'outline', this.mode) : [],
this.clear ? this.getColorClassList(this.color, buttonType, 'clear', this.mode) : [],
this.solid ? this.getColorClassList(this.color, buttonType, 'solid', this.mode) : []
);
if (classList.length === 0) {
classList = this.getColorClassList(this.color, buttonType, 'default', this.mode);
}
return classList;
}
/**
* @hidden
* Whether or not to add the item-button class
*/
getItemClassList(size: string) {
let classList = [].concat(
this.itemButton && !size ? 'item-button' : []
);
return classList;
}
render() {
const size =
(this.large ? 'large' : null) ||
(this.small ? 'small' : null) ||
(this.default ? 'default' : null);
const shape = (this.round ? 'round' : null);
const display =
(this.block ? 'block' : null) ||
(this.full ? 'full' : null);
const decorator = (this.strong ? 'strong' : null);
const buttonClasses: CssClassObject = []
.concat(
this.getElementClassList(this.buttonType, this.mode),
this.getClassList(this.buttonType, shape, this.mode),
this.getClassList(this.buttonType, display, this.mode),
this.getClassList(this.buttonType, size, this.mode),
this.getClassList(this.buttonType, decorator, this.mode),
this.getStyleClassList(this.buttonType),
this.getItemClassList(size)
)
.reduce((prevValue, cssClass) => {
prevValue[cssClass] = true;
return prevValue;
}, {});
const TagType = this.href ? 'a' : 'button';
return (
<TagType class={buttonClasses} disabled={this.disabled}>
<span class='button-inner'>
<slot name='start'></slot>
<slot></slot>
<slot name='end'></slot>
</span>
<div class='button-effect'></div>
</TagType>
);
}
}

View File

@ -1,4 +1,5 @@
@import "../../themes/ionic.globals.wp"; @import "../../themes/ionic.globals.wp";
@import "./button";
// Windows Button // Windows Button
// -------------------------------------------------- // --------------------------------------------------
@ -265,7 +266,7 @@ $button-wp-strong-font-weight: bold !default;
} }
} }
.button-small-wp[icon-only] ion-icon { [icon-only] .button-small-wp ion-icon {
font-size: $button-wp-small-icon-font-size; font-size: $button-wp-small-icon-font-size;
} }
@ -379,7 +380,7 @@ $button-wp-strong-font-weight: bold !default;
} }
} }
.button-wp [icon-only] { [icon-only] .button-wp {
@include padding(0); @include padding(0);
} }

View File

@ -10,9 +10,7 @@ export { AlertController } from './components/alert/alert-controller';
export { AlertOptions } from './components/alert/alert-options'; export { AlertOptions } from './components/alert/alert-options';
export { AlertCmp } from './components/alert/alert-component'; export { AlertCmp } from './components/alert/alert-component';
export { App } from './components/app/app'; export { App } from './components/app/app';
export { Avatar } from './components/avatar/avatar';
export { Backdrop } from './components/backdrop/backdrop'; export { Backdrop } from './components/backdrop/backdrop';
export { Button } from './components/button/button';
export { Checkbox } from './components/checkbox/checkbox'; export { Checkbox } from './components/checkbox/checkbox';
export { Chip } from './components/chip/chip'; export { Chip } from './components/chip/chip';
export { Content, ScrollEvent } from './components/content/content'; export { Content, ScrollEvent } from './components/content/content';

View File

@ -48,9 +48,7 @@ import { AlertController } from './components/alert/alert-controller';
import { ClickBlock } from './components/app/click-block'; import { ClickBlock } from './components/app/click-block';
import { IonicApp } from './components/app/app-root'; import { IonicApp } from './components/app/app-root';
import { OverlayPortal } from './components/app/overlay-portal'; import { OverlayPortal } from './components/app/overlay-portal';
import { Avatar } from './components/avatar/avatar';
import { Backdrop } from './components/backdrop/backdrop'; import { Backdrop } from './components/backdrop/backdrop';
import { Button } from './components/button/button';
import { Checkbox } from './components/checkbox/checkbox'; import { Checkbox } from './components/checkbox/checkbox';
import { Chip } from './components/chip/chip'; import { Chip } from './components/chip/chip';
import { Content } from './components/content/content'; import { Content } from './components/content/content';
@ -180,9 +178,7 @@ import { BooleanInput } from './bindings/angular/components/boolean-input';
ClickBlock, ClickBlock,
IonicApp, IonicApp,
OverlayPortal, OverlayPortal,
Avatar,
Backdrop, Backdrop,
Button,
Checkbox, Checkbox,
Chip, Chip,
Col, Col,
@ -274,9 +270,7 @@ import { BooleanInput } from './bindings/angular/components/boolean-input';
ClickBlock, ClickBlock,
IonicApp, IonicApp,
OverlayPortal, OverlayPortal,
Avatar,
Backdrop, Backdrop,
Button,
Checkbox, Checkbox,
Chip, Chip,
Col, Col,