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:
Egor Savkin 2024-10-31 16:01:55 +08:00
parent c9ddc2513b
commit bf17a24704
3 changed files with 99 additions and 101 deletions

View File

@ -485,6 +485,12 @@ button {
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;
flex-direction: column; flex-direction: column;
@ -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;
}
}

View File

@ -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

View File

@ -1,24 +1,20 @@
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"
@ -26,12 +22,25 @@ export function DialogPopup({options, data, target, id, big, first, last, option
show={displayNotification} show={displayNotification}
onHide={onHideNotification} onHide={onHideNotification}
content={ content={
<img className="alert-info" <img className="alert-info" ref={ref}
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}/>
} }
/> />
<div style={{'display': show ? 'flex' : 'none'}} className={div_classes}> <Overlay target={ref.current}
show={show}
placement={horizontal ? "right" : "bottom"}
onHide={() => setShow(false)}
rootClose={true}>
{({
placement: _placement,
arrowProps: _arrowProps,
show: _show,
popper: _popper,
hasDoneInitialMeasure: _hasDoneInitialMeasure,
...props
}) => (
<div style={{'display': show ? 'flex' : 'none', ...props.style}} {...props} className={div_classes}>
<ProcessOptions <ProcessOptions
options={options} options={options}
data={data} data={data}
@ -40,7 +49,8 @@ export function DialogPopup({options, data, target, id, big, first, last, option
target={target} target={target}
/> />
</div> </div>
</div> )}
); </Overlay>
</>);
} }