feat(components): cascade mode from parent to child components (#19369)

fixes #18285
This commit is contained in:
Brandy Carney
2019-10-08 15:46:59 -04:00
parent dbf6a448ff
commit 3dd5f05760
8 changed files with 269 additions and 94 deletions

View File

@ -21,8 +21,8 @@
</ion-header>
<ion-content>
<h2>Mode: ios</h2>
<ion-segment mode="ios" id="modeSegment" name="iosMode" value="kittens">
<h2>Mode: segment & button ios</h2>
<ion-segment mode="ios" value="kittens">
<ion-segment-button mode="ios" value="puppies">
<ion-label>Puppies</ion-label>
</ion-segment-button>
@ -34,10 +34,21 @@
</ion-segment-button>
</ion-segment>
<hr>
<h2>Mode: segment ios</h2>
<ion-segment mode="ios" value="kittens">
<ion-segment-button value="puppies">
<ion-label>Puppies</ion-label>
</ion-segment-button>
<ion-segment-button value="kittens">
<ion-label>Kittens</ion-label>
</ion-segment-button>
<ion-segment-button value="turtles">
<ion-label>Turtles</ion-label>
</ion-segment-button>
</ion-segment>
<h2>Mode: md</h2>
<ion-segment mode="md" name="mdMode" value="kittens">
<h2>Mode: segment ios, button: md</h2>
<ion-segment mode="ios" value="kittens">
<ion-segment-button mode="md" value="puppies">
<ion-label>Puppies</ion-label>
</ion-segment-button>
@ -48,6 +59,48 @@
<ion-label>Turtles</ion-label>
</ion-segment-button>
</ion-segment>
<hr>
<h2>Mode: segment & button md</h2>
<ion-segment mode="md" value="kittens">
<ion-segment-button mode="md" value="puppies">
<ion-label>Puppies</ion-label>
</ion-segment-button>
<ion-segment-button mode="md" value="kittens">
<ion-label>Kittens</ion-label>
</ion-segment-button>
<ion-segment-button mode="md" value="turtles">
<ion-label>Turtles</ion-label>
</ion-segment-button>
</ion-segment>
<h2>Mode: segment md</h2>
<ion-segment mode="md" value="kittens">
<ion-segment-button value="puppies">
<ion-label>Puppies</ion-label>
</ion-segment-button>
<ion-segment-button value="kittens">
<ion-label>Kittens</ion-label>
</ion-segment-button>
<ion-segment-button value="turtles">
<ion-label>Turtles</ion-label>
</ion-segment-button>
</ion-segment>
<h2>Mode: segment md, button: ios</h2>
<ion-segment mode="md" value="kittens">
<ion-segment-button mode="ios" value="puppies">
<ion-label>Puppies</ion-label>
</ion-segment-button>
<ion-segment-button mode="ios" value="kittens">
<ion-label>Kittens</ion-label>
</ion-segment-button>
<ion-segment-button mode="ios" value="turtles">
<ion-label>Turtles</ion-label>
</ion-segment-button>
</ion-segment>
</ion-content>
</ion-app>
</body>

View File

@ -0,0 +1,57 @@
@import "./title";
// iOS Title
// --------------------------------------------------
:host {
@include position(0, null, null, 0);
@include padding(0, 90px, 0);
position: absolute;
width: 100%;
height: 100%;
transform: translateZ(0);
font-size: 17px;
font-weight: 600;
text-align: center;
box-sizing: border-box;
pointer-events: none;
}
// iOS Title: Small
// --------------------------------------------------
:host(.title-small) {
@include padding(6px, 9px, 16px, 9px);
position: relative;
font-size: 13px;
font-weight: normal;
}
// iOS Title: Large
// --------------------------------------------------
:host(.title-large) {
@include padding(0, 16px);
bottom: 0;
align-items: flex-end;
min-width: 100%;
padding-bottom: 6px;
font-size: 34px;
font-weight: 700;
text-align: start;
}

View File

@ -0,0 +1,27 @@
@import "./title";
// Material Design Title
// --------------------------------------------------
:host {
@include padding(0, 20px);
font-size: 20px;
font-weight: 500;
letter-spacing: .0125em;
}
// Material Design Title: Small
// --------------------------------------------------
:host(.title-small) {
width: 100%;
height: 100%;
font-size: 15px;
font-weight: normal;
}

View File

@ -19,35 +19,6 @@
color: var(--color);
}
:host(.title-ios.title-default),
:host(.title-ios.title-large) {
@include position(0, null, null, 0);
@include padding(0, 90px, 0);
position: absolute;
width: 100%;
height: 100%;
transform: translateZ(0);
font-size: 17px;
font-weight: 600;
text-align: center;
box-sizing: border-box;
pointer-events: none;
}
:host(.title-md) {
@include padding(0, 20px);
font-size: 20px;
font-weight: 500;
letter-spacing: .0125em;
}
:host(.ion-color) {
color: #{current-color(base)};
}
@ -72,44 +43,3 @@
:host(.title-small) .toolbar-title {
white-space: normal;
}
:host(.title-ios.title-small) {
@include padding(6px, 9px, 16px, 9px);
width: 100%;
height: 100%;
font-size: 13px;
text-align: center;
}
:host(.title-md.title-small) {
width: 100%;
height: 100%;
font-size: 15px;
font-weight: normal;
}
// Title: Large
// --------------------------------------------------
:host(.title-ios.title-large) {
@include padding(0, 16px);
bottom: 0;
align-items: flex-end;
min-width: 100%;
padding-bottom: 6px;
font-size: 34px;
font-weight: 700;
text-align: start;
}

View File

@ -6,7 +6,10 @@ import { createColorClasses } from '../../utils/theme';
@Component({
tag: 'ion-title',
styleUrl: 'title.scss',
styleUrls: {
'ios': 'title.ios.scss',
'md': 'title.md.scss'
},
shadow: true
})
export class ToolbarTitle implements ComponentInterface {
@ -52,21 +55,14 @@ export class ToolbarTitle implements ComponentInterface {
return (this.size !== undefined) ? this.size : 'default';
}
private getMode() {
const mode = getIonMode(this);
const toolbar = this.el.closest('ion-toolbar');
return (toolbar && toolbar.mode) || mode;
}
render() {
const mode = this.getMode();
const mode = getIonMode(this);
const size = this.getSize();
return (
<Host
class={{
[mode]: true,
[`title-${mode}`]: true,
[`title-${size}`]: true,
...createColorClasses(this.color),

View File

@ -0,0 +1,19 @@
import { newE2EPage } from '@stencil/core/testing';
test('toolbar: modes', async () => {
const page = await newE2EPage({
url: '/src/components/toolbar/test/modes?ionic:_testing=true'
});
const compare = await page.compareScreenshot();
expect(compare).toMatchScreenshot();
});
test('toolbar:rtl: modes', async () => {
const page = await newE2EPage({
url: '/src/components/toolbar/test/modes?ionic:_testing=true&rtl=true'
});
const compare = await page.compareScreenshot();
expect(compare).toMatchScreenshot();
});

View File

@ -0,0 +1,84 @@
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="UTF-8">
<title>Toolbar - Modes</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
</head>
<body>
<ion-app>
<ion-content id="content">
<!-- iOS Toolbar -->
<ion-toolbar mode="ios">
<ion-title>iOS toolbar</ion-title>
</ion-toolbar>
<!-- Material Design Toolbar -->
<ion-toolbar mode="md">
<ion-title>MD toolbar</ion-title>
</ion-toolbar>
<!-- iOS Toolbar -->
<ion-toolbar mode="ios">
<ion-title>iOS toolbar</ion-title>
<ion-buttons slot="secondary">
<ion-button fill="outline">Outline</ion-button>
</ion-buttons>
<ion-buttons slot="primary">
<ion-button>Clear</ion-button>
<ion-button fill="solid">Solid</ion-button>
</ion-buttons>
</ion-toolbar>
<!-- Material Design Toolbar -->
<ion-toolbar mode="md">
<ion-title>MD toolbar</ion-title>
<ion-buttons slot="secondary">
<ion-button fill="outline">Outline</ion-button>
</ion-buttons>
<ion-buttons slot="primary">
<ion-button>Clear</ion-button>
<ion-button fill="solid">Solid</ion-button>
</ion-buttons>
</ion-toolbar>
<!-- iOS Toolbar -->
<ion-toolbar mode="ios">
<ion-searchbar></ion-searchbar>
</ion-toolbar>
<!-- Material Design Toolbar -->
<ion-toolbar mode="md">
<ion-searchbar></ion-searchbar>
</ion-toolbar>
<!-- iOS Toolbar -->
<ion-toolbar mode="ios">
<ion-segment>
<ion-segment-button>iOS</ion-segment-button>
<ion-segment-button checked>Segment</ion-segment-button>
</ion-segment>
</ion-toolbar>
<!-- Material Design Toolbar -->
<ion-toolbar mode="md">
<ion-segment>
<ion-segment-button>MD</ion-segment-button>
<ion-segment-button checked>Segment</ion-segment-button>
</ion-segment>
</ion-toolbar>
</ion-content>
</ion-app>
</body>
</html>

View File

@ -7,10 +7,10 @@ import { config, configFromSession, configFromURL, saveConfig } from './config';
declare const Context: any;
let mode: Mode;
let defaultMode: Mode;
export const getIonMode = (ref?: any): Mode => {
return (ref && getMode(ref)) || mode;
return (ref && getMode(ref)) || defaultMode;
};
export default () => {
@ -37,19 +37,28 @@ export default () => {
}
// first see if the mode was set as an attribute on <html>
// which could have been set by the user, or by prerendering
// which could have been set by the user, or by pre-rendering
// otherwise get the mode via config settings, and fallback to md
Ionic.config = config;
Ionic.mode = mode = config.get('mode', (doc.documentElement.getAttribute('mode')) || (isPlatform(win, 'ios') ? 'ios' : 'md'));
config.set('mode', mode);
doc.documentElement.setAttribute('mode', mode);
doc.documentElement.classList.add(mode);
Ionic.mode = defaultMode = config.get('mode', (doc.documentElement.getAttribute('mode')) || (isPlatform(win, 'ios') ? 'ios' : 'md'));
config.set('mode', defaultMode);
doc.documentElement.setAttribute('mode', defaultMode);
doc.documentElement.classList.add(defaultMode);
if (config.getBoolean('_testing')) {
config.set('animated', false);
}
setMode(
(elm: any) => (elm as any).mode = (elm as any).mode || elm.getAttribute('mode') || mode
);
setMode((elm: any) => {
while (elm) {
const elmMode = (elm as any).mode || elm.getAttribute('mode');
if (elmMode) {
return elmMode;
}
elm = elm.parentElement;
}
return defaultMode;
});
};