Skip to content

Commit 749ca2f

Browse files
Merge pull request #380 from topcoder-platform/TCA-407_my-learning-filtering
TCA-407 my learning filtering -> dev
2 parents ce5c871 + f4b8d16 commit 749ca2f

File tree

6 files changed

+118
-32
lines changed

6 files changed

+118
-32
lines changed

src-ts/lib/form/form-groups/form-input/input-select/InputSelect.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ const InputSelect: FC<InputSelectProps> = (props: InputSelectProps) => {
6868
hideInlineErrors={props.hideInlineErrors}
6969
ref={triggerRef}
7070
>
71-
<div className={styles['selected']} onClick={() => !props.disabled && toggleMenu}>
71+
<div className={styles['selected']} onClick={() => !props.disabled && toggleMenu()}>
7272
<span className='body-small'>{selectedOption ? label(selectedOption) : ''}</span>
7373
<span className={styles['selected-icon']}>
7474
<IconOutline.ChevronDownIcon />

src-ts/lib/styles/mixins/_icons.mixins.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
width: $space-xxl;
2626
}
2727

28+
@mixin icon-xxxl {
29+
height: $space-xxxl;
30+
width: $space-xxxl;
31+
}
2832
@mixin icon-xxxxl {
2933
height: $space-xxxxl;
3034
width: $space-xxxxl;

src-ts/lib/tabs-navbar/TabsNavbar.module.scss

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,60 @@
22
@import '../styles/typography';
33

44
.tabs-wrapper {
5-
display: flex;
6-
background: $blue-10;
7-
border-bottom: 1px solid $black-20;
5+
position: relative;
86
margin-bottom: $space-md;
7+
border-bottom: 1px solid $black-20;
8+
background: $blue-10;
9+
}
910

10-
position: relative;
11+
.menu-trigger {
12+
display: flex;
13+
align-items: center;
14+
padding-right: $space-md;
15+
16+
.tab-item {
17+
.tab-label {
18+
@include font-weight-bold;
19+
}
20+
}
21+
22+
svg {
23+
@include icon-xxxl;
24+
margin-left: auto;
25+
color: $turq-160;
26+
transition: 0.15s ease-in-out;
27+
}
28+
29+
&.menu-is-visible {
30+
svg {
31+
transform: rotate(180deg);
32+
}
33+
}
34+
35+
@include ltemd {
36+
&:not(.menu-is-visible) {
37+
+ .menu-wrapper {
38+
display: none;
39+
}
40+
}
41+
}
42+
}
43+
44+
.menu-wrapper {
45+
display: flex;
46+
background: $blue-10;
1147

1248
@include ltemd {
1349
flex-direction: column;
50+
position: absolute;
51+
top: 100%;
52+
left: 0;
53+
width: 100%;
54+
z-index: 1;
55+
56+
.tab-item {
57+
border-top: 1px solid $black-20;
58+
}
1459
}
1560
}
1661

@@ -22,7 +67,7 @@
2267
padding: $space-md $space-lg calc($space-md - 2px);
2368
color: $black-80;
2469
cursor: pointer;
25-
70+
2671
&:global(.active) {
2772
color: $black-100;
2873
background-color: $blue-25;
@@ -32,10 +77,6 @@
3277
}
3378
}
3479

35-
&:global(.active) ~ .active-icon > svg path:last-child {
36-
fill: $blue-25;
37-
}
38-
3980
&:hover:not(:global(.active)) {
4081
color: $black-100;
4182
background-color: $blue-15;
@@ -73,8 +114,11 @@
73114
top: 100%;
74115
left: 0;
75116
transform: translateX(-50%);
76-
117+
77118
transition: left 0.15s ease-in-out;
119+
> svg path:last-child {
120+
fill: $blue-25;
121+
}
78122
@include ltemd {
79123
display: none;
80124
}

src-ts/lib/tabs-navbar/TabsNavbar.tsx

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@ import {
33
Dispatch,
44
FC,
55
MutableRefObject,
6+
ReactNode,
67
SetStateAction,
78
useCallback,
89
useLayoutEffect,
10+
useMemo,
911
useRef,
1012
useState,
1113
} from 'react'
1214

13-
import { ActiveTabTipIcon } from '../svgs'
15+
import { useClickOutside } from '../hooks'
16+
import { ActiveTabTipIcon, IconOutline } from '../svgs'
1417

1518
import { TabsNavItem } from './tabs-nav-item.model'
1619
import styles from './TabsNavbar.module.scss'
@@ -28,6 +31,12 @@ const TabsNavbar: FC<TabsNavbarProps> = (props: TabsNavbarProps) => {
2831
const tabRefs: MutableRefObject<Array<HTMLElement>> = useRef([] as Array<HTMLElement>)
2932
const [tabOpened, setTabOpened]: [string | undefined, Dispatch<SetStateAction<string | undefined>>] = useState<string | undefined>(props.defaultActive)
3033
const [offset, setOffset]: [number, Dispatch<SetStateAction<number>>] = useState<number>(0)
34+
const [menuIsVisible, setMenuIsVisible]: [boolean, Dispatch<SetStateAction<boolean>>] = useState(false)
35+
const triggerRef: MutableRefObject<any> = useRef(undefined)
36+
37+
const activeTab: TabsNavItem = useMemo(() => (
38+
props.tabs.find(tab => tab.id === tabOpened) as TabsNavItem
39+
), [tabOpened, props.tabs])
3140

3241
const updateOffset: (tabId: string) => void = useCallback((tabId: string) => {
3342

@@ -37,8 +46,8 @@ const TabsNavbar: FC<TabsNavbarProps> = (props: TabsNavbarProps) => {
3746
return
3847
}
3948

40-
const activeTab: HTMLElement = tabRefs.current[index]
41-
setOffset(activeTab.offsetLeft + activeTab.offsetWidth / 2)
49+
const activatedTab: HTMLElement = tabRefs.current[index]
50+
setOffset(activatedTab.offsetLeft + activatedTab.offsetWidth / 2)
4251
}, [
4352
props.tabs,
4453
])
@@ -70,27 +79,54 @@ const TabsNavbar: FC<TabsNavbarProps> = (props: TabsNavbarProps) => {
7079
updateOffset,
7180
])
7281

82+
const renderTabItem: (tab: TabsNavItem, activeTabId?: string, ref?: (el: HTMLDivElement) => void) => ReactNode = (
83+
tab: TabsNavItem,
84+
activeTabId?: string,
85+
ref?: (el: HTMLDivElement) => void
86+
) => (
87+
<div
88+
ref={ref}
89+
className={classNames(styles['tab-item'], activeTabId === tab.id && 'active')}
90+
key={tab.id}
91+
onClick={() => handleActivateTab(tab.id)}
92+
>
93+
<span className={styles['tab-label']}>
94+
{tab.title}
95+
</span>
96+
{tab.badges?.map((badge, id) => (
97+
<span className={classNames(styles['tab-badge'], badge.type)} key={id}>
98+
{badge.count}
99+
</span>
100+
))}
101+
</div>
102+
)
103+
104+
useClickOutside(triggerRef.current, () => setMenuIsVisible(false))
105+
73106
return (
74107
<div className={styles['tabs-wrapper']}>
75-
{props.tabs.map((tab, i) => (
76-
<div
77-
ref={el => tabRefs.current[i] = el as HTMLElement}
78-
className={classNames(styles['tab-item'], tabOpened === tab.id && 'active')}
79-
key={tab.id}
80-
onClick={() => handleActivateTab(tab.id)}
81-
>
82-
<span className={styles['tab-label']}>
83-
{tab.title}
84-
</span>
85-
{tab.badges?.map((badge, id) => (
86-
<span className={classNames(styles['tab-badge'], badge.type)} key={id}>
87-
{badge.count}
88-
</span>
89-
))}
90-
</div>
91-
))}
92108
<div
93-
className={styles['active-icon']}
109+
className={
110+
classNames(
111+
styles['menu-trigger'],
112+
'desktop-hide',
113+
menuIsVisible && styles['menu-is-visible']
114+
)
115+
}
116+
onClick={() => setMenuIsVisible((menuWasVisible: boolean) => !menuWasVisible)}
117+
ref={triggerRef}
118+
>
119+
{renderTabItem(activeTab)}
120+
<IconOutline.ChevronDownIcon />
121+
</div>
122+
123+
<div className={classNames(styles['menu-wrapper'])}>
124+
{props.tabs.map((tab, i) => (
125+
renderTabItem(tab, tabOpened, el => {tabRefs.current[i] = el as HTMLElement})
126+
))}
127+
</div>
128+
<div
129+
className={classNames(styles['active-icon'], 'mobile-hide')}
94130
style={{ left: `${offset}px` }}
95131
>
96132
<ActiveTabTipIcon />

src-ts/tools/learn/my-learning/completed-tab/CompletedTab.module.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
display: flex;
55
gap: $space-xxl;
66
flex-wrap: wrap;
7+
flex: 1;
78

89
> * {
910
flex: 0 1 calc(50% - calc($space-xxl / 2));

src-ts/tools/learn/my-learning/in-progress-tab/InProgressTab.module.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
display: flex;
66
flex-direction: column;
77
position: relative;
8+
flex: 1;
89

910
@include ltemd {
1011
gap: $space-xxl;

0 commit comments

Comments
 (0)