Skip to content

Commit

Permalink
Merge pull request #110 from sebgroup/feature/ios-modal
Browse files Browse the repository at this point in the history
Feature/ios modal
  • Loading branch information
hjalmers authored Apr 4, 2019
2 parents 62271b0 + 7879c63 commit a7498d3
Show file tree
Hide file tree
Showing 10 changed files with 709 additions and 32 deletions.
639 changes: 623 additions & 16 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"e2e-ci": "ng e2e --protractor-config=e2e/protractor-ci.conf.js",
"commit": "git-cz",
"travis-deploy-once": "travis-deploy-once --pro",
"semantic-release": "semantic-release && npm run build && npm run build-sdl"
"semantic-release": "semantic-release && npm run build && npm run build-sdl",
"package-lock-sanitizer": "package-lock-sanitizer"
},
"config": {
"commitizen": {
Expand All @@ -49,6 +50,7 @@
},
"husky": {
"hooks": {
"pre-commit": "npm run package-lock-sanitizer && git add package-lock.json",
"commit-msg": "commitlint --edit"
}
},
Expand All @@ -69,7 +71,7 @@
"@fortawesome/angular-fontawesome": "^0.1.1",
"@fortawesome/fontawesome-svg-core": "^1.2.15",
"@fortawesome/pro-light-svg-icons": "^5.7.2",
"@ng-bootstrap/ng-bootstrap": "^4.0.3",
"@ng-bootstrap/ng-bootstrap": "^4.1.1",
"@sebgroup/fonts": "^1.0.0",
"angular-exemplify": "^3.1.3",
"core-js": "^2.6.5",
Expand Down Expand Up @@ -118,7 +120,9 @@
"karma-coverage-istanbul-reporter": "^2.0.5",
"karma-jasmine": "~1.1.1",
"karma-jasmine-html-reporter": "^0.2.2",
"mobile-detect": "^1.4.3",
"node-sass-tilde-importer": "^1.0.2",
"package-lock-sanitizer": "^1.0.0",
"postcss-cli": "^6.1.1",
"prismjs": "^1.15.0",
"protractor": "^5.4.2",
Expand Down
5 changes: 3 additions & 2 deletions scss/styles/_modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
&.modal-aside-right {
.modal-dialog {
right: 0;
position: fixed;
@include media-breakpoint-up(md) {
position: fixed;
@include add-transition('slideInRight');
}
}
}
&.modal-aside-left {
.modal-dialog {
left: 0;
position: fixed;
@include media-breakpoint-up(md) {
position: fixed;
@include add-transition('slideInLeft');
}
}
Expand Down Expand Up @@ -66,6 +66,7 @@
height: 100vh;
max-width: 100vw;
max-height: 100vh;
position: fixed;
@include add-transition('slideInUp');
.modal-content {
border:none;
Expand Down
7 changes: 6 additions & 1 deletion scss/third-parties/ng-bootstrap/mixins/_ngb-dropdown.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@
display: block;
}

//dropdown style for mobile
// dropdown style for mobile
@include media-breakpoint-down(xs) {
// placement fix for container body
body > .dropdown {
z-index: $zindex-modal;
transform: none !important;
}
#{$selector}.show {
[ngbdropdowntoggle] {
z-index: $zindex-modal;
Expand Down
20 changes: 14 additions & 6 deletions src/example/components/dropdowns/dropdowns.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ <h4 class="card-header">
<div class="alert alert-info mt-5">
<strong>Framework needed!</strong> Please note that the examples below uses a framework for Angular called <a class="alert-link" href="https://ng-bootstrap.github.io/" target="_blank">ng-bootstrap</a> and their <a class="alert-link" href="https://ng-bootstrap.github.io/#/components/dropdown/" target="_blank">dropdown component</a>, so in order to use the components below you need to add ng-bootstrap to your project.
</div>
<div class="alert alert-warning mx-n3 mx-md-0">
<strong>Mobile development!</strong> To make the experience extra crisp on mobile devices and more specifically to avoid the issue with scrolling content behind the dropdown on mobile devices, you should consider adding <a class="alert-link" href="https://github.com/willmcpo/body-scroll-lock" target="_blank">body scroll lock</a> to your project when implementing dropdowns. An example implementation for angular can also be found on <a class="alert-link" href="https://stackblitz.com/edit/seb-dropdown-body-scroll-lock" target="_blank">stack blitz</a>.
<br><br><strong>Dropdown cut off?</strong> If the dropdown is placed inside a container with overflow set to auto or hidden you should consider adding container="body" to add the dropdown to the body element instead, this to avoid cutting off the dropdown menu.
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheckInline" [checked]="useContainerBody" (change)="toggleContainer(useContainerBody)">
<label class="custom-control-label" for="customCheckInline">Use container='body'</label>
</div>
</div>
<div class="card mb-4 mx-n3 mx-md-0" id="dropdownExample">
<h4 class="card-header">
Angular dropdown select
Expand All @@ -33,9 +41,9 @@ <h4 class="card-header">
<div class="row">
<div class="col-12 col-sm-auto">
<label for="ngb_dropdown">Example dropdown select</label>
<div ngbDropdown>
<div ngbDropdown [container]="useContainerBody ? 'body' : 'null'" (openChange)="toggleBodyLock($event, dropdownMenu)">
<button class="btn btn-outline-primary w-100" id="ngb_dropdown" ngbDropdownToggle>{{selected ? selected:'select...'}}</button>
<div ngbDropdownMenu aria-labelledby="dropdownExample" class="w-100 mb-3">
<div ngbDropdownMenu aria-labelledby="dropdownExample" class="w-100 mb-3" #dropdownMenu>
<button *ngFor="let option of options" class="dropdown-item" (click)="selected = option" [ngClass]="{'active':selected === option}">{{option}}</button>
</div>
</div>
Expand All @@ -57,7 +65,7 @@ <h4 class="card-header">
<div class="row">
<div class="col-12 col-sm-auto">
<label for="ngb_multiselect">Example multi-select</label>
<div ngbDropdown #multiSelect="ngbDropdown">
<div ngbDropdown #multiSelect="ngbDropdown" [container]="useContainerBody ? 'body' : 'null'">
<button ngClass="{{classes ? classes:'btn btn-secondary w-100'}}" id="ngb_multiselect" ngbDropdownToggle>{{selectedMulti.length === 0 ? 'select...': selectedMulti.length === 1 ? selectedMulti[0]: selectedMulti.length + ' selected'}}</button>
<div ngbDropdownMenu aria-labelledby="ngb_multiselect" class="w-100 mb-3">
<div class="dropdown-control">
Expand Down Expand Up @@ -95,7 +103,7 @@ <h4 class="card-header">
<div class="row">
<div class="col-12 col-sm-auto">
<label for="dropdownSmall">Small dropdown select</label>
<div ngbDropdown>
<div ngbDropdown [container]="useContainerBody ? 'body' : 'null'">
<button class="btn btn-secondary btn-sm w-100" id="dropdownSmall" ngbDropdownToggle>{{selected ? selected:'select...'}}</button>
<div ngbDropdownMenu aria-labelledby="dropdownSmall" class="w-100 mb-3">
<button *ngFor="let option of options" class="dropdown-item" (click)="selected = option" [ngClass]="{'active':selected === option}">{{option}}</button>
Expand All @@ -106,7 +114,7 @@ <h4 class="card-header">
<div class="row">
<div class="col-12 col-sm-auto">
<label for="dropdownNormal">Normal dropdown select</label>
<div ngbDropdown>
<div ngbDropdown [container]="useContainerBody ? 'body' : 'null'">
<button class="btn btn-secondary w-100" id="dropdownNormal" ngbDropdownToggle>{{selected ? selected:'select...'}}</button>
<div ngbDropdownMenu aria-labelledby="dropdownNormal" class="w-100 mb-3">
<button *ngFor="let option of options" class="dropdown-item" (click)="selected = option" [ngClass]="{'active':selected === option}">{{option}}</button>
Expand All @@ -117,7 +125,7 @@ <h4 class="card-header">
<div class="row">
<div class="col-12 col-sm-auto">
<label for="dropdownLarge">Large dropdown select</label>
<div ngbDropdown>
<div ngbDropdown [container]="useContainerBody ? 'body' : 'null'">
<button class="btn btn-secondary btn-lg w-100" id="dropdownLarge" ngbDropdownToggle>{{selected ? selected:'select...'}}</button>
<div ngbDropdownMenu aria-labelledby="dropdownLarge" class="w-100 mb-3">
<button *ngFor="let option of options" class="dropdown-item" (click)="selected = option" [ngClass]="{'active':selected === option}">{{option}}</button>
Expand Down
19 changes: 18 additions & 1 deletion src/example/components/dropdowns/dropdowns.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock';
import { MobileDetectService } from '../../services/mobile-detect.service';

@Component({
selector: 'app-dropdowns',
Expand All @@ -7,11 +9,12 @@ import { Component, OnInit } from '@angular/core';
})
export class DropdownsComponent implements OnInit {

constructor() { }
constructor(private mobileDetectService: MobileDetectService) { }

options: Array<string> = ['First', 'Second', 'Third', 'Forth']; // available options, used by dropdown and multi-select example
selected: string; // selected option for dropdown example
selectedMulti: Array<string> = []; // selected options for multi-select example
useContainerBody = true;

/**
* Select
Expand Down Expand Up @@ -49,6 +52,20 @@ export class DropdownsComponent implements OnInit {
this.selectedMulti = [];
}

toggleBodyLock(show: boolean, templateRef: any) {
if (this.mobileDetectService.isMobile()) {
if (show) {
disableBodyScroll(templateRef);
} else {
enableBodyScroll(templateRef);
}
}
}

toggleContainer(value: boolean) {
this.useContainerBody = !this.useContainerBody;
}

ngOnInit() {
}

Expand Down
2 changes: 1 addition & 1 deletion src/example/components/modals/modals.component.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<a name="modals"><h2 class="my-3">Modals</h2></a>
<div class="alert alert-info mx-n3 mx-md-0"><strong>Framework needed!</strong> Please note that the examples below is just a representation of how modals look and the needed markup. In order to use modals you need a framework to control when and how to show them. If you're using angular, please take a look at <a class="alert-link" href="https://ng-bootstrap.github.io/" target="_blank">ng-bootstrap</a> and their <a class="alert-link" href="https://ng-bootstrap.github.io/#/components/modal" target="_blank">modal component</a>.</div>
<div class="alert alert-warning mx-n3 mx-md-0"><strong>Mobile development!</strong> To make the experience extra crisp on mobile devices and more specifically to avoid the issue with <a class="alert-link" href="https://www.google.com/search?q=content+scrolling+behind+modal" target="_blank">scrolling content behind the modal</a>, you should consider adding <a class="alert-link" href="https://github.com/willmcpo/body-scroll-lock" target="_blank">body scroll lock</a> to your project when implementing modals. An example implementation for angular can also be found on <a class="alert-link" href="https://seb-modal-body-scroll-lock.stackblitz.io" target="_blank">stack blitz</a>.</div>
<div class="alert alert-warning mx-n3 mx-md-0"><strong>Mobile development!</strong> To make the experience extra crisp on mobile devices and more specifically to avoid the issue with <a class="alert-link" href="https://www.google.com/search?q=content+scrolling+behind+modal" target="_blank">scrolling content behind the modal</a>, you should consider adding <a class="alert-link" href="https://github.com/willmcpo/body-scroll-lock" target="_blank">body scroll lock</a> to your project when implementing modals. An example implementation for angular can also be found on <a class="alert-link" href="https://stackblitz.com/edit/seb-modal-body-scroll-lock" target="_blank">stack blitz</a>.</div>
<div class="card mx-n3 mx-md-0" id="modalExample">
<h4 class="card-header">Standard modal</h4>
<div class="card-body bg-secondary px-0">
Expand Down
8 changes: 5 additions & 3 deletions src/example/components/modals/modals.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {Component, OnInit} from '@angular/core';
import {Component, Inject, OnInit} from '@angular/core';
import {ModalDismissReasons, NgbModal, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap';
import { disableBodyScroll, enableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock';
import {DOCUMENT} from '@angular/common';

@Component({
selector: 'app-modals',
Expand All @@ -23,14 +24,15 @@ export class ModalsComponent implements OnInit {
takeOverModal = false;
closeResult: string;

constructor(private modalService: NgbModal) {}
constructor(@Inject(DOCUMENT) private document: Document,
private modalService: NgbModal) {}

open(content, options? : NgbModalOptions) {

const modalRef = this.modalService.open(content, {...options, ariaLabelledBy: 'modal-basic-title'});

// workaround for iOS scroll that allows scroll in modal body
const contentBody = modalRef['_contentRef'].nodes[0][1];
const contentBody = document.getElementsByTagName('ngb-modal-window')[0];
modalRef.result.then((result) => {
clearAllBodyScrollLocks();
this.closeResult = `Closed with: ${result}`;
Expand Down
12 changes: 12 additions & 0 deletions src/example/services/mobile-detect.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';

import { MobileDetectService } from './mobile-detect.service';

describe('MobileDetectService', () => {
beforeEach(() => TestBed.configureTestingModule({}));

it('should be created', () => {
const service: MobileDetectService = TestBed.get(MobileDetectService);
expect(service).toBeTruthy();
});
});
21 changes: 21 additions & 0 deletions src/example/services/mobile-detect.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Injectable } from '@angular/core';
import * as Detect from 'mobile-detect';

@Injectable({
providedIn: 'root'
})
export class MobileDetectService {

constructor() { }

_nativeWindow: Window = window;

get nativeWindow() {
return this._nativeWindow;
}

isMobile(): boolean {
const md = new Detect(this.nativeWindow.navigator.userAgent);
return !!md.mobile();
}
}

0 comments on commit a7498d3

Please sign in to comment.