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