Skip to content

Commit a7afdce

Browse files
committed
feat: Sticky Headers and Responsive Tables
1 parent 7936223 commit a7afdce

File tree

4 files changed

+82
-99
lines changed

4 files changed

+82
-99
lines changed

src/components/FeedOutputBrowser/FeedOutputBrowser.css

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -12,95 +12,23 @@
1212
}
1313
}
1414

15-
.feed-output-browser__button {
16-
cursor: pointer;
17-
}
18-
1915
.file-browser {
2016
height: 100%;
2117
}
2218

23-
.file-browser__drawerbody {
24-
overflow: scroll;
25-
}
26-
27-
.file-browser .carousel {
28-
position: absolute;
29-
bottom: 0;
30-
right: 0;
31-
z-index: 999;
32-
}
33-
34-
.file-browser__previewPanel .pf-v5-c-drawer__content,
35-
.file-browser__previewPanel .pf-v5-c-drawer__panel,
36-
.file-browser__previewPanel .pf-v5-c-drawer__panel-main {
37-
overflow: hidden !important;
38-
}
39-
40-
.file-browser__table--fileName {
41-
display: flex;
42-
flex-direction: row;
43-
}
44-
4519
.file-browser__header {
4620
display: flex;
4721
flex-direction: column;
4822
gap: 0.25em;
4923
margin-right: 0.25em;
5024
}
5125

52-
.file-browser__header__info {
53-
gap: 2rem;
54-
display: flex;
55-
justify-content: flex-end;
56-
}
57-
5826
@media screen and (min-width: 1024px) {
5927
.file-browser__header {
6028
display: flex;
6129
}
6230
}
6331

64-
.file-browser .pf-c-breadcrumb {
65-
cursor: pointer;
66-
--pf-v5-c-breadcrumb__item--FontSize: var(--pf-global--FontSize--md);
67-
}
68-
69-
.file-browser__firstGrid {
70-
overflow-y: scroll !important;
71-
height: 100% !important;
72-
max-width: 100%;
73-
margin: 0;
74-
}
75-
76-
.file-browser__firstGrid tbody tr {
77-
cursor: pointer;
78-
}
79-
80-
.file-browser__firstGrid svg {
81-
margin-right: 0.25em;
82-
}
83-
84-
.file-browser .header-panel__buttons {
85-
display: flex;
86-
justify-content: space-between;
87-
}
88-
89-
.file-browser .preview-panel {
90-
display: flex;
91-
justify-content: space-between;
92-
}
93-
94-
.file-browser .preview-panel > div {
95-
width: 100%;
96-
}
97-
98-
.file-browser .preview-panel > div > div:first-child {
99-
display: flex;
100-
flex-direction: row;
101-
justify-content: space-between;
102-
}
103-
10432
.iframe-container {
10533
height: 100%;
10634
}

src/components/FeedOutputBrowser/FileBrowser.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
} from "@patternfly/react-core";
1313
import { Table, Tbody, Th, Thead, Tr } from "@patternfly/react-table";
1414
import { useEffect } from "react";
15+
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
1516
import { setFilePreviewPanel } from "../../store/drawer/drawerSlice";
1617
import {
1718
clearSelectedFile,
@@ -38,8 +39,6 @@ import { OperationContext } from "../NewLibrary/context";
3839
import FileDetailView from "../Preview/FileDetailView";
3940
import XtkViewer from "../XtkViewer/XtkViewer";
4041
import type { FileBrowserProps } from "./types";
41-
import { PanelGroup, Panel, PanelResizeHandle } from "react-resizable-panels";
42-
import backgroundColors from "@cornerstonejs/core/dist/types/constants/backgroundColors";
4342

4443
const previewAnimation = [{ opacity: "0.0" }, { opacity: "1.0" }];
4544

@@ -153,7 +152,6 @@ const FileBrowser = (props: FileBrowserProps) => {
153152
return (
154153
<Grid hasGutter className="file-browser">
155154
{contextHolder}
156-
157155
<PanelGroup autoSaveId="conditional" direction="horizontal">
158156
{/* Left Panel: File Browser */}
159157
{drawerState.files.open && (
@@ -164,6 +162,7 @@ const FileBrowser = (props: FileBrowserProps) => {
164162
id="4"
165163
defaultSize={53}
166164
minSize={20}
165+
style={{ display: "flex", flexDirection: "column" }}
167166
>
168167
{/* Drawer Action Button for Files */}
169168
<DrawerActionButton
@@ -220,20 +219,30 @@ const FileBrowser = (props: FileBrowserProps) => {
220219
</div>
221220
</div>
222221
{/* Scrollable Content */}
223-
<div className="scrollable-content">
222+
223+
<div style={{ flex: 1, overflow: "auto" }}>
224224
<Table
225225
style={{
226226
backgroundColor: "inherit",
227227
}}
228228
variant="compact"
229+
isStickyHeader={true}
229230
>
230231
<Thead aria-label="file-browser-table">
231232
<Tr>
232233
<Th aria-label="file-selection-checkbox" />
233-
<Th aria-label="file-name">{columnNames.name}</Th>
234-
<Th aria-label="file-creator">{columnNames.created}</Th>
235-
<Th aria-label="file-owner">{columnNames.creator}</Th>
236-
<Th aria-label="file-size">{columnNames.size}</Th>
234+
<Th aria-label="file-name" width={40}>
235+
{columnNames.name}
236+
</Th>
237+
<Th aria-label="file-creator" width={20}>
238+
{columnNames.created}
239+
</Th>
240+
<Th aria-label="file-owner" width={20}>
241+
{columnNames.creator}
242+
</Th>
243+
<Th aria-label="file-size" width={20}>
244+
{columnNames.size}
245+
</Th>
237246
</Tr>
238247
</Thead>
239248
<Tbody>

src/components/NewLibrary/components/LibraryTable.tsx

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import useNewResourceHighlight from "../utils/useNewResourceHighlight";
3434
import { FolderContextMenu } from "./ContextMenu";
3535
import { getFileName, getLinkFileName } from "./FileCard";
3636
import { getFolderName } from "./FolderCard";
37+
import TruncatedText from "./TruncatedText";
3738

3839
interface TableProps {
3940
data: {
@@ -148,7 +149,7 @@ const BaseRow: React.FC<RowProps> = ({
148149
isSelected: isSelected,
149150
}}
150151
/>
151-
<Td dataLabel={columnNames.name}>
152+
<Td dataLabel={columnNames.name} modifier="truncate">
152153
<Button
153154
onClick={(e) => {
154155
e.stopPropagation();
@@ -158,23 +159,21 @@ const BaseRow: React.FC<RowProps> = ({
158159
icon={icon}
159160
variant="link"
160161
>
161-
{name}
162+
<TruncatedText text={name} className="pf-c-button__text" />
162163
</Button>
163-
<span
164-
style={{
165-
display: "inline-block",
166-
width: "90px",
167-
marginLeft: "0.25em",
168-
}}
169-
>
170-
{isNewResource ? <Tag color="#3E8635">Newly Added</Tag> : null}
171-
</span>
164+
{isNewResource && (
165+
<span style={{ marginLeft: "0.5em" }}>
166+
<Tag color="#3E8635">Newly Added</Tag>
167+
</span>
168+
)}
169+
</Td>
170+
<Td dataLabel={columnNames.date} modifier="truncate">
171+
<TruncatedText text={format(new Date(date), "dd MMM yyyy, HH:mm")} />
172172
</Td>
173-
<Td dataLabel={columnNames.date}>
174-
{format(new Date(date), "dd MMM yyyy, HH:mm")}
173+
<Td dataLabel={columnNames.owner} modifier="truncate">
174+
<TruncatedText text={owner} />
175175
</Td>
176-
<Td dataLabel={columnNames.owner}>{owner}</Td>
177-
<Td dataLabel={columnNames.size}>
176+
<Td dataLabel={columnNames.size} modifier="truncate">
178177
{size > 0 ? formatBytes(size, 0) : " "}
179178
</Td>
180179
</Tr>
@@ -308,19 +307,32 @@ const LibraryTable: React.FC<TableProps> = ({
308307
variant="compact"
309308
aria-label="Simple table"
310309
isStriped={true}
310+
isStickyHeader={true}
311311
>
312312
<Caption>Data Library</Caption>
313313
<Thead>
314314
<Tr>
315315
<Th screenReaderText="Select a row" arial-label="Select a row" />
316-
<Th sort={{ sortBy, onSort, columnIndex: 1 }} name="name">
316+
<Th
317+
sort={{ sortBy, onSort, columnIndex: 1 }}
318+
width={40}
319+
name="name"
320+
>
317321
{columnNames.name}
318322
</Th>
319-
<Th sort={{ sortBy, onSort, columnIndex: 2 }} name="date">
323+
<Th
324+
sort={{ sortBy, onSort, columnIndex: 2 }}
325+
width={20}
326+
name="date"
327+
>
320328
{columnNames.date}
321329
</Th>
322-
<Th name="owner">{columnNames.owner}</Th>
323-
<Th name="size">{columnNames.size}</Th>
330+
<Th name="owner">
331+
{columnNames.owner} width={20}
332+
</Th>
333+
<Th name="size">
334+
{columnNames.size} width={20}
335+
</Th>
324336
</Tr>
325337
</Thead>
326338
<Tbody>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React, { useRef, useEffect, useState } from "react";
2+
import { Tooltip } from "@patternfly/react-core";
3+
4+
interface TruncatedTextProps {
5+
text: string;
6+
className?: string;
7+
}
8+
9+
const TruncatedText: React.FC<TruncatedTextProps> = React.memo(
10+
({ text, className }) => {
11+
const textRef = useRef<HTMLSpanElement>(null);
12+
const [isTruncated, setIsTruncated] = useState(false);
13+
useEffect(() => {
14+
const { current } = textRef;
15+
/*
16+
clientWidth: Represents the inner width of an element (excluding borders and scrollbars). It's essentially the width available for the content.
17+
scrollWidth: Represents the total width of the element's content, including the portion not visible on the screen due to overflow.
18+
* */
19+
if (current) {
20+
setIsTruncated(current.scrollWidth > current.clientWidth);
21+
}
22+
}, []);
23+
24+
return (
25+
<Tooltip content={text} isVisible={isTruncated} trigger="mouseenter">
26+
<span ref={textRef} className={className}>
27+
{text}
28+
</span>
29+
</Tooltip>
30+
);
31+
},
32+
);
33+
34+
export default TruncatedText;

0 commit comments

Comments
 (0)