From fd8a6ecc727ed2eb0adcf5de6c59d454d822f33d Mon Sep 17 00:00:00 2001 From: nklhrstv Date: Thu, 13 Feb 2020 17:57:37 +0200 Subject: [PATCH 1/7] export isRequired for selectable inputs --- src/routes/Discover/useSelectableInputs.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/routes/Discover/useSelectableInputs.js b/src/routes/Discover/useSelectableInputs.js index 576109fde..bcb6e6aac 100644 --- a/src/routes/Discover/useSelectableInputs.js +++ b/src/routes/Discover/useSelectableInputs.js @@ -110,6 +110,7 @@ const mapSelectableInputs = (discover) => { }; const extraSelects = discover.selectable.extra.map((extra) => { const title = `Select ${extra.name}`; + const isRequired = extra.isRequired; const options = (extra.isRequired ? [] : [NONE_EXTRA_VALUE]) .concat(extra.options) .map((option) => ({ @@ -141,7 +142,7 @@ const mapSelectableInputs = (discover) => { } }); }; - return { title, options, selected, renderLabelText, onSelect }; + return { title, isRequired, options, selected, renderLabelText, onSelect }; }); const paginationInput = discover.selectable.has_prev_page || discover.selectable.has_next_page ? { From 547065b927a8a605b9c9ca2cc1cc0a8394f42110 Mon Sep 17 00:00:00 2001 From: nklhrstv Date: Thu, 13 Feb 2020 18:13:11 +0200 Subject: [PATCH 2/7] extended inputs layout implemented in discover --- src/common/Multiselect/Multiselect.js | 133 +++++++++++++++----------- src/common/Multiselect/styles.less | 92 +++++++++--------- src/routes/Discover/Discover.js | 16 +++- src/routes/Discover/styles.less | 35 +++++++ 4 files changed, 174 insertions(+), 102 deletions(-) diff --git a/src/common/Multiselect/Multiselect.js b/src/common/Multiselect/Multiselect.js index 0ac42c2d1..25b9c95fb 100644 --- a/src/common/Multiselect/Multiselect.js +++ b/src/common/Multiselect/Multiselect.js @@ -4,10 +4,11 @@ const classnames = require('classnames'); const Icon = require('stremio-icons/dom'); const Button = require('stremio/common/Button'); const Popup = require('stremio/common/Popup'); +const ModalDialog = require('stremio/common/ModalDialog'); const useBinaryState = require('stremio/common/useBinaryState'); const styles = require('./styles'); -const Multiselect = ({ className, direction, title, disabled, dataset, renderLabelContent, renderLabelText, onOpen, onClose, onSelect, ...props }) => { +const Multiselect = ({ className, mode, direction, title, disabled, dataset, renderLabelContent, renderLabelText, onOpen, onClose, onSelect, ...props }) => { const [menuOpen, , closeMenu, toggleMenu] = useBinaryState(false); const options = React.useMemo(() => { return Array.isArray(props.options) ? @@ -25,19 +26,19 @@ const Multiselect = ({ className, direction, title, disabled, dataset, renderLab : []; }, [props.selected]); - const popupLabelOnClick = React.useCallback((event) => { + const labelOnClick = React.useCallback((event) => { if (typeof props.onClick === 'function') { props.onClick(event); } - if (!event.nativeEvent.togglePopupPrevented) { + if (!event.nativeEvent.toggleMenuPrevented) { toggleMenu(); } }, [props.onClick, toggleMenu]); - const popupMenuOnClick = React.useCallback((event) => { - event.nativeEvent.togglePopupPrevented = true; + const menuOnClick = React.useCallback((event) => { + event.nativeEvent.toggleMenuPrevented = true; }, []); - const popupMenuOnKeyDown = React.useCallback((event) => { + const menuOnKeyDown = React.useCallback((event) => { event.nativeEvent.buttonClickPrevented = true; }, []); const optionOnClick = React.useCallback((event) => { @@ -77,64 +78,84 @@ const Multiselect = ({ className, direction, title, disabled, dataset, renderLab mountedRef.current = true; }, [menuOpen]); - return ( + const renderLabel = React.useMemo(() => ({ children, className, ...props }) => ( + + ), [menuOpen, title, disabled, options, selected, labelOnClick, renderLabelContent, renderLabelText]); + const renderMenu = React.useMemo(() => () => ( +
+ { + options.length > 0 ? + options.map(({ label, value }) => ( + + )) + : +
+
No options available
+
+ } +
+ ), [options, selected, menuOnKeyDown, menuOnClick, optionOnClick]); + const renderPopupLabel = React.useMemo(() => (labelProps) => { + return renderLabel({ + ...labelProps, + ...props, + className: classnames(className, labelProps.className) + }); + }, [props, className, renderLabel]); + return mode === 'modal' ? + renderLabel({ + ...props, + className, + children: menuOpen ? + + {renderMenu()} + + : + null + }) + : ( - - )} - renderMenu={() => ( -
- { - options.length > 0 ? - options.map(({ label, value }) => ( - - )) - : -
-
No options available
-
- } -
- )} - /> - ); + renderLabel={renderPopupLabel} + renderMenu={renderMenu} + />; }; Multiselect.propTypes = { className: PropTypes.string, + mode: PropTypes.oneOf(['popup', 'modal']), direction: PropTypes.any, title: PropTypes.string, options: PropTypes.arrayOf(PropTypes.shape({ diff --git a/src/common/Multiselect/styles.less b/src/common/Multiselect/styles.less index 090d39bb1..bb1589483 100644 --- a/src/common/Multiselect/styles.less +++ b/src/common/Multiselect/styles.less @@ -37,59 +37,61 @@ .popup-menu-container { width: 100%; + } +} - .menu-container { - .option-container { - display: flex; - flex-direction: row; - align-items: center; - padding: 1rem; - background-color: var(--color-backgroundlighter); +.modal-container, .popup-menu-container { + .menu-container { + .option-container { + display: flex; + flex-direction: row; + align-items: center; + padding: 1rem; + background-color: var(--color-backgroundlighter); - &:global(.selected) { - background-color: var(--color-surfacedarker); - - .icon { - display: block; - } - } - - &:hover, &:focus { - background-color: var(--color-surfacedark); - } - - .label { - flex: 1; - max-height: 4.8em; - color: var(--color-surfacelighter); - } + &:global(.selected) { + background-color: var(--color-surfacedarker); .icon { - flex: none; - display: none; - width: 1rem; - height: 1rem; - margin-left: 1rem; - fill: var(--color-surfacelighter); + display: block; } } - .no-options-container { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - padding: 1rem; - background-color: var(--color-backgroundlighter); + &:hover, &:focus { + background-color: var(--color-surfacedark); + } - .label { - flex-grow: 0; - flex-shrink: 1; - flex-basis: auto; - font-size: 1.2rem; - text-align: center; - color: var(--color-surfacelighter); - } + .label { + flex: 1; + max-height: 4.8em; + color: var(--color-surfacelighter); + } + + .icon { + flex: none; + display: none; + width: 1rem; + height: 1rem; + margin-left: 1rem; + fill: var(--color-surfacelighter); + } + } + + .no-options-container { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + padding: 1rem; + background-color: var(--color-backgroundlighter); + + .label { + flex-grow: 0; + flex-shrink: 1; + flex-basis: auto; + font-size: 1.2rem; + text-align: center; + color: var(--color-surfacelighter); } } } diff --git a/src/routes/Discover/Discover.js b/src/routes/Discover/Discover.js index 78116cd7e..3c7f32f8f 100644 --- a/src/routes/Discover/Discover.js +++ b/src/routes/Discover/Discover.js @@ -143,7 +143,21 @@ const Discover = ({ urlParams, queryParams }) => { { inputsModalOpen ? - + + {selectInputs.slice(2).map((selectInput, index) => ( +
+
+ {selectInput.title} + {selectInput.isRequired ? '*' : null} +
+ +
+ ))} +
: null } diff --git a/src/routes/Discover/styles.less b/src/routes/Discover/styles.less index 8e20dd3c9..a1b16bf87 100644 --- a/src/routes/Discover/styles.less +++ b/src/routes/Discover/styles.less @@ -2,6 +2,7 @@ :import('~stremio/common/Multiselect/styles.less') { multiselect-menu-container: menu-container; + multiselect-modal-container: modal-container; } :import('~stremio/common/PaginationInput/styles.less') { @@ -172,6 +173,40 @@ } } +.selectable-inputs-modal-container { + .selectable-inputs-container { + display: flex; + flex-direction: row; + align-items: center; + + &:not(:last-child) { + margin-bottom: 1rem; + } + + .select-input-label-container { + flex: none; + width: 10rem; + max-height: 2.4em; + padding-right: 0.5rem; + color: var(--color-backgrounddarker); + } + + .select-input-container { + flex: none; + width: 15rem; + height: 3rem; + } + } +} + +.multiselect-modal-container { + .multiselect-menu-container { + width: 15rem; + max-height: calc(3.2rem * 7); + overflow-y: auto; + } +} + @media only screen and (min-width: @xxlarge) { .discover-container { .discover-content { From 11b69be4208f26311efd1adab5df739da6059f3d Mon Sep 17 00:00:00 2001 From: nklhrstv Date: Thu, 13 Feb 2020 18:21:03 +0200 Subject: [PATCH 3/7] prevent spreading unnesesary props on multiselects in discover --- src/routes/Discover/Discover.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/routes/Discover/Discover.js b/src/routes/Discover/Discover.js index 3c7f32f8f..b3602b72c 100644 --- a/src/routes/Discover/Discover.js +++ b/src/routes/Discover/Discover.js @@ -52,11 +52,15 @@ const Discover = ({ urlParams, queryParams }) => {
- {selectInputs.map((selectInput, index) => ( + {selectInputs.map(({ title, options, selected, renderLabelText, onSelect }, index) => ( ))}