mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
feat(components): cascade mode from parent to child components (#19369)
fixes #18285
This commit is contained in:
@ -21,8 +21,8 @@
|
|||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<h2>Mode: ios</h2>
|
<h2>Mode: segment & button ios</h2>
|
||||||
<ion-segment mode="ios" id="modeSegment" name="iosMode" value="kittens">
|
<ion-segment mode="ios" value="kittens">
|
||||||
<ion-segment-button mode="ios" value="puppies">
|
<ion-segment-button mode="ios" value="puppies">
|
||||||
<ion-label>Puppies</ion-label>
|
<ion-label>Puppies</ion-label>
|
||||||
</ion-segment-button>
|
</ion-segment-button>
|
||||||
@ -34,10 +34,21 @@
|
|||||||
</ion-segment-button>
|
</ion-segment-button>
|
||||||
</ion-segment>
|
</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>
|
<h2>Mode: segment ios, button: md</h2>
|
||||||
<ion-segment mode="md" name="mdMode" value="kittens">
|
<ion-segment mode="ios" value="kittens">
|
||||||
<ion-segment-button mode="md" value="puppies">
|
<ion-segment-button mode="md" value="puppies">
|
||||||
<ion-label>Puppies</ion-label>
|
<ion-label>Puppies</ion-label>
|
||||||
</ion-segment-button>
|
</ion-segment-button>
|
||||||
@ -48,6 +59,48 @@
|
|||||||
<ion-label>Turtles</ion-label>
|
<ion-label>Turtles</ion-label>
|
||||||
</ion-segment-button>
|
</ion-segment-button>
|
||||||
</ion-segment>
|
</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-content>
|
||||||
</ion-app>
|
</ion-app>
|
||||||
</body>
|
</body>
|
||||||
|
57
core/src/components/title/title.ios.scss
Normal file
57
core/src/components/title/title.ios.scss
Normal 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;
|
||||||
|
}
|
27
core/src/components/title/title.md.scss
Normal file
27
core/src/components/title/title.md.scss
Normal 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;
|
||||||
|
}
|
||||||
|
|
@ -19,35 +19,6 @@
|
|||||||
color: var(--color);
|
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) {
|
:host(.ion-color) {
|
||||||
color: #{current-color(base)};
|
color: #{current-color(base)};
|
||||||
}
|
}
|
||||||
@ -72,44 +43,3 @@
|
|||||||
:host(.title-small) .toolbar-title {
|
:host(.title-small) .toolbar-title {
|
||||||
white-space: normal;
|
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;
|
|
||||||
}
|
|
||||||
|
@ -6,7 +6,10 @@ import { createColorClasses } from '../../utils/theme';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
tag: 'ion-title',
|
tag: 'ion-title',
|
||||||
styleUrl: 'title.scss',
|
styleUrls: {
|
||||||
|
'ios': 'title.ios.scss',
|
||||||
|
'md': 'title.md.scss'
|
||||||
|
},
|
||||||
shadow: true
|
shadow: true
|
||||||
})
|
})
|
||||||
export class ToolbarTitle implements ComponentInterface {
|
export class ToolbarTitle implements ComponentInterface {
|
||||||
@ -52,21 +55,14 @@ export class ToolbarTitle implements ComponentInterface {
|
|||||||
return (this.size !== undefined) ? this.size : 'default';
|
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() {
|
render() {
|
||||||
const mode = this.getMode();
|
const mode = getIonMode(this);
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Host
|
<Host
|
||||||
class={{
|
class={{
|
||||||
[mode]: true,
|
[mode]: true,
|
||||||
[`title-${mode}`]: true,
|
|
||||||
[`title-${size}`]: true,
|
[`title-${size}`]: true,
|
||||||
|
|
||||||
...createColorClasses(this.color),
|
...createColorClasses(this.color),
|
||||||
|
19
core/src/components/toolbar/test/modes/e2e.ts
Normal file
19
core/src/components/toolbar/test/modes/e2e.ts
Normal 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();
|
||||||
|
});
|
84
core/src/components/toolbar/test/modes/index.html
Normal file
84
core/src/components/toolbar/test/modes/index.html
Normal 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>
|
@ -7,10 +7,10 @@ import { config, configFromSession, configFromURL, saveConfig } from './config';
|
|||||||
|
|
||||||
declare const Context: any;
|
declare const Context: any;
|
||||||
|
|
||||||
let mode: Mode;
|
let defaultMode: Mode;
|
||||||
|
|
||||||
export const getIonMode = (ref?: any): Mode => {
|
export const getIonMode = (ref?: any): Mode => {
|
||||||
return (ref && getMode(ref)) || mode;
|
return (ref && getMode(ref)) || defaultMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
@ -37,19 +37,28 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// first see if the mode was set as an attribute on <html>
|
// 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
|
// otherwise get the mode via config settings, and fallback to md
|
||||||
Ionic.config = config;
|
Ionic.config = config;
|
||||||
Ionic.mode = mode = config.get('mode', (doc.documentElement.getAttribute('mode')) || (isPlatform(win, 'ios') ? 'ios' : 'md'));
|
Ionic.mode = defaultMode = config.get('mode', (doc.documentElement.getAttribute('mode')) || (isPlatform(win, 'ios') ? 'ios' : 'md'));
|
||||||
config.set('mode', mode);
|
config.set('mode', defaultMode);
|
||||||
doc.documentElement.setAttribute('mode', mode);
|
doc.documentElement.setAttribute('mode', defaultMode);
|
||||||
doc.documentElement.classList.add(mode);
|
doc.documentElement.classList.add(defaultMode);
|
||||||
|
|
||||||
if (config.getBoolean('_testing')) {
|
if (config.getBoolean('_testing')) {
|
||||||
config.set('animated', false);
|
config.set('animated', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
setMode(
|
setMode((elm: any) => {
|
||||||
(elm: any) => (elm as any).mode = (elm as any).mode || elm.getAttribute('mode') || mode
|
while (elm) {
|
||||||
);
|
const elmMode = (elm as any).mode || elm.getAttribute('mode');
|
||||||
|
|
||||||
|
if (elmMode) {
|
||||||
|
return elmMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
elm = elm.parentElement;
|
||||||
|
}
|
||||||
|
return defaultMode;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user