Cupertino Panes
Cupertino Panes is multi-functional panes & boards with touch technologies.
- Small. 12kb (minified and gzipped bundle with all modules). No dependencies.
- Modularized. Add extra features to your panes and create own modules.
- Accelerated. Hardware accelerated transitions and amazing native behavior.
- Progressive. Useful for mobile/web/hybrid applications.
Right like in Apple Maps, Apple Stocks, Apple Music and other modern apps.
- Demonstration
- Financial Contributors
- Supporting platforms
- Getting Started
- Modules
- Settings
- Breakpoints
- Z-Stack
- Events
- Public Methods
- Attributes
- CSS Variables
- Keyboard issues
- Future Goals
- Contributors
- Changelog
- License
Financial Contributors
Become a financial contributor and help us sustain our community. [Contribute]
Individuals
Organizations
Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]
Demonstration
- Picture-in-Picture live
- Rich notifications live
- Base live
- Overflow top live
- Z-stack full live
- Z-Stack simple live
- 3D Push live
- Overflow top-middle live
- Draggable over live
- Prevent dismiss live
- Top-to-bottom live
- Follower live
- Apple Clips live
- Bulletin live
- Starbucks live
- Backdrop drag-opacity live
Supporting platforms
We officially support the last two versions of every major browser. Specifically, we test on the following browsers
Browser | Operating system |
---|---|
Chrome | Android, Windows, macOS, and Linux |
Firefox | Windows, macOS, and Linux |
Safari | iOS |
WkWebView | iOS |
Android WebView | Android |
Getting Started
Install via NPM
npm install cupertino-pane
Use from CDN
If you don't want to include Cupertino Pane files in your project, you may use it from CDN. The following files are available:
<script src="https://unpkg.com/cupertino-pane/dist/cupertino-pane.js"></script>
<script src="https://unpkg.com/cupertino-pane/dist/cupertino-pane.min.js"></script>
Include Files To App/Website
<!DOCTYPE html>
<html lang="en">
<body>
...
<script src="path/to/cupertino-pane.min.js"></script>
</body>
</html>
Add HTML Layout
<div class="cupertino-pane">
<h1>Header</h1>
<div class="content">Content</div>
</div>
Additional CSS Styles
.cupertino-pane {
margin: 20px;
}
Initialize Cupertino Pane
<body>
...
<script>
window.onload = function () {
var myPane = new CupertinoPane(
'.cupertino-pane', // Pane container selector
{
parentElement: 'body', // Parent container
breaks: {
middle: { enabled: true, height: 300, bounce: true },
bottom: { enabled: true, height: 80 },
},
events: {
onDrag: () => console.log('Drag event')
}
}
);
myPane.present({animate: true}).then(res => {...});
};
</script>
</body>
jQuery example
$(document).ready(function () {
//initialize pane when document ready
var myPane = new CupertinoPane('.cupertino-pane', { /* ... */ });
myPane.present({animate: true}).then(...);
});
As an ES module
Cupertino Pane package comes with ES module version which can be used where supported or with bundlers like Webpack or Rollup:
import { CupertinoPane, CupertinoSettings } from 'cupertino-pane';
let settings: CupertinoSettings = { /* ... */ };
let myPane = new CupertinoPane('.cupertino-pane', settings);
await myPane.present({animate: true});
Class creation
You can pass html element or string selector to class constructor
// String selector
new CupertinoPane('.cupertino-pane');
// HTML element
let element = document.querySelector('.cupertino-pane');
new CupertinoPane(element); // HTMLElement
Modules
Available modules: ZStackModule, FollowerModule, BackdropModule, FitHeightModule, InverseModule, HorizontalModule
Modular architecture of the project helps us to keep small size of bundles, also huge scalability features are possible.
We are welcome to creators β feel free to make your own modules!
Examples of modules can be found here
Install es bundle with all modules
By default you will import esm
with all modules in bundle:
import { CupertinoPane } from 'cupertino-pane';
Size of this bundle might be more than you need, if you don't use all features and modules.
Install es bundle with specific modules
Pick modules that you need to decrease bundle size:
import { CupertinoPane } from 'cupertino-pane/dist/core';
import { BackdropModule, FitHeightModule } from 'cupertino-pane/dist/modules';
let myPane = new CupertinoPane('.cupertino-pane', {
modules: [BackdropModule, FitHeightModule],
fitHeight: true,
backdrop: true
});
Be sure that you're import only core
version here with modules
you need.
You can check installed modules:
console.log(myPane.modules);
Build your own umd bundles with specific modules
Clone repository and run commands:
npm run build // will include all modules
npm run build -- --modules="" // will not include any modules
npm run build -- --modules="ZStackModule, BackdropModule" // Cherry-pick your modules
As output you will have your umd
and esm
builds in dist
folder.
Settings
Common configuration
Property | Type | Default | Description |
---|---|---|---|
horizontal | boolean |
false | Drag by horizontal axis will be possible on true and left right screen edge will automatically recognized as horizontal breakpoints |
horizontalOffset | number |
'null' | Margin left and right for screen edges used with horizontal gestures |
inverse | boolean |
false | On true will change pane direction from bottom-to-top to top-to-bottom |
parentElement | string |
Parent element selector | Element selector where pane will rendered |
followerElement | string |
Follower element selector | Element with selector will following pane transitions |
cssClass | string |
null | Additional classes to apply for wrapper to stylize different panes |
fitHeight | boolean |
'false' | Automatically calc and define content height as top breakpoint. Middle and bottom breakpoint will be disabled |
maxFitHeight | number |
'null' | Define a maximum possible automatically calculated height with fitHeight property |
fitScreenHeight | boolean |
'true' | On true will automatically adjust pane maximum height to screen height |
initialBreak | 'top' | 'middle' | 'bottom' |
'middle' | Initial pane position |
backdrop | boolean |
false | Dimmed overlay will rendered with pane if true |
backdropOpacity | number |
0.4 | Dimmed overlay opacity value |
animationType | string |
'ease' | Base transition timing function |
animationDuration | number |
300 | Transition property duration |
bottomClose | boolean |
false | Close pane with drag to bottom breakpoint |
fastSwipeClose | boolean |
false | Close pane with fast drag to bottom direction |
fastSwipeSensivity | number |
3 | Increase value and fast swipes become heavier |
freeMode | boolean |
false | On true will remove automatical magnetic effects to near breakpoint |
lowerThanBottom | boolean |
true | By default allow user to drag pane lower than bottom position. On false will automatically place pane to bottom position on lower than bottom attemption |
upperThanTop | boolean |
false | Allow user to drag pane upper than maximum top position. Useful with bulletin style without overflow-y |
touchAngle | number |
45 | Allowable angle (in degrees) to trigger drag gestures |
buttonDestroy | boolean |
true | Determinate whetever close button will render or not |
bottomOffset | number |
0 | Margin bottom for pane from screen bottom point |
topperOverflow | boolean |
true | Ability to scroll content inside pane if topper point reached |
topperOverflowOffset | number |
0 | Offset from screen bottom to the end of overflow content |
showDraggable | boolean |
true | Render rectangular shape on the top of pane |
draggableOver | boolean |
true | Render rectangular shape over a pane |
clickBottomOpen | boolean |
true | If bottom position reached, simple click to pane will open pane to the next upper point |
dragBy | string[] |
null | Array of selectors for whom elements drag events will be attached. By default drag events attached to pane element. If you are about to drag only with draggable component set option to ['.pane .draggable'] |
preventClicks | boolean |
true | Prevent accidental unwanted clicks events during move gestures |
handleKeyboard | boolean |
true | Pane will be pushed up on open keyboard (only for cordova/capacitor/phonegap applications) |
touchMoveStopPropagation | boolean |
false | If enabled, then propagation of "touchmove" will be stopped |
simulateTouch | boolean |
true | Simulate touch events for Desktop |
passiveListeners | boolean |
true | (Indicates that the function specified by listener will never call preventDefault()) |
Breakpoints
Package now supports 3 base breakpoints
const pane = new CupertinoPane('.cupertino-pane', {
breaks: {
top: { // Topper point that pane can reach
enabled: true, // Enable or disable breakpoint
height: 700, // Pane breakpoint height
bounce: true // Bounce pane on transition
},
middle: { ... },
bottom: { ... }
}
});
Bottom and middle heights normalized accross devices by default
Default top height: window.screen.height - (135 * 0.35)
Add property bounce
to break and enjoy transitions in apple stocks style with cubic-bezier(0.175, 0.885, 0.370, 1.120)
Z-Stack
Configuration for 3D push effects and z-stack
let settings = {
...
zStack: {
pushElements: ['.card-1', '.main-content'],
pushYOffset: 10
}
}
Property | Type | Default | Description |
---|---|---|---|
pushElements | string[] |
null | DOM Element will be pushed and scaled |
minPushHeight | number |
null | Height from which 3d push effect will be started |
cardYOffset | number |
null | Margin value to place pushed elements upper |
cardZScale | number |
0.93 | Scale value for each pushed element |
cardContrast | number |
0.85 | Contrast value for each pushed element |
stackZAngle | number |
160 | Value from 0 to 3000 that define angle of z-stack in common. 0 - 150 positive expontial angle. 150 - 170 = 45 degree angle. 200 - 3000 negative exponential angle |
Events
The function that executes when the event fires. Events can be assigned in two ways:
- Using
events
parameter on initialization:
let settings = {
...
events: {
onWillPresent: (ev) => {
console.log('Will present callback', ev);
}
}
}
- Using on method after initialization.
const pane = new CupertinoPane('.cupertino-pane', { /* ... */ });
pane.on('onBackdropTap', (ev) => {
console.log('Backdrop tapped', ev);
});
Name | Type | Description |
---|---|---|
onDidDismiss | void: () => {} |
Call after pane will dissapeared |
onWillDismiss | void: () => {} |
Call before pane will dissapeared |
onDidPresent | void: () => {} |
Call after pane will present |
onWillPresent | void: () => {} |
Call before panel will present |
onDragStart | void: () => {} |
Call when detect user drag event on pane |
onDrag | void: () => {} |
Call executes on each new position of pane |
onDragEnd | void: () => {} |
Executes when drag event complete |
onBackdropTap | void: () => {} |
Call when user tap backdrop overlay |
onTransitionStart | void: () => {} |
Executes before auto transition and animation start |
onTransitionEnd | void: () => {} |
Executes when transition and animation complete |
Public Methods
present({animate: boolean = false}): Promise
Will render pane DOM and show pane with setted params.
myPane.present();
on({events: string, handler: Function}): Promise
Will assign a function to be executed when the event will be fired.
myPane.on('onDidPresent', () => console.log('Presented!'));
moveToBreak('top' | 'middle' | 'bottom')
Will change pane position with animation to selected breakpoint.
myPane.moveToBreak('top');
moveToHeight(val: number)
Will move pane to exact height with animation. Breakpoints will saved.
myPane.moveToHeight(575);
hide()
Dissappear pane from screen, still keep pane in DOM.
myPane.hide();
destroy({animate: boolean = false}): Promise
Remove pane from DOM and clear styles
myPane.destroy();
isHidden()
Determinate if pane position was moved out of screen, but pane still exist in DOM. true - in DOM but not visible, false - in DOM and visible, null - not rendered
if (myPane.isHidden()) {
myPane.moveToBreak('top');
}
currentBreak()
Method return current break position in text format ('top' | 'middle' | 'bottom)
if (myPane.currentBreak() === 'top') {
myPane.moveToBreak('bottom');
}
disableDrag()
Method disable any drag actions for pane
myPane.disableDrag();
enableDrag()
Method enable any drag actions for pane
myPane.enableDrag();
backdrop({show: boolean = true})
Show/Hide backdrop method
myPane.backdrop({show: true}); // show
myPane.backdrop({show: false}); // hide
setBreakpoints(breakpoints: PaneBreaks)
Method updates breakpoints configuration for rendered Pane
myPane.setBreakpoints({
top: {
enabled: true,
height: 700,
bounce: true
},
middle: { ... },
bottom: { ... }
});
preventDismiss(boolean = false)
Use this method to prevent dismiss events. Use onWillDismiss()
callback to listen if dismiss event prevented.
const settings = {
...
events: {
onWillDismiss: (e) => {
if (e) {
console.log(e.prevented);
}
}
}
}
const myPane = new CupertinoPane('.cupertino-pane', settings);
myPane.present({animate: true});
myPane.preventDismiss(true);
calcFitHeight()
Force re-calculate height for fitHeight: true
in cases when height was calculated not properly.
myPane.calcFitHeight();
Attributes
hide-on-bottom
Set for element to automaticaly hide on reach bottom breakpoint.
<div class="cupertino-pane">
<h1>Header</h1>
<div class="content" hide-on-bottom>Content</div>
</div>
overflow-y
Set for element with overflow ability. By default using for full pane area, but in some cases good useful with header.
<div class="cupertino-pane">
<h1>Header</h1>
<div class="content" overflow-y>Content</div>
</div>
CSS Variables
Variable | Default |
---|---|
--cupertino-pane-background | #ffffff |
--cupertino-pane-color | #333333 |
--cupertino-pane-shadow | #0 4px 16px rgba(0,0,0,.12) |
--cupertino-pane-border-radius | #20px |
--cupertino-pane-move-background | #c0c0c0 |
--cupertino-pane-destroy-button-background | #ebebeb |
--cupertino-pane-icon-close-color | #7a7a7e |
Keyboard issues
By default, we are now handle keyboard in all type of applications.
If you would like handle this part by yourself, set option handleKeyboard: false
.
- Safari WebKit (browser) will handle inputs and keyboard automatically.
- Chrome WebView (browser) are handled in our end with resize events.
- Cordova WkWebView/WebView are handled in our end with keyboard events.
Future Goals
Project under regularly maintanance and bug fixes. All new features and new investigations moved to open collective Goals
Contributors
We are welcome contributions of all kinds from anyone. Please review the contributing guideline.
Commit Message Format angular commit format
License
Licensed under the MIT License. View license.