fix(content): better device suport (ios)

This commit is contained in:
Manu Mtz.-Almeida
2018-02-20 17:51:41 +01:00
parent b05eaeb85b
commit 69093551b2
16 changed files with 298 additions and 248 deletions

View File

@@ -761,6 +761,7 @@ declare global {
}
namespace JSXElements {
export interface IonContentAttributes extends HTMLAttributes {
forceOverscroll?: boolean;
fullscreen?: boolean;
}
}
@@ -2689,6 +2690,8 @@ declare global {
}
namespace JSXElements {
export interface IonScrollAttributes extends HTMLAttributes {
forceOverscroll?: boolean;
mode?: string;
onionScroll?: ScrollCallback;
onionScrollEnd?: ScrollCallback;
onionScrollStart?: ScrollCallback;

View File

@@ -29,3 +29,15 @@
a {
color: $app-ios-link-color;
}
// iOS Content Padding
// --------------------------------------------------
@include app-padding("ios", $content-ios-padding);
// iOS Content Margin
// --------------------------------------------------
@include app-margin("ios", $content-ios-margin);

View File

@@ -28,3 +28,14 @@
a {
color: $app-md-link-color;
}
// iOS Content Padding
// --------------------------------------------------
@include app-padding("md", $content-md-padding);
// iOS Content Margin
// --------------------------------------------------
@include app-margin("md", $content-md-margin);

View File

@@ -308,3 +308,105 @@ ion-toast-controller,
}
}
}
ion-app [no-padding],
ion-app [no-padding] .scroll-inner {
@include padding(0);
}
@mixin app-padding($mode, $content-padding) {
.app-#{$mode} [padding],
.app-#{$mode} [padding] .scroll-inner {
@include padding($content-padding);
}
.app-#{$mode} [padding-top],
.app-#{$mode} [padding-top] .scroll-inner {
@include padding($content-padding, null, null, null);
}
.app-#{$mode} [padding-left],
.app-#{$mode} [padding-left] .scroll-inner {
@include padding-horizontal($content-padding, null);
}
.app-#{$mode} [padding-right],
.app-#{$mode} [padding-right] .scroll-inner {
@include padding-horizontal(null, $content-padding);
}
.app-#{$mode} [padding-bottom],
.app-#{$mode} [padding-bottom] .scroll-inner {
@include padding(null, null, $content-padding, null);
}
.app-#{$mode} [padding-vertical],
.app-#{$mode} [padding-vertical] .scroll-inner {
@include padding($content-padding, null, $content-padding, null);
}
.app-#{$mode} [padding-horizontal],
.app-#{$mode} [padding-horizontal] .scroll-inner {
@include padding-horizontal($content-padding);
}
}
// Content Margin
// --------------------------------------------------
ion-app [no-margin],
ion-app [no-margin] ion-scroll {
@include margin(0);
}
@mixin app-margin($mode, $content-margin) {
.app-#{$mode} [margin],
.app-#{$mode} [margin] .scroll-inner {
@include margin($content-margin);
}
.app-#{$mode} [margin-top],
.app-#{$mode} [margin-top] .scroll-inner {
@include margin($content-margin, null, null, null);
}
.app-#{$mode} [margin-left],
.app-#{$mode} [margin-left] .scroll-inner {
// scss-lint:disable PropertySpelling
margin-left: $content-margin;
}
.app-#{$mode} [margin-start],
.app-#{$mode} [margin-start] .scroll-inner {
@include margin-horizontal($content-margin, null);
}
.app-#{$mode} [margin-right],
.app-#{$mode} [margin-right] .scroll-inner {
// scss-lint:disable PropertySpelling
margin-right: $content-margin;
}
.app-#{$mode} [margin-end],
.app-#{$mode} [margin-end] .scroll-inner {
@include margin-horizontal(null, $content-margin);
}
.app-#{$mode} [margin-bottom],
.app-#{$mode} [margin-bottom] .scroll-inner {
@include margin(null, null, $content-margin, null);
}
.app-#{$mode} [margin-vertical],
.app-#{$mode} [margin-vertical] .scroll-inner {
@include margin($content-margin, null, $content-margin, null);
}
.app-#{$mode} [margin-horizontal],
.app-#{$mode} [margin-horizontal] .scroll-inner {
@include margin-horizontal($content-margin);
}
}

View File

@@ -1,67 +0,0 @@
@import "./content";
@import "./content.ios.vars";
// iOS Content
// --------------------------------------------------
.content-ios {
font-family: $content-ios-font-family;
color: $text-ios-color;
background-color: $background-ios-color;
}
.content-ios.outer-content {
background: $content-ios-outer-background;
}
.content-ios hr {
height: $hairlines-width;
background-color: ion-color-alpha($background-ios-color-value, background-ios-color, $alpha-ios-low);
}
// iOS Content Padding
// --------------------------------------------------
@include content-padding("ios", $content-ios-padding);
// iOS Content Margin
// --------------------------------------------------
@include content-margin("ios", $content-ios-margin);
// iOS Content Scroll
// --------------------------------------------------
.content-ios:not([no-bounce]) > .scroll-content::before,
.content-ios:not([no-bounce]) > .scroll-content::after {
position: absolute;
width: 1px;
height: 1px;
content: "";
}
.content-ios:not([no-bounce]) > .scroll-content::before {
bottom: -1px;
}
.content-ios:not([no-bounce]) > .scroll-content::after {
top: -1px;
}
.platform-core .content-ios .scroll-content::after,
.platform-core .content-ios .scroll-content::before {
position: initial;
top: initial;
bottom: initial;
width: initial;
height: initial;
}

View File

@@ -1,28 +0,0 @@
@import "./content";
@import "./content.md.vars";
// Material Design Content
// --------------------------------------------------
.content-md {
font-family: $content-md-font-family;
color: $text-md-color;
background-color: $background-md-color;
}
.content-md hr {
background-color: $background-md-color-step-50;
}
// Material Design Content Padding
// --------------------------------------------------
@include content-padding("md", $content-md-padding);
// Material Design Content Margin
// --------------------------------------------------
@include content-margin("md", $content-md-margin);

View File

@@ -13,137 +13,6 @@ ion-content {
contain: layout size style;
margin: 0 !important; // scss-lint:disable all
padding: 0 !important; // scss-lint:disable all
}
// Scrollable Content
// --------------------------------------------------
ion-scroll {
@include position(0, 0, 0, 0);
position: absolute;
z-index: $z-index-scroll-content;
display: block;
overflow-x: hidden;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
will-change: scroll-position;
contain: size style layout;
}
ion-content.js-scroll ion-scroll {
position: relative;
min-height: 100%;
overflow-x: initial;
overflow-y: initial;
-webkit-overflow-scrolling: auto;
will-change: initial;
}
// Content Padding
// --------------------------------------------------
ion-app [no-padding],
ion-app [no-padding] ion-scroll {
@include padding(0);
}
@mixin content-padding($mode, $content-padding) {
.app-#{$mode} [padding],
.app-#{$mode} [padding] .scroll-inner {
@include padding($content-padding);
}
.app-#{$mode} [padding-top],
.app-#{$mode} [padding-top] .scroll-inner {
@include padding($content-padding, null, null, null);
}
.app-#{$mode} [padding-left],
.app-#{$mode} [padding-left] .scroll-inner {
@include padding-horizontal($content-padding, null);
}
.app-#{$mode} [padding-right],
.app-#{$mode} [padding-right] .scroll-inner {
@include padding-horizontal(null, $content-padding);
}
.app-#{$mode} [padding-bottom],
.app-#{$mode} [padding-bottom] .scroll-inner {
@include padding(null, null, $content-padding, null);
}
.app-#{$mode} [padding-vertical],
.app-#{$mode} [padding-vertical] .scroll-inner {
@include padding($content-padding, null, $content-padding, null);
}
.app-#{$mode} [padding-horizontal],
.app-#{$mode} [padding-horizontal] .scroll-inner {
@include padding-horizontal($content-padding);
}
}
// Content Margin
// --------------------------------------------------
ion-app [no-margin],
ion-app [no-margin] ion-scroll {
@include margin(0);
}
@mixin content-margin($mode, $content-margin) {
.app-#{$mode} [margin],
.app-#{$mode} [margin] ion-scroll {
@include margin($content-margin);
}
.app-#{$mode} [margin-top],
.app-#{$mode} [margin-top] ion-scroll {
@include margin($content-margin, null, null, null);
}
.app-#{$mode} [margin-left],
.app-#{$mode} [margin-left] ion-scroll {
// scss-lint:disable PropertySpelling
margin-left: $content-margin;
}
.app-#{$mode} [margin-start],
.app-#{$mode} [margin-start] ion-scroll {
@include margin-horizontal($content-margin, null);
}
.app-#{$mode} [margin-right],
.app-#{$mode} [margin-right] ion-scroll {
// scss-lint:disable PropertySpelling
margin-right: $content-margin;
}
.app-#{$mode} [margin-end],
.app-#{$mode} [margin-end] ion-scroll {
@include margin-horizontal(null, $content-margin);
}
.app-#{$mode} [margin-bottom],
.app-#{$mode} [margin-bottom] ion-scroll {
@include margin(null, null, $content-margin, null);
}
.app-#{$mode} [margin-vertical],
.app-#{$mode} [margin-vertical] ion-scroll {
@include margin($content-margin, null, $content-margin, null);
}
.app-#{$mode} [margin-horizontal],
.app-#{$mode} [margin-horizontal] ion-scroll {
@include margin-horizontal($content-margin);
}
}

View File

@@ -1,14 +1,10 @@
import { Component, Element, Listen, Method, Prop } from '@stencil/core';
import { Config, DomController } from '../../index';
import { createThemedClasses, getElementClassMap } from '../../utils/theme';
import { getPageElement } from '../../utils/helpers';
@Component({
tag: 'ion-content',
styleUrls: {
ios: 'content.ios.scss',
md: 'content.md.scss'
}
styleUrl: 'content.scss'
})
export class Content {
@@ -32,6 +28,8 @@ export class Content {
*/
@Prop() fullscreen = false;
@Prop() forceOverscroll: boolean;
@Listen('body:ionNavChanged')
onNavChanged() {
this.resize();
@@ -112,18 +110,10 @@ export class Content {
}
render() {
const themedClasses = createThemedClasses(this.mode, this.color, 'content');
const hostClasses = getElementClassMap(this.el.classList);
const scrollClasses = {
...themedClasses,
...hostClasses,
};
this.resize();
return [
<ion-scroll class={scrollClasses}>
<ion-scroll mode={this.mode} forceOverscroll={this.forceOverscroll}>
<slot></slot>
</ion-scroll>,
<slot name='fixed'></slot>

View File

@@ -16,6 +16,11 @@ view component.
## Properties
#### forceOverscroll
boolean
#### fullscreen
boolean
@@ -27,6 +32,11 @@ to transparent.
## Attributes
#### force-overscroll
boolean
#### fullscreen
boolean

View File

@@ -7,6 +7,16 @@
## Properties
#### forceOverscroll
boolean
#### mode
string
#### onionScroll
@@ -24,6 +34,16 @@
## Attributes
#### force-overscroll
boolean
#### mode
string
#### onion-scroll

View File

@@ -0,0 +1,22 @@
@import "./scroll";
@import "./scroll.ios.vars";
// iOS Content
// --------------------------------------------------
.outer-content .scroll-ios {
background: $content-ios-outer-background;
}
.scroll-ios {
font-family: $content-ios-font-family;
color: $text-ios-color;
background-color: $background-ios-color;
}
.scroll-ios hr {
height: $hairlines-width;
background-color: ion-color-alpha($background-ios-color-value, background-ios-color, $alpha-ios-low);
}

View File

@@ -4,7 +4,7 @@
// --------------------------------------------------
/// @prop - Font family of the content
$content-ios-font-family: $font-family-ios-base !default;
$content-ios-font-family: $font-family-ios-base !default;
/// @prop - Background color of the outer content
$content-ios-outer-background: $background-ios-color-step-50 !default;
$content-ios-outer-background: $background-ios-color-step-50 !default;

View File

@@ -0,0 +1,16 @@
@import "./scroll";
@import "./scroll.md.vars";
// Material Design Content
// --------------------------------------------------
.scroll-md {
font-family: $content-md-font-family;
color: $text-md-color;
background-color: $background-md-color;
hr {
background-color: $background-md-color-step-50;
}
}

View File

@@ -4,4 +4,4 @@
// --------------------------------------------------
/// @prop - Font family of the content
$content-md-font-family: $font-family-md-base !default;
$content-md-font-family: $font-family-md-base !default;

View File

@@ -0,0 +1,54 @@
@import "../../themes/ionic.globals";
ion-scroll {
@include position(0, 0, 0, 0);
position: absolute;
z-index: $z-index-scroll-content;
display: block;
overflow-x: hidden;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
will-change: scroll-position;
contain: size style layout;
margin: 0 !important; // scss-lint:disable all
padding: 0 !important; // scss-lint:disable all
.focus-input {
@include margin(0);
@include padding(0);
position: absolute;
width: 0;
height: 0;
border: 0;
background: none;
opacity: 0;
appearance: none;
}
&.overscroll::before,
&.overscroll::after {
position: absolute;
width: 1px;
height: 1px;
content: "";
}
&.overscroll::before {
bottom: -1px;
}
&.overscroll::after {
top: -1px;
}
}

View File

@@ -4,7 +4,14 @@ import { GestureDelegate } from '../gesture-controller/gesture-controller';
@Component({
tag: 'ion-scroll'
tag: 'ion-scroll',
styleUrls: {
ios: 'scroll.ios.scss',
md: 'scroll.md.scss'
},
host: {
theme: 'scroll'
}
})
export class Scroll {
@@ -24,6 +31,9 @@ export class Scroll {
@Prop({ context: 'dom' }) dom: DomController;
@Prop({ context: 'isServer' }) isServer: boolean;
@Prop() mode: string;
@Prop({mutable: true}) forceOverscroll: boolean;
@Prop() onionScrollStart: ScrollCallback;
@Prop() onionScroll: ScrollCallback;
@Prop() onionScrollEnd: ScrollCallback;
@@ -55,6 +65,9 @@ export class Scroll {
if (this.isServer) {
return;
}
if (this.forceOverscroll === undefined) {
this.forceOverscroll = this.mode === 'ios' && ('ontouchstart' in window);
}
this.app = this.el.closest('ion-app') as HTMLIonAppElement;
}
@@ -77,6 +90,11 @@ export class Scroll {
}
}
@Listen('touchend', {passive: true, capture: true })
onTouchEnd(_ev: TouchEvent) {
this.refocus();
}
@Method()
scrollToTop(duration: number): Promise<void> {
return this.scrollToPoint(0, 0, duration);
@@ -280,15 +298,33 @@ export class Scroll {
this.onionScrollEnd(detail);
}
this.ionScrollEnd.emit(detail);
this.refocus();
}
private refocus() {
setTimeout(() => {
if (document.activeElement === document.body) {
(this.el.querySelector('.focus-input') as HTMLElement).focus();
}
});
}
hostData() {
return {
class: {
overscroll: this.forceOverscroll
}
};
}
render() {
return (
return [
// scroll-inner is used to keep custom user padding
<div class='scroll-inner'>
<slot></slot>
</div>
);
</div>,
<input type='button' class='focus-input'/>
];
}
}