forked from M-Labs/web2019
Make dialog popup rendered by bootstrap overlay library
This makes it more dynamic and eases proper placement in case of vertical layout Signed-off-by: Egor Savkin <es@m-labs.hk>
This commit is contained in:
parent
34a86e24c5
commit
66bb5b25d8
|
@ -484,6 +484,12 @@ button {
|
||||||
background-color: #ebebeb;
|
background-color: #ebebeb;
|
||||||
padding: 5px 5px 12px;
|
padding: 5px 5px 12px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
&.horizontal {
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 50px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -571,67 +577,6 @@ button {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlayVariant {
|
|
||||||
top: 24px;
|
|
||||||
width: 140px;
|
|
||||||
min-height: 40px;
|
|
||||||
max-height: 320px;
|
|
||||||
overflow-y: scroll;
|
|
||||||
position: absolute;
|
|
||||||
display: flex;
|
|
||||||
align-items: start;
|
|
||||||
text-align: left;
|
|
||||||
background-color: white;
|
|
||||||
color: black;
|
|
||||||
flex-direction: column;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 0.2rem 0;
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: .65rem;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
div {
|
|
||||||
margin: 0.1rem 0.2rem;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
|
|
||||||
input {
|
|
||||||
padding: 0;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
margin-bottom: 0.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.options-icon {
|
|
||||||
display: inline;
|
|
||||||
height: .875rem;
|
|
||||||
margin-right: 0.2rem;
|
|
||||||
margin-left: 0.2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-check {
|
|
||||||
min-height: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.overlay-smallcard {
|
|
||||||
left: -38.5px; // (card width (63) - overlay width (140)) / 2
|
|
||||||
|
|
||||||
&.overlay-first {
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
&.overlay-last {
|
|
||||||
left: -67px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.overlay-bigcard {
|
|
||||||
left: -7px; // (card width (126) - overlay width (140)) / 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hovered {
|
.hovered {
|
||||||
|
@ -778,3 +723,49 @@ button {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overlayVariant {
|
||||||
|
width: 140px;
|
||||||
|
min-height: 40px;
|
||||||
|
max-height: 320px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
align-items: start;
|
||||||
|
text-align: left;
|
||||||
|
background-color: white;
|
||||||
|
color: black;
|
||||||
|
flex-direction: column;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0.2rem 0;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: .65rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
margin: 0.1rem 0.2rem;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding: 0;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
margin-bottom: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.options-icon {
|
||||||
|
display: inline;
|
||||||
|
height: .875rem;
|
||||||
|
margin-right: 0.2rem;
|
||||||
|
margin-left: 0.2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-check {
|
||||||
|
min-height: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,12 +3,11 @@ import React from "react";
|
||||||
import {useShopStore} from "./shop_store";
|
import {useShopStore} from "./shop_store";
|
||||||
import {SummaryPopup} from "./options/SummaryPopup";
|
import {SummaryPopup} from "./options/SummaryPopup";
|
||||||
|
|
||||||
export function OptionsDialogWrapper({crate_index, card_index, first, last}) {
|
export function OptionsDialogWrapper({crate_index, card_index, horizontal}) {
|
||||||
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
||||||
const use_options = useShopStore((state) => state.crateParams(state.crates[crate_index].crate_mode).options);
|
const use_options = useShopStore((state) => state.crateParams(state.crates[crate_index].crate_mode).options);
|
||||||
const options = useShopStore((state) => state.crates[crate_index].items[card_index][use_options]);
|
const options = useShopStore((state) => state.crates[crate_index].items[card_index][use_options]);
|
||||||
const options_data = useShopStore((state) => state.crates[crate_index].items[card_index].options_data);
|
const options_data = useShopStore((state) => state.crates[crate_index].items[card_index].options_data);
|
||||||
const card_size = useShopStore((state) => state.crates[crate_index].items[card_index].size);
|
|
||||||
const card_id = useShopStore((state) => state.crates[crate_index].items[card_index].id);
|
const card_id = useShopStore((state) => state.crates[crate_index].items[card_index].id);
|
||||||
const options_class = useShopStore((state) => state.crates[crate_index].items[card_index].options_class);
|
const options_class = useShopStore((state) => state.crates[crate_index].items[card_index].options_class);
|
||||||
const sideMenuIsOpen = useShopStore((state) => state.sideMenuIsOpen);
|
const sideMenuIsOpen = useShopStore((state) => state.sideMenuIsOpen);
|
||||||
|
@ -27,12 +26,10 @@ export function OptionsDialogWrapper({crate_index, card_index, first, last}) {
|
||||||
options_class={options_class}
|
options_class={options_class}
|
||||||
key={"popover" + crate_id +card_id}
|
key={"popover" + crate_id +card_id}
|
||||||
id={"popover"+ crate_id + card_id}
|
id={"popover"+ crate_id + card_id}
|
||||||
big={card_size === "big"}
|
|
||||||
first={first}
|
|
||||||
last={last}
|
|
||||||
sideMenuIsOpen={sideMenuIsOpen}
|
sideMenuIsOpen={sideMenuIsOpen}
|
||||||
onHideNotification={hideNotification}
|
onHideNotification={hideNotification}
|
||||||
displayNotification={displayNotification}
|
displayNotification={displayNotification}
|
||||||
|
horizontal={horizontal}
|
||||||
target={{
|
target={{
|
||||||
construct: ((outvar, value) => {
|
construct: ((outvar, value) => {
|
||||||
// #!options_log
|
// #!options_log
|
||||||
|
|
|
@ -1,46 +1,56 @@
|
||||||
import React, {useState} from "react";
|
import React, {useRef, useState} from "react";
|
||||||
import {useClickAway} from "./useClickAway";
|
|
||||||
import {ProcessOptions} from "./Options";
|
import {ProcessOptions} from "./Options";
|
||||||
import {Notification} from "./Notification";
|
import {Notification} from "./Notification";
|
||||||
|
import {Overlay} from "react-bootstrap";
|
||||||
|
|
||||||
export function DialogPopup({options, data, target, id, big, first, last, options_class,
|
export function DialogPopup({options, data, target, id, options_class,
|
||||||
sideMenuIsOpen, displayNotification, onHideNotification}) {
|
sideMenuIsOpen, displayNotification, onHideNotification, horizontal}) {
|
||||||
const [show, setShow] = useState(false);
|
const [show, setShow] = useState(false);
|
||||||
const ref = useClickAway((e) => {
|
const ref = useRef(null);
|
||||||
if (e.type === "mousedown") // ignore touchstart
|
|
||||||
setShow(false)
|
let div_classes = `overlayVariant border rounded ${options_class || ""}`;
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let div_classes = `overlayVariant border rounded ${big ? "overlay-bigcard" : "overlay-smallcard"} ${(!big && first) ? "overlay-first" : ""} ${(!big && last && !first) ? "overlay-last" : ""} ${options_class || ""}`;
|
|
||||||
const handleClick = (_event) => {
|
const handleClick = (_event) => {
|
||||||
setShow(!show);
|
setShow(!show);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (<>
|
||||||
<div ref={ref}>
|
<Notification
|
||||||
<Notification
|
id={"processed_options_notification" + id}
|
||||||
id={"processed_options_notification" + id}
|
tip="Customization options available"
|
||||||
tip="Customization options available"
|
sideMenuIsOpen={sideMenuIsOpen}
|
||||||
sideMenuIsOpen={sideMenuIsOpen}
|
show={displayNotification}
|
||||||
show={displayNotification}
|
onHide={onHideNotification}
|
||||||
onHide={onHideNotification}
|
content={
|
||||||
content={
|
<img className="alert-info" ref={ref}
|
||||||
<img className="alert-info"
|
src={show ? "/images/shop/icon-close.svg" : "/images/shop/icon-customize.svg"}
|
||||||
src={show ? "/images/shop/icon-close.svg" : "/images/shop/icon-customize.svg"}
|
onClick={handleClick}/>
|
||||||
onClick={handleClick}/>
|
}
|
||||||
}
|
/>
|
||||||
/>
|
<Overlay target={ref.current}
|
||||||
<div style={{'display': show ? 'flex' : 'none'}} className={div_classes}>
|
show={show}
|
||||||
<ProcessOptions
|
placement={horizontal ? "right" : "bottom"}
|
||||||
options={options}
|
onHide={() => setShow(false)}
|
||||||
data={data}
|
rootClose={true}>
|
||||||
key={"processed_options_" + id}
|
{({
|
||||||
id={"processed_options_" + id}
|
placement: _placement,
|
||||||
target={target}
|
arrowProps: _arrowProps,
|
||||||
/>
|
show: _show,
|
||||||
</div>
|
popper: _popper,
|
||||||
</div>
|
hasDoneInitialMeasure: _hasDoneInitialMeasure,
|
||||||
);
|
...props
|
||||||
|
}) => (
|
||||||
|
<div style={{'display': show ? 'flex' : 'none', ...props.style}} {...props} className={div_classes}>
|
||||||
|
<ProcessOptions
|
||||||
|
options={options}
|
||||||
|
data={data}
|
||||||
|
key={"processed_options_" + id}
|
||||||
|
id={"processed_options_" + id}
|
||||||
|
target={target}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Overlay>
|
||||||
|
</>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue