Skip to content

Commit

Permalink
polish shared/RoutedTabsHeader & introduce RoutedTabsHeader.module.css
Browse files Browse the repository at this point in the history
  • Loading branch information
amass01 committed Mar 19, 2021
1 parent 17dcc66 commit 664db33
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 104 deletions.
41 changes: 0 additions & 41 deletions app/components/layout/TabbedPage/TabbedPage.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,6 @@
height: 114px;
}

.tabbedPageHeader > .tabs {
position: absolute;
bottom: 0px;
left: 100px;
white-space: nowrap;
}

.tabbedPageHeader > .tabs > .tab {
line-height: 35px;
margin-right: 55px;
}

.tabbedPageHeader > .tabs > .tab:last-of-type {
margin-right: 0;
}

.tabbedPageHeader > .tabs > .tabs-caret > {
position: absolute;
bottom: 0;
height: 5px;
}

.tabbedPageHeader > .tabs > .tabs-caret > .active {
background-color: var(--accent-color);
position: absolute;
height: 5px;
}

.tabContent {
position: absolute;
overflow-x: hidden;
Expand All @@ -66,14 +38,10 @@
background-color: transparent;
}


@media screen and (max-width: 1179px) {
.tabbedPageHeader {
padding-left: 20px;
}
.tabbedPageHeader > .tabs {
left: 55px;
}
.tabContent {
padding: 38px 20px 30px 20px;
}
Expand All @@ -89,15 +57,6 @@
padding-top: 30px;
}

.tabbedPageHeader > .tabs {
font-size: 13px;
left: 25px;
right: 20px;
.tab {
margin-right: 45px;
}
}

.tabContent {
padding: 0 10px 80px 10px;
}
Expand Down
81 changes: 23 additions & 58 deletions app/components/shared/RoutedTabsHeader/RoutedTabsHeader.jsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
import { useState, useEffect, useCallback, useMemo, useRef } from "react";
import { useMemo, useCallback } from "react";
import { NavLink as Link } from "react-router-dom";
import { spring, Motion } from "react-motion";
import { useRoutedTabsHeader } from "./hooks";
import theme from "theme";
import styles from "./RoutedTabsHeader.module.css";

export const RoutedTab = (path, link) => ({ path, link });

const RoutedTabsHeader = ({ tabs, caret }) => {
const nodes = useRef(new Map());
const { uiAnimations, caretLeft, caretWidth, nodes } = useRoutedTabsHeader();

const [caretLeft, setCaretLeft] = useState(null);
const [caretWidth, setCaretWidth] = useState(null);
const [selectedTab, setSelectedTab] = useState(null);
const [localSidebarOnBottom, setLocalSidebarOnBottom] = useState(null);

const { location, uiAnimations, sidebarOnBottom } = useRoutedTabsHeader();

const getAnimatedCaret = () => {
const getAnimatedCaret = useCallback(() => {
const caretStyle = {
left: spring(caretLeft, theme("springs.tab")),
width: spring(caretWidth, theme("springs.tab"))
Expand All @@ -25,78 +19,49 @@ const RoutedTabsHeader = ({ tabs, caret }) => {
return (
<Motion style={caretStyle}>
{(style) => (
<div className={"tabs-caret"}>
<div className={"active"} style={style} />
<div className={styles.tabCaret}>
<div className={styles.active} style={style} />
</div>
)}
</Motion>
);
};
}, [caretLeft, caretWidth]);

const getStaticCaret = () => {
const getStaticCaret = useCallback(() => {
const style = {
left: caretLeft,
width: caretWidth
};

return (
<div className={"tabs-caret"}>
<div className={"active"} style={style}></div>
<div className={styles.tabsCaret}>
<div className={styles.active} style={style}></div>
</div>
);
};
}, [caretLeft, caretWidth]);

const tabLinks = useMemo(
() =>
tabs.map((t) => (
tabs.map(({ path, link }) => (
<span
className={"tab"}
key={t.path}
ref={(ref) => nodes.current.set(t.path, ref)}>
<Link to={t.path} activeClassName={"active"}>
{t.link}
className={styles.tab}
key={path}
ref={(ref) => nodes.current.set(path, ref)}>
<Link to={path} activeClassName={styles.active}>
{link}
</Link>
</span>
)),
[tabs]
[tabs, nodes]
);

const localCaret = uiAnimations ? getAnimatedCaret() : getStaticCaret();

const updateCaretPosition = useCallback(() => {
const selectedTab = location.pathname;
const tabForRoute = nodes.current.get(selectedTab);
if (!tabForRoute) return null;
const tabRect = tabForRoute.getBoundingClientRect();
const caretLeft = tabForRoute.offsetLeft;
const caretWidth = tabRect.width;
setCaretLeft(caretLeft);
setCaretWidth(caretWidth);
setSelectedTab(selectedTab);
}, [location]);

useEffect(() => {
setLocalSidebarOnBottom(sidebarOnBottom);
updateCaretPosition();
}, [sidebarOnBottom, updateCaretPosition]);

useEffect(() => {
if (
selectedTab != location.pathname ||
localSidebarOnBottom != sidebarOnBottom
) {
updateCaretPosition();
}
}, [
location,
selectedTab,
sidebarOnBottom,
localSidebarOnBottom,
updateCaretPosition
]);
const localCaret = useMemo(
() => (uiAnimations ? getAnimatedCaret() : getStaticCaret()),
[uiAnimations, getAnimatedCaret, getStaticCaret]
);

return (
<div className={"tabs"}>
<div className={styles.tabs}>
{tabLinks}
{caret ? caret : localCaret}
</div>
Expand Down
45 changes: 45 additions & 0 deletions app/components/shared/RoutedTabsHeader/RoutedTabsHeader.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.tabs {
position: absolute;
bottom: 0px;
left: 100px;
white-space: nowrap;
}

.tabs > .tab {
line-height: 35px;
margin-right: 55px;
}

.tabs > .tab:last-of-type {
margin-right: 0;
}

.tabs > .tabCaret > {
position: absolute;
bottom: 0;
height: 5px;
}

.tabs > .tabCaret > .active {
background-color: var(--accent-color);
position: absolute;
height: 5px;
}

@media screen and (max-width: 1179px) {
.tabs {
left: 55px;
}
}

@media screen and (max-width: 768px) {
.tabs {
font-size: 13px;
left: 25px;
right: 20px;
}

.tabs > .tab {
margin-right: 45px;
}
}
41 changes: 36 additions & 5 deletions app/components/shared/RoutedTabsHeader/hooks.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,45 @@
import { useEffect, useCallback, useState, useRef } from "react";
import { useSelector } from "react-redux";
import * as sel from "selectors";

export function useRoutedTabsHeader() {
const location = useSelector(sel.location);
const nodes = useRef(new Map());
const [caretLeft, setCaretLeft] = useState(null);
const [caretWidth, setCaretWidth] = useState(null);
const [selectedTab, setSelectedTab] = useState(null);
const [localSidebarOnBottom, setLocalSidebarOnBottom] = useState(null);
const { pathname } = useSelector(sel.location);
const sidebarOnBottom = useSelector(sel.sidebarOnBottom);
const uiAnimations = useSelector(sel.uiAnimations);

return {
location,
const updateCaretPosition = useCallback(() => {
const selectedTab = pathname;
const tabForRoute = nodes.current.get(selectedTab);
if (!tabForRoute) return null;
const tabRect = tabForRoute.getBoundingClientRect();
const caretLeft = tabForRoute.offsetLeft;
const caretWidth = tabRect.width;
setCaretLeft(caretLeft);
setCaretWidth(caretWidth);
setSelectedTab(selectedTab);
}, [pathname]);

useEffect(() => {
setLocalSidebarOnBottom(sidebarOnBottom);
updateCaretPosition();
}, [sidebarOnBottom, updateCaretPosition]);

useEffect(() => {
if (selectedTab != pathname || localSidebarOnBottom != sidebarOnBottom) {
updateCaretPosition();
}
}, [
pathname,
selectedTab,
sidebarOnBottom,
uiAnimations
};
localSidebarOnBottom,
updateCaretPosition
]);

return { uiAnimations, caretLeft, caretWidth, nodes };
}

0 comments on commit 664db33

Please sign in to comment.