feat(toolbar): control toolbar borders on top/bottom

Toolbars can be stacked up vertically in `<ion-header>`,
`<ion-content>`, and `<ion-footer>` elements. However, toolbars also
come with borders on both the top and bottom of the toolbar. To give
developers full control of the design, Ionic also includes the
`no-border-bottom` and `no-border-top` attributes. For example,
sometimes two vertically stacked toolbars may have different background
colors, in this case it might be best to leave a border between them.
However, if they have the same background color, the app may look best
without a border between them. The main point here is, it's entirely up
to the app's design to decide when and when not to show borders between
toolbars, and to do so then each toolbar can individually set
`no-border-bottom` and `no-border-top` attributes.
This commit is contained in:
Adam Bradley
2016-06-20 12:01:21 -05:00
parent a1223da08c
commit 3a7addf7b0
16 changed files with 98 additions and 65 deletions

View File

@ -68,7 +68,7 @@ export class Animation {
var i: number; var i: number;
if (ele) { if (ele) {
if (Array.isArray(ele)) { if (ele.length) {
for (i = 0; i < ele.length; i++) { for (i = 0; i < ele.length; i++) {
this._addEle(ele[i]); this._addEle(ele[i]);
} }

View File

@ -18,7 +18,7 @@
</button> </button>
</ion-navbar> </ion-navbar>
<ion-toolbar> <ion-toolbar no-border-top>
<ion-title>I'm a toolbar</ion-title> <ion-title>I'm a toolbar</ion-title>
</ion-toolbar> </ion-toolbar>

View File

@ -1,6 +1,6 @@
<ion-header> <ion-header>
<ion-navbar> <ion-navbar no-border-bottom>
<ion-title>Page 2</ion-title> <ion-title>Page 2</ion-title>
<button menuToggle> <button menuToggle>
<ion-icon name="menu"></ion-icon> <ion-icon name="menu"></ion-icon>
@ -15,8 +15,8 @@
</button> </button>
</ion-navbar> </ion-navbar>
<ion-toolbar> <ion-toolbar no-border-top>
<ion-title>I'm a toolbar</ion-title> Hello, I am a sub header, with no border on top
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>

View File

@ -15,7 +15,7 @@ $z-index-refresher: 0;
$z-index-page-container: 0; $z-index-page-container: 0;
$z-index-selected-tab: 1; $z-index-selected-tab: 1;
$z-index-toolbar: 10; $z-index-toolbar: 10;
$z-index-toolbar-background: 0; $z-index-toolbar-background: -1;
$z-index-backdrop: 2; $z-index-backdrop: 2;
$z-index-overlay-wrapper: 10; $z-index-overlay-wrapper: 10;

View File

@ -188,7 +188,7 @@ class ModalPassData {
<ion-title>Toolbar 1</ion-title> <ion-title>Toolbar 1</ion-title>
</ion-toolbar> </ion-toolbar>
<ion-toolbar> <ion-toolbar no-border-top>
<ion-title>Toolbar 2</ion-title> <ion-title>Toolbar 2</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>

View File

@ -209,6 +209,9 @@ class FullPage {
<button>S1g</button> <button>S1g</button>
</ion-buttons> </ion-buttons>
</ion-navbar> </ion-navbar>
<ion-toolbar no-border-top>
<ion-title>I'm a sub header!</ion-title>
</ion-toolbar>
</ion-header> </ion-header>
<ion-content padding> <ion-content padding>
@ -227,8 +230,11 @@ class FullPage {
</ion-content> </ion-content>
<ion-footer> <ion-footer>
<ion-toolbar> <ion-toolbar no-border-bottom>
Footer I'm a sub footer!
</ion-toolbar>
<ion-toolbar no-border-top>
<ion-title>Footer</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-footer> </ion-footer>
` `
@ -281,6 +287,11 @@ class PrimaryHeaderPage {
</ion-header> </ion-header>
<ion-content> <ion-content>
<ion-toolbar no-border-top>
I'm a sub header in the content!
</ion-toolbar>
<ion-list> <ion-list>
<ion-item> <ion-item>
@ -296,7 +307,17 @@ class PrimaryHeaderPage {
<button ion-item (click)="setRoot()">setRoot(FirstPage)</button> <button ion-item (click)="setRoot()">setRoot(FirstPage)</button>
<button ion-item (click)="toggleBackButton()">Toggle hideBackButton</button> <button ion-item (click)="toggleBackButton()">Toggle hideBackButton</button>
<button ion-item (click)="setBackButtonText()">Set Back Button Text</button> <button ion-item (click)="setBackButtonText()">Set Back Button Text</button>
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
</ion-list> </ion-list>
<ion-toolbar no-border-bottom>
I'm a sub footer in the content!
</ion-toolbar>
<ion-toolbar no-border-bottom no-border-top>
And I'm a sub footer in the content too!
</ion-toolbar>
</ion-content> </ion-content>
<ion-footer> <ion-footer>

View File

@ -1,10 +1,10 @@
<ion-header> <ion-header>
<ion-navbar> <ion-navbar no-border-bottom>
<ion-title>Searchbar</ion-title> <ion-title>Searchbar</ion-title>
</ion-navbar> </ion-navbar>
<ion-toolbar> <ion-toolbar no-border-top>
<ion-searchbar primary (ionInput)="getItems($event)" placeholder="Filter Schedules"> <ion-searchbar primary (ionInput)="getItems($event)" placeholder="Filter Schedules">
</ion-searchbar> </ion-searchbar>
</ion-toolbar> </ion-toolbar>

View File

@ -1,6 +1,6 @@
<ion-header> <ion-header>
<ion-toolbar> <ion-toolbar no-border-bottom>
<ion-segment id="segment" [(ngModel)]="relationship" (ionChange)="onSegmentChanged($event)"> <ion-segment id="segment" [(ngModel)]="relationship" (ionChange)="onSegmentChanged($event)">
<ion-segment-button value="friends" (ionSelect)="onSegmentSelected($event)" class="e2eSegmentFriends"> <ion-segment-button value="friends" (ionSelect)="onSegmentSelected($event)" class="e2eSegmentFriends">
Friends Friends
@ -11,7 +11,7 @@
</ion-segment> </ion-segment>
</ion-toolbar> </ion-toolbar>
<ion-toolbar> <ion-toolbar no-border-top>
<ion-buttons end> <ion-buttons end>
<button> <button>
<ion-icon name="search"></ion-icon> <ion-icon name="search"></ion-icon>
@ -117,7 +117,7 @@
</ion-segment> </ion-segment>
</ion-toolbar> </ion-toolbar>
<ion-toolbar> <ion-toolbar no-border-top no-border-bottom>
<ion-segment [(ngModel)]="appType" danger> <ion-segment [(ngModel)]="appType" danger>
<ion-segment-button value="paid"> <ion-segment-button value="paid">
Default Default
@ -131,7 +131,7 @@
</ion-segment> </ion-segment>
</ion-toolbar> </ion-toolbar>
<ion-toolbar> <ion-toolbar no-border-top>
<ion-segment [(ngModel)]="appType" dark [disabled]="isDisabled"> <ion-segment [(ngModel)]="appType" dark [disabled]="isDisabled">
<ion-segment-button value="paid"> <ion-segment-button value="paid">
Default Default

View File

@ -1,12 +1,12 @@
<ion-header> <ion-header>
<ion-navbar> <ion-navbar no-border-bottom>
<ion-title> <ion-title>
Segment under Navbar Segment under Navbar
</ion-title> </ion-title>
</ion-navbar> </ion-navbar>
<ion-toolbar> <ion-toolbar no-border-top>
<ion-segment [(ngModel)]="signInType"> <ion-segment [(ngModel)]="signInType">
<ion-segment-button value="new"> <ion-segment-button value="new">
New New

View File

@ -1,12 +1,12 @@
<ion-header> <ion-header>
<ion-navbar> <ion-navbar no-border-bottom>
<ion-title> <ion-title>
Segment Swipeable under Navbar Segment Swipeable under Navbar
</ion-title> </ion-title>
</ion-navbar> </ion-navbar>
<ion-toolbar> <ion-toolbar no-border-top>
<ion-segment [(ngModel)]="selectedSegment" (ionChange)="onSegmentChanged($event)"> <ion-segment [(ngModel)]="selectedSegment" (ionChange)="onSegmentChanged($event)">
<ion-segment-button value="first"> <ion-segment-button value="first">
First First

View File

@ -6,7 +6,7 @@ import {ionicBootstrap} from '../../../../../src';
templateUrl: 'main.html' templateUrl: 'main.html'
}) })
class E2EPage { class E2EPage {
musicAlertOpts; musicAlertOpts: any;
gender: string; gender: string;
gaming: string; gaming: string;
os: string; os: string;
@ -30,17 +30,13 @@ class E2EPage {
title: '1994 Music', title: '1994 Music',
subTitle: 'Select your favorite' subTitle: 'Select your favorite'
}; };
setTimeout(() => {
this.gender = 'm';
}, 1500);
} }
gamingCancel() { gamingCancel() {
console.log('Gaming Select, Cancel'); console.log('Gaming Select, Cancel');
} }
gamingChange(selectedValue) { gamingChange(selectedValue: any) {
console.log('Gaming Select, Change value:', selectedValue); console.log('Gaming Select, Change value:', selectedValue);
} }

View File

@ -8,4 +8,5 @@ ion-tabs ion-tabbar {
top: auto; top: auto;
height: auto; height: auto;
visibility: visible; visibility: visible;
opacity: 1;
} }

View File

@ -8,4 +8,5 @@ ion-tabs ion-tabbar {
top: auto; top: auto;
height: auto; height: auto;
visibility: visible; visibility: visible;
opacity: 1;
} }

View File

@ -14,8 +14,8 @@
<br /> <br />
<button block (click)="showDismissDurationToast()">Custom (1.5s) Duration</button> <button block (click)="showDismissDurationToast()">Custom (1.5s) Duration</button>
<button block (click)="showToastWithCloseButton('bottom')" class="e2eOpenToast">With closeButtonText</button> <button block (click)="showToastWithCloseButton('bottom')" class="e2eOpenToast">With closeButtonText</button>
<button block (click)="showToastWithCloseButton('top')" class="e2eOpenToast">Top With closeButtonText</button> <button block (click)="showToastWithCloseButton('top')">Top With closeButtonText</button>
<button block (click)="showToastWithCloseButton('middle')" class="e2eOpenToast">Middle With closeButtonText</button> <button block (click)="showToastWithCloseButton('middle')">Middle With closeButtonText</button>
<p> <p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed lacinia purus ac turpis fermentum, nec accumsan nulla rutrum. Aenean lorem est, luctus id iaculis ac, ultricies quis odio. Aenean imperdiet imperdiet ex et vehicula. Suspendisse vulputate turpis quis ultricies porttitor. Proin malesuada tortor at libero laoreet, eu eleifend enim pulvinar. Nulla facilisi. Fusce sit amet mauris mauris. Mauris consequat libero sed egestas tincidunt. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed lacinia purus ac turpis fermentum, nec accumsan nulla rutrum. Aenean lorem est, luctus id iaculis ac, ultricies quis odio. Aenean imperdiet imperdiet ex et vehicula. Suspendisse vulputate turpis quis ultricies porttitor. Proin malesuada tortor at libero laoreet, eu eleifend enim pulvinar. Nulla facilisi. Fusce sit amet mauris mauris. Mauris consequat libero sed egestas tincidunt.

View File

@ -38,43 +38,37 @@ $navbar-ios-height: $toolbar-ios-height !default;
} }
// iOS Header Toolbar
// --------------------------------------------------
ion-header {
border: 0;
border-bottom-width: 1px;
border-style: solid;
border-color: $toolbar-ios-border-color;
}
&.hairlines ion-header {
border-bottom-width: $hairlines-width;
}
// iOS Footer Toolbar
// --------------------------------------------------
ion-footer {
border: 0;
border-top-width: 1px;
border-style: solid;
border-color: $toolbar-ios-border-color;
}
&.hairlines ion-footer {
border-top-width: $hairlines-width;
}
// iOS Toolbar Background // iOS Toolbar Background
// -------------------------------------------------- // --------------------------------------------------
.toolbar-background { .toolbar-background {
border-top-width: 1px;
border-bottom-width: 1px;
border-style: solid;
border-color: $toolbar-ios-border-color;
background: $toolbar-ios-background; background: $toolbar-ios-background;
} }
&.hairlines .toolbar-background {
border-top-width: $hairlines-width;
border-bottom-width: $hairlines-width;
}
// iOS Toolbar Borders
// --------------------------------------------------
ion-header .toolbar:first-child .toolbar-background,
ion-menu > .toolbar:first-child .toolbar-background,
.toolbar[no-border-top] .toolbar-background {
border-top-width: 0;
}
ion-footer .toolbar:last-child .toolbar-background,
.toolbar[no-border-bottom] .toolbar-background {
border-bottom-width: 0;
}
// iOS Toolbar Content // iOS Toolbar Content
// -------------------------------------------------- // --------------------------------------------------

View File

@ -116,14 +116,25 @@ export class ToolbarBase extends Ion {
* | `left` | Positions element to the left of all other elements. | * | `left` | Positions element to the left of all other elements. |
* | `right` | Positions element to the right of all other elements. | * | `right` | Positions element to the right of all other elements. |
* *
* See [usage](#usage) below for some examples. *
* ### Multiple Toolbars
* Toolbars can be stacked up vertically in `<ion-header>`, `<ion-content>`, and
* `<ion-footer>` elements. However, toolbars also come with borders on both
* the top and bottom of the toolbar. To give developers full control of the
* design, Ionic also includes the `no-border-bottom` and `no-border-top` attributes.
* For example, sometimes two vertically stacked toolbars may have different
* background colors, in this case it might be best to leave a border between them.
* However, if they have the same background color, the app may look best without
* a border between them. The main point here is, it's entirely up to the app's design
* to decide when and when not to show borders between toolbars, and to do so then
* each toolbar can individually set `no-border-bottom` and `no-border-top` attributes.
* *
* *
* @usage * @usage
* ```html * ```html
* <ion-header> * <ion-header>
* *
* <ion-toolbar> * <ion-toolbar no-border-bottom>
* <ion-buttons start> * <ion-buttons start>
* <button> * <button>
* <ion-icon name="contact"></ion-icon> * <ion-icon name="contact"></ion-icon>
@ -135,7 +146,7 @@ export class ToolbarBase extends Ion {
* <ion-title>My Toolbar Title</ion-title> * <ion-title>My Toolbar Title</ion-title>
* </ion-toolbar> * </ion-toolbar>
* *
* <ion-toolbar> * <ion-toolbar no-border-top>
* <ion-title>I'm a subheader</ion-title> * <ion-title>I'm a subheader</ion-title>
* </ion-toolbar> * </ion-toolbar>
* *
@ -153,7 +164,7 @@ export class ToolbarBase extends Ion {
* *
* <ion-footer> * <ion-footer>
* *
* <ion-toolbar> * <ion-toolbar no-border-bottom>
* <ion-title>I'm a subfooter</ion-title> * <ion-title>I'm a subfooter</ion-title>
* <ion-buttons right> * <ion-buttons right>
* <button> * <button>
@ -162,7 +173,7 @@ export class ToolbarBase extends Ion {
* </ion-buttons> * </ion-buttons>
* </ion-toolbar> * </ion-toolbar>
* *
* <ion-toolbar> * <ion-toolbar no-border-top>
* <ion-title>I'm a footer</ion-title> * <ion-title>I'm a footer</ion-title>
* <ion-buttons end> * <ion-buttons end>
* <button> * <button>
@ -201,11 +212,20 @@ export class Toolbar extends ToolbarBase {
constructor( constructor(
@Optional() viewCtrl: ViewController, @Optional() viewCtrl: ViewController,
elementRef: ElementRef, @Optional() header: Header,
config: Config @Optional() footer: Footer,
config: Config,
elementRef: ElementRef
) { ) {
super(elementRef); super(elementRef);
viewCtrl && viewCtrl.setToolbarRef(elementRef);
if (viewCtrl && (header || footer)) {
// only toolbars within headers and footer are view toolbars
// toolbars within the content are not view toolbars, since they
// are apart of the content, and could be anywhere within the content
viewCtrl.setToolbarRef(elementRef);
}
this._sbPadding = config.getBoolean('statusbarPadding'); this._sbPadding = config.getBoolean('statusbarPadding');
} }