feat(mobile): Adapts design for mobile/tablet
This commit is contained in:
parent
66cd581a47
commit
a4c77f3872
199
static/css/order-hardware.css
Normal file
199
static/css/order-hardware.css
Normal file
@ -0,0 +1,199 @@
|
||||
.mobileCloseMenu {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 1em 1em 0;
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Tablets, Ipads (portrait)
|
||||
##Screen = B/w 768px to 1024px
|
||||
*/
|
||||
@media (min-width: 768px) and (max-width: 1024px) {
|
||||
body {
|
||||
font-size: .8rem;
|
||||
}
|
||||
|
||||
#root-shop .productItem {
|
||||
padding: 2rem 1rem 1rem;
|
||||
}
|
||||
|
||||
#root-shop .productItem .content img {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
#root-shop .productItem .content .price {
|
||||
padding: .5rem;
|
||||
}
|
||||
|
||||
#root-shop .productItem .content h3 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
#root-shop .productItem .content ul {
|
||||
font-size: .6rem;
|
||||
}
|
||||
|
||||
#root-shop .panel .control {
|
||||
flex-direction: column;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
#root-shop .panel .control > .description,
|
||||
#root-shop .panel .control > .crate-mode {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#root-shop .panel .control > .crate-mode {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#root-shop .panel .summary {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#root-shop .panel .summary>.summary-price table {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
#root-shop .panel .summary>.summary-form form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#root-shop .panel {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
#root-shop .mobileBtnDisplaySideMenu,
|
||||
#root-shop .mobileCloseMenu {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
/*
|
||||
##Device = Tablets, Ipads (landscape)
|
||||
##Screen = B/w 768px to 1024px
|
||||
*/
|
||||
@media (min-width: 768px) and (max-width: 1024px) and (orientation: landscape) {
|
||||
|
||||
}
|
||||
/*
|
||||
##Device = Low Resolution Tablets, Mobiles (Landscape)
|
||||
##Screen = B/w 481px to 767px
|
||||
*/
|
||||
@media (min-width: 481px) and (max-width: 767px) {
|
||||
|
||||
}
|
||||
/*
|
||||
##Device = Most of the Smartphones Mobiles (Portrait)
|
||||
##Screen = B/w 320px to 479px
|
||||
*/
|
||||
@media (min-width: 320px) and (max-width: 480px) {
|
||||
#root-shop .layout>aside.aside.menu-opened {
|
||||
transform: translate3d(0, 0, 0);
|
||||
transition: transform .3s;
|
||||
width: 310px;
|
||||
}
|
||||
|
||||
#root-shop .layout>aside.aside.menu-opened + section.main {
|
||||
transform: translate3d(310px, 0, 0);
|
||||
transition: transform .3s;
|
||||
}
|
||||
|
||||
#root-shop .layout>aside.aside.menu-opened + section.main:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: rgba(0, 0, 0, .8);
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#root-shop .layout>aside.aside {
|
||||
transform: translate3d(-310px, 0px, 0px);
|
||||
transition: transform .3s;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
width: 310px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#root-shop .layout>aside.aside:after {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
#root-shop .layout>aside.aside + section.main {
|
||||
transform: translate3d(0, 0, 0);
|
||||
transition: transform .3s;
|
||||
}
|
||||
|
||||
#root-shop .layout>section.main {
|
||||
flex: 1;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#root-shop .productItem {
|
||||
padding: 2rem 1rem 1rem;
|
||||
}
|
||||
|
||||
#root-shop .productItem .content img {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
#root-shop .productItem .content .price {
|
||||
padding: .5rem;
|
||||
}
|
||||
|
||||
#root-shop .panel {
|
||||
padding: 1.3rem;
|
||||
}
|
||||
|
||||
#root-shop .panel .control {
|
||||
flex-direction: column;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
#root-shop .panel .control > .description,
|
||||
#root-shop .panel .control > .crate-mode {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#root-shop .panel .control > .crate-mode {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#root-shop .panel .summary {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#root-shop .panel .summary>.summary-price table {
|
||||
font-size: .7rem;
|
||||
}
|
||||
|
||||
#root-shop .panel .summary>.summary-form form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#root-shop .panel .summary>.summary-price tfoot {
|
||||
font-size: .85rem;
|
||||
}
|
||||
|
||||
#root-shop .panel .summary>.summary-form form input[type="submit"] {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#root-shop .mobileBtnDisplaySideMenu {
|
||||
background-color: #0d3547;
|
||||
border-bottom-right-radius: 30px;
|
||||
border-top-right-radius: 30px;
|
||||
width: 80px;
|
||||
padding: 5px 0 5px 10px;
|
||||
margin-bottom: 15px;
|
||||
margin-left: -1.3rem;
|
||||
}
|
||||
|
||||
#root-shop table tfoot > tr {
|
||||
display: flex !important;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
7
static/images/shop/icon-close-white.svg
Normal file
7
static/images/shop/icon-close-white.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22">
|
||||
<g id="Group_441" data-name="Group 441" transform="translate(-1251 -346)">
|
||||
<rect id="Rectangle_1020" data-name="Rectangle 1020" width="22" height="22" transform="translate(1251 346)" fill="none"/>
|
||||
<rect id="Rectangle_1021" data-name="Rectangle 1021" width="2.4" height="24" transform="translate(1269.778 347.808) rotate(45)" fill="#fff"/>
|
||||
<rect id="Rectangle_1022" data-name="Rectangle 1022" width="2.4" height="24" transform="translate(1271.192 364.778) rotate(135)" fill="#fff"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 594 B |
@ -136,6 +136,14 @@ class Layout extends React.PureComponent {
|
||||
return {
|
||||
aside: PropTypes.any,
|
||||
main: PropTypes.any,
|
||||
mobileSideMenuShouldOpen: PropTypes.bool,
|
||||
onClickToggleMobileSideMenu: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
static get defaultProps() {
|
||||
return {
|
||||
mobileSideMenuShouldOpen: false,
|
||||
};
|
||||
}
|
||||
|
||||
@ -143,14 +151,20 @@ class Layout extends React.PureComponent {
|
||||
const {
|
||||
aside,
|
||||
main,
|
||||
mobileSideMenuShouldOpen,
|
||||
onClickToggleMobileSideMenu
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div className="layout">
|
||||
|
||||
<aside className="aside">{aside}</aside>
|
||||
<aside className={'aside ' + (mobileSideMenuShouldOpen ? 'menu-opened' : '')}>{aside}</aside>
|
||||
|
||||
{mobileSideMenuShouldOpen ? (
|
||||
<section className="main" onClick={onClickToggleMobileSideMenu}>{main}</section>
|
||||
) : (
|
||||
<section className="main">{main}</section>
|
||||
)}
|
||||
|
||||
</div>
|
||||
);
|
||||
@ -722,6 +736,8 @@ class OrderPanel extends React.PureComponent {
|
||||
crate: PropTypes.element,
|
||||
summaryPrice: PropTypes.element,
|
||||
form: PropTypes.element,
|
||||
isMobile: PropTypes.bool,
|
||||
onClickToggleMobileSideMenu: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
@ -733,11 +749,21 @@ class OrderPanel extends React.PureComponent {
|
||||
crate,
|
||||
summaryPrice,
|
||||
form,
|
||||
isMobile,
|
||||
onClickToggleMobileSideMenu
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<section className="panel">
|
||||
|
||||
{isMobile ? (
|
||||
<div className="mobileBtnDisplaySideMenu">
|
||||
<button onClick={onClickToggleMobileSideMenu}>
|
||||
<img src="/images/shop/icon-add.svg" alt="add" />
|
||||
</button>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<h2>{title}</h2>
|
||||
|
||||
<div className="control">
|
||||
@ -1026,7 +1052,9 @@ class Backlog extends React.PureComponent {
|
||||
currency: PropTypes.string,
|
||||
data: PropTypes.object.isRequired,
|
||||
items: PropTypes.object,
|
||||
isMobile: PropTypes.bool,
|
||||
onClickAddItem: PropTypes.func,
|
||||
onClickToggleMobileSideMenu: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1042,6 +1070,8 @@ class Backlog extends React.PureComponent {
|
||||
data,
|
||||
items,
|
||||
onClickAddItem,
|
||||
onClickToggleMobileSideMenu,
|
||||
isMobile,
|
||||
} = this.props;
|
||||
|
||||
const ordered_items = data.itemIds.map(itemId => items[itemId]);
|
||||
@ -1072,6 +1102,14 @@ class Backlog extends React.PureComponent {
|
||||
ref={provided.innerRef}
|
||||
{...provided.droppableProps}>
|
||||
|
||||
{isMobile ? (
|
||||
<div className="mobileCloseMenu">
|
||||
<button onClick={onClickToggleMobileSideMenu}>
|
||||
<img src="/images/shop/icon-close-white.svg" alt="add" />
|
||||
</button>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{products}
|
||||
|
||||
{provided.placeholder && (
|
||||
@ -1115,6 +1153,7 @@ class Shop extends React.PureComponent {
|
||||
this.handleClickSelectItem = this.handleClickSelectItem.bind(this);
|
||||
this.handleClickSubmit = this.handleClickSubmit.bind(this);
|
||||
this.handleToggleOverlayRemove = this.handleToggleOverlayRemove.bind(this);
|
||||
this.handleClickToggleMobileSideMenu = this.handleClickToggleMobileSideMenu.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@ -1401,6 +1440,13 @@ class Shop extends React.PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
handleClickToggleMobileSideMenu() {
|
||||
this.setState({
|
||||
...this.state,
|
||||
mobileSideMenuShouldOpen: !this.state.mobileSideMenuShouldOpen,
|
||||
});
|
||||
}
|
||||
|
||||
checkAlerts(prevItems, newItems) {
|
||||
console.log('--- START CHECKING CRATE WARNING ---');
|
||||
|
||||
@ -1684,6 +1730,7 @@ class Shop extends React.PureComponent {
|
||||
items,
|
||||
columns,
|
||||
rules,
|
||||
mobileSideMenuShouldOpen,
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
@ -1691,16 +1738,22 @@ class Shop extends React.PureComponent {
|
||||
|
||||
<Layout
|
||||
className="shop"
|
||||
mobileSideMenuShouldOpen={mobileSideMenuShouldOpen}
|
||||
onClickToggleMobileSideMenu={this.handleClickToggleMobileSideMenu}
|
||||
aside={
|
||||
<Backlog
|
||||
currency={currency}
|
||||
items={items}
|
||||
data={columns['backlog']}
|
||||
onClickAddItem={this.handleClickAddItem}>
|
||||
onClickAddItem={this.handleClickAddItem}
|
||||
onClickToggleMobileSideMenu={this.handleClickToggleMobileSideMenu}
|
||||
isMobile={window.deviceIsMobile()}>
|
||||
</Backlog>
|
||||
}
|
||||
main={(
|
||||
<OrderPanel
|
||||
onClickToggleMobileSideMenu={this.handleClickToggleMobileSideMenu}
|
||||
isMobile={window.deviceIsMobile()}
|
||||
title="Order hardware"
|
||||
description="
|
||||
Drag and drop the cards you want into the crate below to see how the combination would look like. If you have any issues with this ordering system, or if you need other configurations, email us directly anytime at sales@m-****.hk. The price is estimated and must be confirmed by a quote."
|
||||
|
@ -1,5 +1,6 @@
|
||||
const shop_data = {
|
||||
|
||||
mobileSideMenuShouldOpen: false,
|
||||
currentItemHovered: null,
|
||||
currentMode: 'rack',
|
||||
currency: 'USD',
|
||||
|
@ -1,6 +1,12 @@
|
||||
{% extends 'section.html' %}
|
||||
|
||||
|
||||
{% block deferred_styles %}
|
||||
{{ super() }}
|
||||
<link rel="stylesheet" href="{{ get_url(path='css/order-hardware.css', cachebust=true) }}">
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block hero %}{% endblock %}
|
||||
|
||||
|
||||
@ -24,6 +30,9 @@
|
||||
return (typeof window.orientation !== 'undefined') || (navigator.userAgent.indexOf('IEMobile') !== -1);
|
||||
};
|
||||
|
||||
window.deviceIsMobile = deviceIsMobile;
|
||||
|
||||
return;
|
||||
if (deviceIsMobile()) {
|
||||
alert('The online crate configuration tool is not available for mobile browsers yet. Please use a desktop computer or email us at sales@m-l****.hk to get a quote.');
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user