Skip to content

Commit 273878e

Browse files
committed
fix various scrolling related issues
1 parent 1f70821 commit 273878e

File tree

2 files changed

+116
-46
lines changed

2 files changed

+116
-46
lines changed

src/app/App.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -466,22 +466,22 @@ export const AppFC: FC<AppFCProps> = function AppFC(appProps) {
466466

467467
let app =
468468
<Box sx={{
469-
position: 'absolute', // Added to fill viewport
469+
position: 'absolute',
470470
top: 0,
471471
left: 0,
472472
right: 0,
473473
bottom: 0,
474-
overflow: 'auto', // Enable scrolling at root level
475474
'& > *': {
476-
minWidth: '1200px',
475+
minWidth: '1000px',
477476
minHeight: '800px'
478477
}
479478
}}>
480479
<Box sx={{
481480
display: 'flex',
482481
flexDirection: 'column',
483482
height: '100%',
484-
width: '100%'
483+
width: '100%',
484+
overflow: 'hidden'
485485
}}>
486486
{appBar}
487487
<RouterProvider router={router} />

src/views/DataThread.tsx

Lines changed: 112 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
Tooltip,
1616
ButtonGroup,
1717
useTheme,
18+
SxProps
1819
} from '@mui/material';
1920

2021
import { VegaLite } from 'react-vega'
@@ -67,13 +68,15 @@ let SingleThreadView: FC<{
6768
threadIdx: number,
6869
leafTable: DictTable;
6970
chartElements: { tableId: string, chartId: string, element: any }[];
70-
usedTableIds: string[]
71+
usedTableIds: string[],
72+
sx?: SxProps
7173
}> = function ({
7274
scrollRef,
7375
threadIdx,
7476
leafTable,
7577
chartElements,
7678
usedTableIds, // tables that have been used
79+
sx
7780
}) {
7881
let theme = useTheme();
7982

@@ -84,7 +87,6 @@ let SingleThreadView: FC<{
8487

8588
let focusedChart = charts.find(c => c.id == focusedChartId);
8689

87-
8890
const dispatch = useDispatch();
8991

9092
let [collapsed, setCollapsed] = useState<boolean>(false);
@@ -118,7 +120,8 @@ let SingleThreadView: FC<{
118120
let fieldsIdentical = _.isEqual(previousActiveFields, currentActiveFields)
119121

120122
let triggerCard = <div key={'thread-card-trigger-box'}>
121-
<Box sx={{ flex: 1 }} /*sx={{ width: 'calc(100% - 8px)', marginLeft: 1, borderLeft: '1px dashed darkgray' }}*/ >
123+
<Box sx={{ flex: 1 }}
124+
/*sx={{ width: 'calc(100% - 8px)', marginLeft: 1, borderLeft: '1px dashed darkgray' }}*/ >
122125
<TriggerCard className={selectedClassName} trigger={trigger} hideFields={fieldsIdentical} />
123126
</Box>
124127
</div>;
@@ -228,11 +231,12 @@ let SingleThreadView: FC<{
228231
key={`table-${tableId}`}
229232
sx={{ display: 'flex', flexDirection: 'row' }}>
230233
<div style={{
231-
minWidth: '1px', padding: '0px', width: '17px', flex: 'none', display: 'flex'
232-
//borderLeft: '1px dashed darkgray',
234+
minWidth: '1px', padding: '0px', width: '8px', flex: 'none', display: 'flex',
235+
marginLeft: '8px',
236+
borderLeft: '1px dashed darkgray',
233237
}}>
234238
<Box sx={{
235-
padding: 0, width: '1px', margin: 'auto', height: '100%',
239+
padding: 0, width: '1px', margin: 'auto',
236240
//borderLeft: 'thin solid lightgray',
237241
// the following for
238242
backgroundImage: 'linear-gradient(180deg, darkgray, darkgray 75%, transparent 75%, transparent 100%)',
@@ -252,31 +256,9 @@ let SingleThreadView: FC<{
252256
content = w(tableList, triggerCards, "")
253257

254258
return <Box sx={{
255-
backgroundColor: (threadIdx % 2 == 1 ? "rgba(0, 0, 0, 0.02)" : 'white'), //threadIsFocused ? alpha(theme.palette.primary.main, 0.05) :
256-
padding: '8px 8px'
257-
}}>
258-
{/* <Tooltip title={collapsed ? 'expand' : 'collapse'}>
259-
<Button fullWidth sx={{display: 'flex', direction: 'ltr'}} color="primary" onClick={() => setCollapsed(!collapsed)}>
260-
<Divider flexItem sx={{
261-
"& .MuiDivider-wrapper": {
262-
display: 'flex', flexDirection: 'row',
263-
},
264-
"&::before, &::after": {
265-
borderColor: theme.palette.primary.light,
266-
opacity: 0.5,
267-
borderWidth: '4px',
268-
width: 50,
269-
270-
},
271-
}}
272-
>
273-
<Typography sx={{fontSize: "10px", fontWeight: 'bold', textTransform: 'none'}}>
274-
{`thread - ${threadIdx + 1}`}
275-
</Typography>
276-
{!collapsed ? <ExpandLess sx={{fontSize: 14}}/> : <ExpandMore sx={{fontSize: 14}}/>}
277-
</Divider>
278-
</Button>
279-
</Tooltip>*/}
259+
260+
...sx
261+
}} data-thread-index={threadIdx}>
280262
<Box sx={{ display: 'flex', direction: 'ltr', margin: 1 }}>
281263
<Divider flexItem sx={{
282264
margin: 'auto',
@@ -462,41 +444,129 @@ export const DataThread: FC<{}> = function ({ }) {
462444
let refTables = tables;
463445
let leafTables = refTables.filter(t => !refTables.some(t2 => t2.derive?.trigger.tableId == t.id));
464446

465-
466447
let drawerOpen = leafTables.length > 1 && threadDrawerOpen;
467-
468-
let view = <Box sx={{ width: '100%', margin: "0px 0px 8px 0px", display: 'flex', flexDirection: drawerOpen ? 'row-reverse' : 'column', paddingBottom: 2 }}>
448+
let threadDrawerWidth = Math.max(Math.min(600, leafTables.length * 200), 212)
449+
450+
let view = <Box width={drawerOpen ? threadDrawerWidth + 12 : 224} sx={{
451+
overflowY: 'auto',
452+
position: 'relative',
453+
display: 'flex',
454+
flexDirection: drawerOpen ? 'row-reverse' : 'column',
455+
}}>
469456
{leafTables.map((lt, i) => {
470457
let usedTableIds = leafTables.slice(0, i)
471458
.map(x => [x.id, ...getTriggers(x, tables).map(y => y.tableId) || []]).flat();
472459
return <SingleThreadView
473460
key={`thread-${lt.id}`}
474-
scrollRef={scrollRef} threadIdx={i} leafTable={lt} chartElements={chartElements} usedTableIds={usedTableIds} />
461+
scrollRef={scrollRef}
462+
threadIdx={i}
463+
leafTable={lt}
464+
chartElements={chartElements}
465+
usedTableIds={usedTableIds}
466+
sx={{
467+
backgroundColor: (i % 2 == 1 ? "rgba(0, 0, 0, 0.02)" : 'white'),
468+
padding: '8px 8px',
469+
flex: 1,
470+
display: 'flex',
471+
flexDirection: 'column',
472+
height: '100%'
473+
}} />
475474
})}
476475
</Box>
477476

478-
let threadDrawerWidth = Math.max(Math.min(Math.max(600, window.innerWidth * 0.8), leafTables.length * 200), 212)
477+
478+
let jumpButtonsDrawerOpen = <ButtonGroup size="small" color="primary">
479+
{_.chunk(Array.from({length: leafTables.length}, (_, i) => i), 3).map((group, groupIdx) => {
480+
const startNum = group[0] + 1;
481+
const endNum = group[group.length - 1] + 1;
482+
const label = startNum === endNum ? `${startNum}` : `${startNum}-${endNum}`;
483+
484+
return (
485+
<Tooltip key={`thread-nav-group-${groupIdx}`} title={`Jump to thread${startNum === endNum ? '' : 's'} ${label}`}>
486+
<IconButton
487+
size="small"
488+
color="primary"
489+
sx={{ fontSize: '12px' }}
490+
onClick={() => {
491+
setTimeout(() => {
492+
// Get currently most visible thread index
493+
const viewportCenter = window.innerWidth / 2;
494+
const currentIndex = Array.from(document.querySelectorAll('[data-thread-index]')).reduce((closest, element) => {
495+
const rect = element.getBoundingClientRect();
496+
const distance = Math.abs(rect.left + rect.width/2 - viewportCenter);
497+
if (!closest || distance < closest.distance) {
498+
return { index: parseInt(element.getAttribute('data-thread-index') || '0'), distance };
499+
}
500+
return closest;
501+
}, null as { index: number, distance: number } | null)?.index || 0;
502+
503+
// If moving from larger to smaller numbers (scrolling left), target first element
504+
// If moving from smaller to larger numbers (scrolling right), target last element
505+
const targetIndex = currentIndex > group[0] ? group[0] : group[group.length - 1];
506+
507+
const targetElement = document.querySelector(`[data-thread-index="${targetIndex}"]`);
508+
if (targetElement) {
509+
targetElement.scrollIntoView({
510+
behavior: 'smooth',
511+
block: 'nearest', // Don't change vertical scroll
512+
inline: currentIndex > group[group.length - 1] ? 'start' : 'end'
513+
});
514+
}
515+
}, 100);
516+
}}
517+
>
518+
{label}
519+
</IconButton>
520+
</Tooltip>
521+
);
522+
})}
523+
</ButtonGroup>
524+
525+
let jumpButtonDrawerClosed = <ButtonGroup size="small" color="primary" sx={{ gap: 0 }}>
526+
{leafTables.map((_, idx) => (
527+
<Tooltip key={`thread-nav-${idx}`} title={`Jump to thread ${idx + 1}`}>
528+
<IconButton
529+
size="small"
530+
color="primary"
531+
sx={{ fontSize: '12px', padding: '4px' }}
532+
onClick={() => {
533+
const threadElement = document.querySelector(`[data-thread-index="${idx}"]`);
534+
threadElement?.scrollIntoView({ behavior: 'smooth' });
535+
}}
536+
>
537+
{idx + 1}
538+
</IconButton>
539+
</Tooltip>
540+
))}
541+
</ButtonGroup>
542+
543+
let jumpButtons = drawerOpen ? jumpButtonsDrawerOpen : jumpButtonDrawerClosed;
544+
479545

480546
let carousel = (
481547
<Box className="data-thread" sx={{ overflow: 'hidden', }}>
482548
<Box sx={{
483549
direction: 'ltr', display: 'flex',
484550
paddingTop: "10px", paddingLeft: '12px', alignItems: 'center', justifyContent: 'space-between'
485551
}}>
486-
<Typography className="view-title" component="h2" sx={{ marginTop: "6px" }}>
487-
Data Threads
488-
</Typography>
552+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
553+
<Typography className="view-title" component="h2" sx={{ marginTop: "6px" }}>
554+
Data Threads
555+
</Typography>
556+
{jumpButtons}
557+
</Box>
558+
489559
<Tooltip title={drawerOpen ? "collapse" : "expand"}>
490560
<IconButton size={'small'} color="primary" disabled={leafTables.length <= 1} onClick={() => { setThreadDrawerOpen(!threadDrawerOpen); }}>
491561
{drawerOpen ? <ChevronLeftIcon /> : <ChevronRightIcon />}
492562
</IconButton>
493563
</Tooltip>
494564
</Box>
495565
<Box sx={{
496-
transition: 'width 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms', overflow: 'auto',
497-
direction: 'rtl', display: 'flex', flex: 1
566+
transition: 'width 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms', overflowY: 'auto',
567+
direction: 'rtl', display: 'block', flex: 1
498568
}}
499-
width={drawerOpen ? threadDrawerWidth + 12 : 224} className="thread-view-mode">
569+
className="thread-view-mode">
500570
{view}
501571
</Box>
502572
</Box>

0 commit comments

Comments
 (0)