From 16e1869c1d2bd63b1ec6193d78356dd8864f9b23 Mon Sep 17 00:00:00 2001 From: kate-deriv Date: Mon, 15 Jan 2024 15:22:40 +0300 Subject: [PATCH 01/29] feat: add dropdown to the contract description section --- .../src/components/dropdown/dropdown.scss | 3 +- .../src/components/dropdown/dropdown.tsx | 20 ++++++++++- .../src/components/dropdown/items.tsx | 22 ++++++++++-- .../themed-scrollbars/themed-scrollbars.tsx | 10 ++++++ .../ContractTypeInfo/contract-type-info.tsx | 35 ++++++++++++++----- .../ContractTypeMenu/contract-type-menu.tsx | 2 +- .../components/contract-type-info.scss | 23 ++++++++++++ 7 files changed, 101 insertions(+), 14 deletions(-) diff --git a/packages/components/src/components/dropdown/dropdown.scss b/packages/components/src/components/dropdown/dropdown.scss index 18056ea0dba8..c5727f9a327c 100644 --- a/packages/components/src/components/dropdown/dropdown.scss +++ b/packages/components/src/components/dropdown/dropdown.scss @@ -269,7 +269,8 @@ min-width: 15rem; width: 100%; - &:not(.cfd-personal-details-modal__form *):not(.trade-container__multiplier-dropdown):not(.dc-dropdown--left) { + &:not(.cfd-personal-details-modal__form *):not(.trade-container__multiplier-dropdown):not( + .dc-dropdown--left):not(.contract-type-info__dropdown) { margin-top: unset; } diff --git a/packages/components/src/components/dropdown/dropdown.tsx b/packages/components/src/components/dropdown/dropdown.tsx index 8a506f3785da..03722aeb8e1e 100644 --- a/packages/components/src/components/dropdown/dropdown.tsx +++ b/packages/components/src/components/dropdown/dropdown.tsx @@ -44,6 +44,8 @@ type TDropdown = { onClick?: () => void; placeholder?: string; suffix_icon?: string; + should_scroll_to_selected?: boolean; + should_autohide?: boolean; test_id?: string; value?: string | number; classNameIcon?: string; @@ -67,6 +69,8 @@ type TDropdownList = { parent_ref: React.RefObject; portal_id?: string; suffix_icon?: string; + should_scroll_to_selected?: boolean; + should_autohide?: boolean; value?: string | number; }; @@ -89,11 +93,15 @@ const DropdownList = React.forwardRef((props, lis parent_ref, portal_id, suffix_icon, + should_scroll_to_selected, + should_autohide, value, } = props; const [list_dimensions, setListDimensions] = React.useState([initial_offset, 0]); const [style, setStyle] = React.useState({}); + const [scroll_height, setScrollHeight] = React.useState(); + const is_portal = !!portal_id; React.useEffect(() => { @@ -188,7 +196,12 @@ const DropdownList = React.forwardRef((props, lis role='list' ref={list_ref} > - + {Array.isArray(list) ? ( ((props, lis is_align_text_left={is_align_text_left} value={value} nodes={nodes.current} + setScrollHeight={setScrollHeight} /> ) : ( Object.keys(list).map((key, idx) => ( @@ -261,6 +275,8 @@ const Dropdown = ({ onClick, placeholder, suffix_icon, + should_scroll_to_selected, + should_autohide, test_id, value, classNameIcon, @@ -503,6 +519,8 @@ const Dropdown = ({ portal_id={list_portal_id} ref={list_ref} suffix_icon={suffix_icon} + should_scroll_to_selected={should_scroll_to_selected} + should_autohide={should_autohide} value={value} /> diff --git a/packages/components/src/components/dropdown/items.tsx b/packages/components/src/components/dropdown/items.tsx index 8f89b22fa634..60f4391619fe 100644 --- a/packages/components/src/components/dropdown/items.tsx +++ b/packages/components/src/components/dropdown/items.tsx @@ -14,6 +14,7 @@ type TItem = { is_align_text_left?: boolean; nodes: Map | null; item: TListItem; + setScrollHeight?: (new_value: number) => void; }; type TItems = Omit & { @@ -30,10 +31,21 @@ const Items = ({ items, ...props }: TItems) => { ); }; -const Item = ({ onKeyPressed, value, item, handleSelect, nodes, has_symbol, is_align_text_left, className }: TItem) => { +const Item = ({ + onKeyPressed, + value, + item, + handleSelect, + nodes, + has_symbol, + is_align_text_left, + className, + setScrollHeight, +}: TItem) => { const item_ref = React.useRef(null); const symbol_type_class_name = item.text && typeof item.text === 'string' ? `symbols--${item.text.toLowerCase()}` : null; + const is_selected = value === item.value; React.useEffect(() => { const removeListeners = () => { @@ -51,11 +63,17 @@ const Item = ({ onKeyPressed, value, item, handleSelect, nodes, has_symbol, is_a return () => removeListeners(); }, [item, nodes, onKeyPressed]); + React.useEffect(() => { + if (setScrollHeight && item_ref.current && is_selected) { + setScrollHeight(item_ref.current.offsetTop - item_ref.current.scrollHeight); + } + }, [item_ref, setScrollHeight, is_selected]); + return (
; refSetter?: RefObject | null; style?: React.CSSProperties; + scroll_height?: number; + should_scroll_to_selected?: boolean; width?: string; testId?: string; }; @@ -32,10 +34,18 @@ const ThemedScrollbars = ({ onScroll, refSetter = null, style = {}, + scroll_height, + should_scroll_to_selected = false, width, }: React.PropsWithChildren) => { const [hoverRef, isHovered] = useHover(refSetter, false); + React.useEffect(() => { + if (should_scroll_to_selected && scroll_height) { + hoverRef?.current?.scrollTo(0, scroll_height); + } + }, [scroll_height, hoverRef, should_scroll_to_selected]); + if (is_bypassed) return children as JSX.Element; return ( diff --git a/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeInfo/contract-type-info.tsx b/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeInfo/contract-type-info.tsx index 6605aa2a8913..f2c48772b4f5 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeInfo/contract-type-info.tsx +++ b/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeInfo/contract-type-info.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Button, ThemedScrollbars, ButtonToggle } from '@deriv/components'; +import { Button, ThemedScrollbars, ButtonToggle, Dropdown } from '@deriv/components'; import { observer, useStore } from '@deriv/stores'; import { clickAndKeyEventHandler, TRADE_TYPES } from '@deriv/shared'; import { localize } from '@deriv/translations'; @@ -38,17 +38,20 @@ const Info = observer(({ handleSelect, item, list }: TInfo) => { }, } = useStore(); const [selected_tab, setSelectedTab] = React.useState(TABS.DESCRIPTION); + const [selected_contract_type, setSelectedContractType] = React.useState(item); const { RISE_FALL_EQUAL, TURBOS, VANILLA } = TRADE_TYPES; const contract_types: TContractType[] | undefined = getContractTypes(list, item)?.filter( (i: { value: TContractType['value'] }) => i.value !== RISE_FALL_EQUAL && i.value !== TURBOS.SHORT && i.value !== VANILLA.PUT ); - const has_toggle_buttons = /accumulator|turboslong|vanilla|multiplier/i.test(item.value); - const should_show_video = /accumulator|turboslong|vanilla/i.test(item.value); + const has_toggle_buttons = /accumulator|turboslong|vanilla|multiplier/i.test(selected_contract_type.value); + const should_show_video = /accumulator|turboslong|vanilla/i.test(selected_contract_type.value); const is_description_tab_selected = selected_tab === TABS.DESCRIPTION; const is_glossary_tab_selected = selected_tab === TABS.GLOSSARY; const width = is_mobile ? '328' : '528'; const scroll_bar_height = has_toggle_buttons ? '464px' : '560px'; + const button_name = contract_types?.find(item => item.value === selected_contract_type.value)?.text; + const onClickGlossary = (e?: React.MouseEvent | React.KeyboardEvent) => { clickAndKeyEventHandler(() => setSelectedTab(TABS.GLOSSARY), e); }; @@ -66,13 +69,13 @@ const Info = observer(({ handleSelect, item, list }: TInfo) => { Analytics.trackEvent('ce_trade_types_form', { action: 'info_switcher', info_switcher_mode: selected_tab, - trade_type_name: item?.text, + trade_type_name: selected_contract_type?.text, }); } }, [selected_tab]); const cards = contract_types?.map((type: TContractType) => { - if (type.value !== item.value) return null; + if (type.value !== selected_contract_type.value) return null; return (
{ > {is_description_tab_selected ? ( - + { return ( + ['list']} + name='contract_type_dropdown' + value={selected_contract_type.value} + should_autohide={false} + should_scroll_to_selected + onChange={e => setSelectedContractType(e.target)} + /> {has_toggle_buttons && (
{
+ } > {is_info_dialog_open ? ( Date: Mon, 15 Jan 2024 18:02:06 +0300 Subject: [PATCH 03/29] refactor: removed info icons from menu and moved high low under ups and downs --- packages/shared/src/utils/constants/contract.ts | 3 ++- .../Components/Form/ContractType/contract-type-item.tsx | 6 +----- .../Components/Form/ContractType/contract-type-list.tsx | 4 +--- .../Components/Form/ContractType/contract-type-widget.tsx | 1 - 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/shared/src/utils/constants/contract.ts b/packages/shared/src/utils/constants/contract.ts index d81c4eae2d5e..e4882906d32a 100644 --- a/packages/shared/src/utils/constants/contract.ts +++ b/packages/shared/src/utils/constants/contract.ts @@ -219,6 +219,7 @@ export const getContractCategoriesConfig = () => categories: [ TRADE_TYPES.RISE_FALL, TRADE_TYPES.RISE_FALL_EQUAL, + TRADE_TYPES.HIGH_LOW, TRADE_TYPES.RUN_HIGH_LOW, TRADE_TYPES.RESET, TRADE_TYPES.ASIAN, @@ -227,7 +228,7 @@ export const getContractCategoriesConfig = () => }, 'Highs & Lows': { name: localize('Highs & Lows'), - categories: [TRADE_TYPES.HIGH_LOW, TRADE_TYPES.TOUCH, TRADE_TYPES.TICK_HIGH_LOW], + categories: [TRADE_TYPES.TOUCH, TRADE_TYPES.TICK_HIGH_LOW], }, 'Ins & Outs': { name: localize('Ins & Outs'), categories: [TRADE_TYPES.END, TRADE_TYPES.STAY] }, 'Look Backs': { diff --git a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-item.tsx b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-item.tsx index b17a1fb06ee6..0af86b9a54d8 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-item.tsx +++ b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-item.tsx @@ -6,12 +6,11 @@ import { TContractType } from './types'; type TItem = { contract_types: TContractType[]; - handleInfoClick?: (clicked_item: TContractType) => void; handleSelect?: (clicked_item: TContractType, e: React.MouseEvent) => void; value?: string; }; -const Item = ({ contract_types, handleInfoClick, handleSelect, value }: TItem) => ( +const Item = ({ contract_types, handleSelect, value }: TItem) => ( {contract_types.map(type => (
{type.text} -
handleInfoClick?.(type)}> - -
))}
diff --git a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-list.tsx b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-list.tsx index cbb0f5bd0dec..c3b4c1fa86f6 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-list.tsx +++ b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-list.tsx @@ -7,7 +7,6 @@ import classNames from 'classnames'; import { TContractType, TContractCategory } from './types'; type TListProps = { - handleInfoClick?: (clicked_item: TContractType) => void; handleSelect?: ( clicked_item: TContractType, e: React.MouseEvent @@ -17,7 +16,7 @@ type TListProps = { value?: string; }; -const List = ({ handleInfoClick, handleSelect, list, should_show_info_banner, value }: TListProps) => ( +const List = ({ handleSelect, list, should_show_info_banner, value }: TListProps) => ( {list.map((contract_category, index) => { const contract_types = contract_category.contract_types?.filter(contract_type => { @@ -57,7 +56,6 @@ const List = ({ handleInfoClick, handleSelect, list, should_show_info_banner, va
diff --git a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx index 8c263bfbf0fb..4d053b888451 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx +++ b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx @@ -307,7 +307,6 @@ const ContractTypeWidget = observer( /> ) : ( Date: Tue, 16 Jan 2024 16:04:24 +0300 Subject: [PATCH 04/29] feat: add learn more functionality to trading page --- .../contract-type-info-header.tsx | 25 ++- .../ContractTypeMenu/contract-type-menu.tsx | 14 +- .../__tests__/contract-type-dialog.spec.tsx | 2 +- .../ContractType/contract-type-dialog.tsx | 19 +- .../ContractType/contract-type-widget.tsx | 164 ++++++++++-------- .../components/contract-type-info.scss | 13 +- .../components/contract-type-widget.scss | 14 ++ 7 files changed, 166 insertions(+), 85 deletions(-) diff --git a/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeInfo/contract-type-info-header.tsx b/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeInfo/contract-type-info-header.tsx index df1a59d4d8a0..1849287cc553 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeInfo/contract-type-info-header.tsx +++ b/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeInfo/contract-type-info-header.tsx @@ -3,18 +3,35 @@ import { Icon, Text } from '@deriv/components'; type THeader = { onClickGoBack?: () => void; + onClickCross?: () => void; + should_render_arrow?: boolean; + should_render_cross?: boolean; text_size?: string; title: string; }; -const Header = ({ onClickGoBack, text_size = 's', title }: THeader) => ( +const Header = ({ + onClickGoBack, + onClickCross, + should_render_arrow = true, + should_render_cross = false, + text_size = 's', + title, +}: THeader) => (
- - - + {should_render_arrow && ( + + + + )} {title} + {should_render_cross && ( + + + + )}
); diff --git a/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeMenu/contract-type-menu.tsx b/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeMenu/contract-type-menu.tsx index 9a2588a38812..6a1927088633 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeMenu/contract-type-menu.tsx +++ b/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeMenu/contract-type-menu.tsx @@ -21,8 +21,10 @@ type TDialog = { onCategoryClick?: (e: React.ComponentProps['selected']) => void; onChangeInput?: (e: string) => void; onSearchBlur?: React.FocusEventHandler; + onClose?: () => void; show_loading?: boolean; - learn_more_banner: React.ReactNode; + learn_more_banner?: React.ReactNode; + hide_back_button?: boolean; }; const Dialog = ({ @@ -36,9 +38,11 @@ const Dialog = ({ onCategoryClick, onChangeInput, onSearchBlur, + onClose, selected, show_loading, learn_more_banner, + hide_back_button, }: React.PropsWithChildren) => { const input_ref = React.useRef<(HTMLInputElement & HTMLTextAreaElement) | null>(null); const [input_value, setInputValue] = React.useState(''); @@ -123,7 +127,13 @@ const Dialog = ({ ) : (
-
+
{renderChildren()}
diff --git a/packages/trader/src/Modules/Trading/Components/Form/ContractType/__tests__/contract-type-dialog.spec.tsx b/packages/trader/src/Modules/Trading/Components/Form/ContractType/__tests__/contract-type-dialog.spec.tsx index 11c75e0e6789..bb2806024b9a 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/ContractType/__tests__/contract-type-dialog.spec.tsx +++ b/packages/trader/src/Modules/Trading/Components/Form/ContractType/__tests__/contract-type-dialog.spec.tsx @@ -13,8 +13,8 @@ const MockContractTypeDialog = () => ( ['onClose']; + onDescriptionClose: () => void; is_open: boolean; - learn_more_banner: React.ReactNode; + learn_more_banner?: React.ReactNode; + hide_back_button?: boolean; }; type TContractTypeDialogProps = Pick< @@ -36,13 +37,19 @@ const ContractTypeDialog = ({ onBackButtonClick, onCategoryClick, onChangeInput, - onClose, + onDescriptionClose, onSearchBlur, show_loading, learn_more_banner, + hide_back_button, }: React.PropsWithChildren) => { const current_mobile_title = is_info_dialog_open ? ( -
+
) : ( localize('Trade types') ); @@ -58,7 +65,7 @@ const ContractTypeDialog = ({ header_classname='contract-type-widget__header' wrapper_classname={is_info_dialog_open ? 'contracts-modal-info' : 'contracts-modal-list'} visible={is_open} - onClose={onClose} + onClose={onDescriptionClose} has_content_scroll={!is_info_dialog_open} learn_more_banner={is_info_dialog_open ? '' : learn_more_banner} > @@ -74,11 +81,13 @@ const ContractTypeDialog = ({ selected={selected} categories={categories} onSearchBlur={onSearchBlur} + onClose={onDescriptionClose} onBackButtonClick={onBackButtonClick} onChangeInput={onChangeInput} onCategoryClick={onCategoryClick} show_loading={show_loading} learn_more_banner={learn_more_banner} + hide_back_button={hide_back_button} > {children} diff --git a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx index 4d053b888451..0c4049cfbd2d 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx +++ b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx @@ -36,6 +36,7 @@ const ContractTypeWidget = observer( const wrapper_ref = React.useRef(null); const [is_dialog_open, setDialogVisibility] = React.useState(); const [is_info_dialog_open, setInfoDialogVisibility] = React.useState(false); + const [hide_back_button, setHideBackButton] = React.useState(false); const [selected_category, setSelectedCategory] = React.useState('All'); const [search_query, setSearchQuery] = React.useState(''); const [item, setItem] = React.useState(null); @@ -47,6 +48,7 @@ const ContractTypeWidget = observer( setDialogVisibility(false); setInfoDialogVisibility(false); setItem({ ...item, value }); + setHideBackButton(false); } }, [item, value, is_dialog_open, is_mobile] @@ -136,6 +138,7 @@ const ContractTypeWidget = observer( const onWidgetClick = () => { setDialogVisibility(!is_dialog_open); + setHideBackButton(false); setInfoDialogVisibility(false); setItem({ ...item, value }); }; @@ -147,6 +150,17 @@ const ContractTypeWidget = observer( const onChangeInput = (searchQueryItem: string) => setSearchQuery(searchQueryItem); + const handleLearnMore = () => { + handleVisibility(); + handleInfoClick(item || { value }); + setHideBackButton(true); + }; + + const onDescriptionClose = () => { + onWidgetClick(); + setHideBackButton(false); + }; + const list_with_category = () => { const ordered_list = list && getCategoriesSortedByKey(list); const ordered_unavailable_types_list = getCategoriesSortedByKey(unavailable_trade_types_list); @@ -246,75 +260,89 @@ const ContractTypeWidget = observer( const should_show_info_banner = !!selected_category_contracts()?.some(i => i.is_unavailable); return ( -
- - s.symbol === symbol)?.display_name }} - shouldUnescape - /> - } - /> - ) - } - learn_more_banner={ - - } + + + + +
- {is_info_dialog_open ? ( - - ) : ( - - )} - -
+ + s.symbol === symbol)?.display_name, + }} + shouldUnescape + /> + } + /> + ) + } + learn_more_banner={ + + } + > + {is_info_dialog_open ? ( + + ) : ( + + )} + +
+ ); } ); diff --git a/packages/trader/src/sass/app/_common/components/contract-type-info.scss b/packages/trader/src/sass/app/_common/components/contract-type-info.scss index bd8ffc2a6eb1..558b945a2e81 100644 --- a/packages/trader/src/sass/app/_common/components/contract-type-info.scss +++ b/packages/trader/src/sass/app/_common/components/contract-type-info.scss @@ -145,18 +145,21 @@ display: flex; align-items: center; width: 100%; - padding-left: 2.4rem; - - @include mobile { - padding-left: 2.4rem; - } + position: relative; } &__title { cursor: default; } &__icon { cursor: pointer; + padding-left: 2.4rem; padding-right: 2.4rem; + + &-cross { + position: absolute; + right: 0; + cursor: pointer; + } } &__scrollbars { position: relative; diff --git a/packages/trader/src/sass/app/_common/components/contract-type-widget.scss b/packages/trader/src/sass/app/_common/components/contract-type-widget.scss index 9faee38a45bd..6c13382ab921 100644 --- a/packages/trader/src/sass/app/_common/components/contract-type-widget.scss +++ b/packages/trader/src/sass/app/_common/components/contract-type-widget.scss @@ -8,6 +8,20 @@ background: var(--fill-normal); border: 1px solid var(--fill-normal); + &__learn-more { + margin-bottom: 0.8rem; + border: none; + border-bottom: 1px dotted var(--text-general); + padding: 0; + cursor: pointer; + + @include mobile { + position: absolute; + top: 1rem; + background-color: transparent; + } + } + &__display { cursor: pointer; display: flex; From df89e292f3b9f29c96aaefe87be1967036d9ec8f Mon Sep 17 00:00:00 2001 From: kate-deriv Date: Tue, 16 Jan 2024 17:01:06 +0300 Subject: [PATCH 05/29] feat: add arrow to the trade type widget for mobile --- .../src/components/collapsible/arrow-button.tsx | 12 ++++++++++-- .../src/components/collapsible/collapsible.scss | 13 +++++++++++++ .../src/components/collapsible/collapsible.tsx | 10 +++++++++- .../Form/ContractType/contract-type-display.tsx | 5 ++++- .../Trading/Components/Form/screen-small.tsx | 2 +- .../_common/components/contract-type-widget.scss | 8 +++++++- .../trader/src/sass/app/_common/mobile-widget.scss | 2 +- packages/trader/src/sass/app/modules/trading.scss | 2 +- 8 files changed, 46 insertions(+), 8 deletions(-) diff --git a/packages/components/src/components/collapsible/arrow-button.tsx b/packages/components/src/components/collapsible/arrow-button.tsx index ad616e8cacf0..35f96e40f01e 100644 --- a/packages/components/src/components/collapsible/arrow-button.tsx +++ b/packages/components/src/components/collapsible/arrow-button.tsx @@ -14,6 +14,7 @@ type TArrowButton = { onClick: () => void; title?: string; position?: 'top' | 'bottom'; + flat_button?: boolean; }; const IconArrow = ({ className }: { className?: string }) => ( @@ -29,7 +30,7 @@ const IconArrowWithTitle = ({ title, ...props }: TIconArrowWithTitle) => ( ); -const ArrowButton = ({ is_collapsed = false, position, onClick, title }: TArrowButton) => { +const ArrowButton = ({ is_collapsed = false, position, onClick, title, flat_button = false }: TArrowButton) => { const [is_open, expand] = React.useState(!is_collapsed); const toggleExpand = () => { @@ -82,8 +83,15 @@ const ArrowButton = ({ is_collapsed = false, position, onClick, title }: TArrowB ); } + if (flat_button) icon_arrow =
; + return ( -
+
{icon_arrow}
); diff --git a/packages/components/src/components/collapsible/collapsible.scss b/packages/components/src/components/collapsible/collapsible.scss index 57f0c5ef3ed0..fa4892543e8c 100644 --- a/packages/components/src/components/collapsible/collapsible.scss +++ b/packages/components/src/components/collapsible/collapsible.scss @@ -38,10 +38,23 @@ align-items: center; justify-content: center; height: 32px; + + &--wide { + align-items: baseline; + height: 4.2rem; + } } &__icon { transition: transform 0.3s ease-in-out; + &__flat { + width: 4rem; + height: 0.4rem; + margin-top: 0.8rem; + border-radius: 0.2rem; + background-color: var(--general-active); + } + &--top { transform: rotate(180deg); diff --git a/packages/components/src/components/collapsible/collapsible.tsx b/packages/components/src/components/collapsible/collapsible.tsx index 65bbdd93901a..83c42072b61a 100644 --- a/packages/components/src/components/collapsible/collapsible.tsx +++ b/packages/components/src/components/collapsible/collapsible.tsx @@ -9,6 +9,7 @@ type TCollapsible = { position?: 'top' | 'bottom'; onClick: (state: boolean) => void; title?: string; + flat_button?: boolean; }; const swipe_config = { @@ -24,6 +25,7 @@ const Collapsible = ({ children, onClick, title, + flat_button, }: React.PropsWithChildren) => { const [is_open, expand] = React.useState(!is_collapsed); const [should_show_collapsible, setShouldShowCollapsible] = React.useState(false); @@ -58,7 +60,13 @@ const Collapsible = ({ }); const arrow_button = ( - + ); const CustomTag = as || 'div'; return ( diff --git a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-display.tsx b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-display.tsx index a977f4da0a29..31f4e751dc13 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-display.tsx +++ b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-display.tsx @@ -1,6 +1,6 @@ import classNames from 'classnames'; import React from 'react'; -import { Icon, DesktopWrapper } from '@deriv/components'; +import { Icon, DesktopWrapper, MobileWrapper } from '@deriv/components'; import IconTradeCategory from 'Assets/Trading/Categories/icon-trade-categories'; import { findContractCategory } from '../../../Helpers/contract-type'; import { TContractCategory, TContractType, TList } from './types'; @@ -40,6 +40,9 @@ const Display = ({ is_open, name, list, onClick, value }: TDisplay) => { )} /> + + +
); }; diff --git a/packages/trader/src/Modules/Trading/Components/Form/screen-small.tsx b/packages/trader/src/Modules/Trading/Components/Form/screen-small.tsx index 11b0de8333f8..de2c67cf1602 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/screen-small.tsx +++ b/packages/trader/src/Modules/Trading/Components/Form/screen-small.tsx @@ -83,7 +83,7 @@ const CollapsibleTradeParams = ({ const isVisible = (component: string) => form_components.includes(component); return ( - + {is_accumulator && is_collapsed && }
diff --git a/packages/trader/src/sass/app/_common/components/contract-type-widget.scss b/packages/trader/src/sass/app/_common/components/contract-type-widget.scss index 6c13382ab921..52b96a316a3c 100644 --- a/packages/trader/src/sass/app/_common/components/contract-type-widget.scss +++ b/packages/trader/src/sass/app/_common/components/contract-type-widget.scss @@ -17,7 +17,7 @@ @include mobile { position: absolute; - top: 1rem; + top: 1.5rem; background-color: transparent; } } @@ -73,6 +73,12 @@ transform-origin: 45% 45; color: var(--text-prominent); @extend %inline-icon; + + &--right { + position: absolute; + right: 0; + margin-right: 0.2rem; + } } &__icon-wrapper { display: inline-flex; diff --git a/packages/trader/src/sass/app/_common/mobile-widget.scss b/packages/trader/src/sass/app/_common/mobile-widget.scss index 7d8633992e3b..41fd352d452a 100644 --- a/packages/trader/src/sass/app/_common/mobile-widget.scss +++ b/packages/trader/src/sass/app/_common/mobile-widget.scss @@ -93,7 +93,7 @@ margin-bottom: 0.6rem; margin-left: 0.8rem; justify-content: center; - min-width: 8.8rem; + min-width: 11.9rem; &:has(.mobile-widget__item-tooltip) { min-width: 9.9rem; } diff --git a/packages/trader/src/sass/app/modules/trading.scss b/packages/trader/src/sass/app/modules/trading.scss index 13f71cd20f95..d4691515c6f4 100644 --- a/packages/trader/src/sass/app/modules/trading.scss +++ b/packages/trader/src/sass/app/modules/trading.scss @@ -644,7 +644,7 @@ border-color: var(--general-section-1); color: var(--text-general); @include mobile { - width: 50%; + width: 45%; padding: 0; margin-bottom: 0rem; margin-top: 0.6rem; From e7e99dfdad1153725fb6e8fbf08c25f6d14f6c64 Mon Sep 17 00:00:00 2001 From: kate-deriv Date: Fri, 19 Jan 2024 14:45:45 +0300 Subject: [PATCH 06/29] feat: add info banner for unavailable contracts --- .../ContractTypeInfo/contract-type-info.tsx | 11 +++++- .../ContractType/contract-type-widget.tsx | 35 ++++++++++--------- .../components/contract-type-info.scss | 16 +++++++++ 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeInfo/contract-type-info.tsx b/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeInfo/contract-type-info.tsx index f2c48772b4f5..d56b81deabcb 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeInfo/contract-type-info.tsx +++ b/packages/trader/src/Modules/Trading/Components/Form/ContractType/ContractTypeInfo/contract-type-info.tsx @@ -19,6 +19,7 @@ type TInfo = { ) => void; item: TContractType; list: TList[]; + info_banner?: React.ReactNode; }; const TABS = { @@ -28,7 +29,7 @@ const TABS = { type TSelectedTab = 'description' | 'glossary'; -const Info = observer(({ handleSelect, item, list }: TInfo) => { +const Info = observer(({ handleSelect, item, list, info_banner }: TInfo) => { const { cached_multiplier_cancellation_list, symbol } = useTraderStore(); const { active_symbols: { active_symbols }, @@ -56,6 +57,10 @@ const Info = observer(({ handleSelect, item, list }: TInfo) => { clickAndKeyEventHandler(() => setSelectedTab(TABS.GLOSSARY), e); }; + const is_unavailable = !!list[0].contract_categories?.find( + item => item.is_unavailable && item.contract_types.find(type => type.value === selected_contract_type.value) + ); + React.useEffect(() => { return () => { Analytics.trackEvent('ce_trade_types_form', { @@ -138,6 +143,7 @@ const Info = observer(({ handleSelect, item, list }: TInfo) => { should_scroll_to_selected onChange={e => setSelectedContractType(e.target)} /> + {is_unavailable &&
{info_banner}
} {has_toggle_buttons && (
{
{ interpolation: { escapeValue: false }, })} secondary + is_disabled={is_unavailable} />
diff --git a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx index 0c4049cfbd2d..c7654ffc9fd7 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx +++ b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx @@ -259,6 +259,22 @@ const ContractTypeWidget = observer( }; const should_show_info_banner = !!selected_category_contracts()?.some(i => i.is_unavailable); + const info_banner = ( + s.symbol === symbol)?.display_name, + }} + shouldUnescape + /> + } + /> + ); + return ( s.symbol === symbol)?.display_name, - }} - shouldUnescape - /> - } - /> - ) - } + info_banner={should_show_info_banner && info_banner} learn_more_banner={