diff --git a/scripts/gulp/util.ts b/scripts/gulp/util.ts
index 3091d17a7b..1edc62dbc1 100644
--- a/scripts/gulp/util.ts
+++ b/scripts/gulp/util.ts
@@ -57,16 +57,18 @@ export function createTempTsConfig(includeGlob: string[], target: string, module
}
config.include = includeGlob;
const componentsToExclude = [
+ 'avatar',
'badge',
+ 'button',
'card',
'card-content',
'card-header',
'card-title',
+ 'gesture',
'icon',
'scroll',
'slides',
- 'toggle',
- 'gesture'
+ 'toggle'
];
config.exclude = componentsToExclude.map(cmp => path.join(PROJECT_ROOT, `src/components/${cmp}`) + `/*.ts`)
diff --git a/src/components/avatar/avatar.ios.scss b/src/components/avatar/avatar.ios.scss
new file mode 100644
index 0000000000..f5bfb84c7d
--- /dev/null
+++ b/src/components/avatar/avatar.ios.scss
@@ -0,0 +1,6 @@
+@import "../../themes/ionic.globals.ios";
+@import "./avatar";
+
+
+// iOS Avatar
+// --------------------------------------------------
diff --git a/src/components/avatar/avatar.md.scss b/src/components/avatar/avatar.md.scss
new file mode 100644
index 0000000000..4bbcd8cde6
--- /dev/null
+++ b/src/components/avatar/avatar.md.scss
@@ -0,0 +1,6 @@
+@import "../../themes/ionic.globals.md";
+@import "./avatar";
+
+
+// Material Design Avatar
+// --------------------------------------------------
diff --git a/src/components/avatar/avatar.scss b/src/components/avatar/avatar.scss
new file mode 100644
index 0000000000..951217f2bc
--- /dev/null
+++ b/src/components/avatar/avatar.scss
@@ -0,0 +1,9 @@
+@import "../../themes/ionic.globals";
+
+
+// Avatar
+// --------------------------------------------------
+
+ion-avatar {
+ display: block;
+}
diff --git a/src/components/avatar/avatar.tsx b/src/components/avatar/avatar.tsx
new file mode 100644
index 0000000000..d17f64dfa4
--- /dev/null
+++ b/src/components/avatar/avatar.tsx
@@ -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 ;
+ }
+}
diff --git a/src/components/avatar/avatar.wp.scss b/src/components/avatar/avatar.wp.scss
new file mode 100644
index 0000000000..73cb8e1155
--- /dev/null
+++ b/src/components/avatar/avatar.wp.scss
@@ -0,0 +1,6 @@
+@import "../../themes/ionic.globals.wp";
+@import "./avatar";
+
+
+// Windows Avatar
+// --------------------------------------------------
diff --git a/src/components/button/button-icon.scss b/src/components/button/button-icon.scss
index 9a603ff14c..fb80ffd82b 100644
--- a/src/components/button/button-icon.scss
+++ b/src/components/button/button-icon.scss
@@ -3,29 +3,19 @@
// Button Icons
// --------------------------------------------------
-// Icons inside of buttons with text
-@mixin button-icon {
- font-size: 1.4em;
- line-height: .67;
-
- pointer-events: none;
-}
-
-[icon-left] ion-icon, // deprecated
-[icon-start] ion-icon {
- @include button-icon;
+.button ion-icon[slot="start"] {
+ @include button-icon();
@include padding-horizontal(null, .3em);
}
-[icon-right] ion-icon, // deprecated
-[icon-end] ion-icon {
- @include button-icon;
+.button ion-icon[slot="end"] {
+ @include button-icon();
@include padding-horizontal(.4em, null);
}
-.button[icon-only] {
+[icon-only] .button {
@include padding(0);
min-width: .9em;
@@ -38,4 +28,4 @@
line-height: .67;
pointer-events: none;
-}
+}
\ No newline at end of file
diff --git a/src/components/button/button.ios.scss b/src/components/button/button.ios.scss
index 0b53a53b3a..d531883f32 100644
--- a/src/components/button/button.ios.scss
+++ b/src/components/button/button.ios.scss
@@ -1,4 +1,5 @@
@import "../../themes/ionic.globals.ios";
+@import "./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;
}
diff --git a/src/components/button/button.md.scss b/src/components/button/button.md.scss
index dc4ca05fc5..874316649d 100644
--- a/src/components/button/button.md.scss
+++ b/src/components/button/button.md.scss
@@ -1,8 +1,10 @@
@import "../../themes/ionic.globals.md";
+@import "./button";
// Material Design Button
// --------------------------------------------------
+
// deprecated
$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;
}
@@ -459,7 +461,7 @@ $button-md-strong-font-weight: bold !default;
}
}
-.button-md [icon-only] {
+[icon-only] .button-md {
@include padding(0);
}
@@ -487,7 +489,6 @@ $button-md-strong-font-weight: bold !default;
@include multi-dir() {
// scss-lint:disable PropertySpelling
top: 0;
-
left: 0;
}
}
diff --git a/src/components/button/button.scss b/src/components/button/button.scss
index b806a5fc1f..c9461ca97c 100644
--- a/src/components/button/button.scss
+++ b/src/components/button/button.scss
@@ -1,4 +1,5 @@
@import "../../themes/ionic.globals";
+@import "button-icon";
// Buttons
// --------------------------------------------------
@@ -26,6 +27,9 @@ $button-round-border-radius: 64px !default;
@include text-align(center);
@include appearance(none);
+ visibility: visible;
+ border: 0;
+
position: relative;
z-index: 0;
display: inline-block;
diff --git a/src/components/button/button.tsx b/src/components/button/button.tsx
new file mode 100644
index 0000000000..04d1382d76
--- /dev/null
+++ b/src/components/button/button.tsx
@@ -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
+ *
+ *
+ * Default
+ *
+ * Secondary
+ *
+ * Danger
+ *
+ * Light
+ *
+ * Dark
+ *
+ *
+ * Full Button
+ *
+ * Block Button
+ *
+ * Round Button
+ *
+ *
+ * Outline + Full
+ *
+ * Outline + Block
+ *
+ * Outline + Round
+ *
+ *
+ *
+ *
+ * Left Icon
+ *
+ *
+ *
+ * Right Icon
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * Large
+ *
+ * Default
+ *
+ * Small
+ * ```
+ *
+ */
+@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 (
+
+
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/src/components/button/button.wp.scss b/src/components/button/button.wp.scss
index d5b67f1610..e04a0ca0ef 100644
--- a/src/components/button/button.wp.scss
+++ b/src/components/button/button.wp.scss
@@ -1,4 +1,5 @@
@import "../../themes/ionic.globals.wp";
+@import "./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;
}
@@ -379,7 +380,7 @@ $button-wp-strong-font-weight: bold !default;
}
}
-.button-wp [icon-only] {
+[icon-only] .button-wp {
@include padding(0);
}
diff --git a/src/index.ts b/src/index.ts
index 174e41895d..78a487b12c 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -10,9 +10,7 @@ export { AlertController } from './components/alert/alert-controller';
export { AlertOptions } from './components/alert/alert-options';
export { AlertCmp } from './components/alert/alert-component';
export { App } from './components/app/app';
-export { Avatar } from './components/avatar/avatar';
export { Backdrop } from './components/backdrop/backdrop';
-export { Button } from './components/button/button';
export { Checkbox } from './components/checkbox/checkbox';
export { Chip } from './components/chip/chip';
export { Content, ScrollEvent } from './components/content/content';
diff --git a/src/module.ts b/src/module.ts
index 79152a01bf..af20b8d396 100644
--- a/src/module.ts
+++ b/src/module.ts
@@ -48,9 +48,7 @@ import { AlertController } from './components/alert/alert-controller';
import { ClickBlock } from './components/app/click-block';
import { IonicApp } from './components/app/app-root';
import { OverlayPortal } from './components/app/overlay-portal';
-import { Avatar } from './components/avatar/avatar';
import { Backdrop } from './components/backdrop/backdrop';
-import { Button } from './components/button/button';
import { Checkbox } from './components/checkbox/checkbox';
import { Chip } from './components/chip/chip';
import { Content } from './components/content/content';
@@ -180,9 +178,7 @@ import { BooleanInput } from './bindings/angular/components/boolean-input';
ClickBlock,
IonicApp,
OverlayPortal,
- Avatar,
Backdrop,
- Button,
Checkbox,
Chip,
Col,
@@ -274,9 +270,7 @@ import { BooleanInput } from './bindings/angular/components/boolean-input';
ClickBlock,
IonicApp,
OverlayPortal,
- Avatar,
Backdrop,
- Button,
Checkbox,
Chip,
Col,