refactor(mobile): tabs navigation, observer active for tabs, tabs layout scrolling
This commit is contained in:
parent
2e9e9b0a06
commit
be9bfc28c8
@ -43,30 +43,37 @@
|
||||
position: sticky;
|
||||
top: $header-height + $body-vertical-padding;
|
||||
}
|
||||
> :first-child {
|
||||
max-height: calc(
|
||||
100svh - $header-height - $body-vertical-padding * 2 - $tabs-height
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.files {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
grid-gap: 15px;
|
||||
}
|
||||
.content {
|
||||
padding: 10px;
|
||||
border: 10px solid $overlay-background-color;
|
||||
border-radius: 4px;
|
||||
|
||||
.scrollAdjust {
|
||||
@media only screen and (max-width: 767px) {
|
||||
max-height: calc(100svh - $header-height + $body-vertical-padding * 2);
|
||||
max-height: calc(
|
||||
100svh - $header-height - $body-vertical-padding * 2 - $tabs-height
|
||||
);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
@media only screen and (min-width: 768px) {
|
||||
padding: 10px;
|
||||
border: 10px solid $overlay-background-color;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.navTabs {
|
||||
display: none;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
height: $tabs-height;
|
||||
z-index: 2;
|
||||
background: $overlay-background-color;
|
||||
box-shadow: 0 0 4px 0 rgb(0, 0, 0, 0.1);
|
||||
|
@ -21,18 +21,17 @@ interface StickySideColumnsProps {
|
||||
}
|
||||
|
||||
const DEFAULT_TAB = 'nav-content'
|
||||
|
||||
export const StickySideColumns = ({
|
||||
left,
|
||||
right,
|
||||
children
|
||||
}: PropsWithChildren<StickySideColumnsProps>) => {
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const [tab, setTab] = useState(DEFAULT_TAB)
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const tabsRefs = useRef<{ [id: string]: HTMLDivElement | null }>({})
|
||||
const handleNavClick = (id: string) => {
|
||||
setTab(id)
|
||||
const x = document.getElementById(id)?.offsetLeft
|
||||
if (ref.current) {
|
||||
if (ref.current && tabsRefs.current) {
|
||||
const x = tabsRefs.current[id]?.offsetLeft
|
||||
ref.current.scrollTo({
|
||||
left: x,
|
||||
behavior: 'smooth'
|
||||
@ -42,21 +41,67 @@ export const StickySideColumns = ({
|
||||
const isActive = (id: string) => id === tab
|
||||
|
||||
useEffect(() => {
|
||||
setTab(DEFAULT_TAB)
|
||||
handleNavClick(DEFAULT_TAB)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const tabs = tabsRefs.current
|
||||
// Set up the observer
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
setTab(entry.target.id)
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
root: ref.current,
|
||||
threshold: 0.5,
|
||||
rootMargin: '-20px'
|
||||
}
|
||||
)
|
||||
|
||||
if (tabs) {
|
||||
Object.values(tabs).forEach((tab) => {
|
||||
if (tab) observer.observe(tab)
|
||||
})
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (tabs) {
|
||||
Object.values(tabs).forEach((tab) => {
|
||||
if (tab) observer.unobserve(tab)
|
||||
})
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.container} ref={ref}>
|
||||
<div id="nav-left" className={`${styles.sidesWrap} ${styles.files}`}>
|
||||
<div
|
||||
id="nav-left"
|
||||
className={styles.sidesWrap}
|
||||
ref={(tab) => (tabsRefs.current['nav-left'] = tab)}
|
||||
>
|
||||
<div className={styles.sides}>{left}</div>
|
||||
</div>
|
||||
<div id="nav-content">
|
||||
<div
|
||||
id="nav-content"
|
||||
className={styles.scrollAdjust}
|
||||
ref={(tab) => (tabsRefs.current['nav-content'] = tab)}
|
||||
>
|
||||
<div id="content-preview" className={styles.content}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
<div id="nav-right" className={styles.sidesWrap}>
|
||||
<div
|
||||
id="nav-right"
|
||||
className={styles.sidesWrap}
|
||||
ref={(tab) => (tabsRefs.current['nav-right'] = tab)}
|
||||
>
|
||||
<div className={styles.sides}>{right}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -999,7 +999,7 @@ export const CreatePage = () => {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className={styles.paperGroup}>
|
||||
<div className={`${styles.paperGroup} ${styles.users}`}>
|
||||
<DisplayUser
|
||||
metadata={metadata}
|
||||
users={users}
|
||||
|
@ -69,10 +69,6 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
|
||||
// Automatic scrolling if paper-group gets large enough
|
||||
// used for files on the left and users on the right
|
||||
max-height: 350px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
@ -80,6 +76,7 @@
|
||||
.inputWrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
height: 34px;
|
||||
overflow: hidden;
|
||||
@ -94,6 +91,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
.users {
|
||||
flex-shrink: 0;
|
||||
max-height: 33vh;
|
||||
}
|
||||
|
||||
.user {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
@ -144,7 +146,6 @@
|
||||
|
||||
gap: 15px;
|
||||
|
||||
max-height: 450px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
|
@ -53,7 +53,6 @@ import { convertToSigitFile, SigitFile } from '../../utils/file.ts'
|
||||
import { FileDivider } from '../../components/FileDivider.tsx'
|
||||
import { ExtensionFileBox } from '../../components/ExtensionFileBox.tsx'
|
||||
import { useScale } from '../../hooks/useScale.tsx'
|
||||
import { Footer } from '../../components/Footer/Footer.tsx'
|
||||
|
||||
interface PdfViewProps {
|
||||
files: CurrentUserFile[]
|
||||
@ -581,7 +580,6 @@ export const VerifyPage = () => {
|
||||
</StickySideColumns>
|
||||
)}
|
||||
</Container>
|
||||
<Footer />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -2,3 +2,5 @@ $header-height: 65px;
|
||||
$body-vertical-padding: 25px;
|
||||
|
||||
$default-container-padding-inline: 10px;
|
||||
|
||||
$tabs-height: 40px;
|
||||
|
Loading…
Reference in New Issue
Block a user