|
1 | | -import React, { useMemo } from 'react'; |
| 1 | +import React, { useMemo, useRef, useEffect } from 'react'; |
2 | 2 | import { |
3 | 3 | css, |
4 | 4 | Table, |
|
7 | 7 | Cell, |
8 | 8 | cx, |
9 | 9 | spacing, |
| 10 | + uiColors, |
10 | 11 | } from '@mongodb-js/compass-components'; |
11 | 12 |
|
12 | 13 | import NameField from './name-field'; |
@@ -60,20 +61,31 @@ const nameFieldStyles = css({ |
60 | 61 | paddingBottom: spacing[2], |
61 | 62 | }); |
62 | 63 |
|
| 64 | +const tableStyles = css({ |
| 65 | + thead: { |
| 66 | + position: 'sticky', |
| 67 | + top: 0, |
| 68 | + background: uiColors.white, |
| 69 | + zIndex: 1, |
| 70 | + }, |
| 71 | +}); |
| 72 | + |
63 | 73 | type IndexesTableProps = { |
64 | | - darkMode?: boolean; |
65 | 74 | indexes: IndexDefinition[]; |
66 | 75 | canDeleteIndex: boolean; |
| 76 | + scrollHeight: number; |
67 | 77 | onSortTable: (column: SortColumn, direction: SortDirection) => void; |
68 | 78 | onDeleteIndex: (index: IndexDefinition) => void; |
69 | 79 | }; |
70 | 80 |
|
71 | 81 | export const IndexesTable: React.FunctionComponent<IndexesTableProps> = ({ |
72 | 82 | indexes, |
73 | 83 | canDeleteIndex, |
| 84 | + scrollHeight, |
74 | 85 | onSortTable, |
75 | 86 | onDeleteIndex, |
76 | 87 | }) => { |
| 88 | + const containerRef = useRef<HTMLDivElement>(null); |
77 | 89 | const columns = useMemo(() => { |
78 | 90 | const sortColumns: SortColumn[] = [ |
79 | 91 | 'Name and Definition', |
@@ -102,57 +114,73 @@ export const IndexesTable: React.FunctionComponent<IndexesTableProps> = ({ |
102 | 114 | return _columns; |
103 | 115 | }, [canDeleteIndex, onSortTable]); |
104 | 116 |
|
| 117 | + useEffect(() => { |
| 118 | + /** |
| 119 | + * For table header to be sticky, the wrapper element of table needs to have a height. |
| 120 | + * LG wraps table in a div at multiple levels, so height can not be direclty applied to the wrapper we use. |
| 121 | + */ |
| 122 | + const container = |
| 123 | + containerRef.current?.getElementsByTagName('table')[0]?.parentElement; |
| 124 | + if (container) { |
| 125 | + container.style.height = `${scrollHeight}px`; |
| 126 | + } |
| 127 | + }, [scrollHeight]); |
| 128 | + |
105 | 129 | return ( |
106 | | - <Table |
107 | | - data={indexes} |
108 | | - columns={columns} |
109 | | - data-testid="indexes-list" |
110 | | - aria-label="Indexes List Table" |
111 | | - > |
112 | | - {({ datum: index }) => ( |
113 | | - <Row |
114 | | - key={index.name} |
115 | | - data-testid={`index-row-${index.name}`} |
116 | | - className={rowStyles} |
117 | | - > |
118 | | - <Cell data-testid="index-name-field" className={cellStyles}> |
119 | | - <div className={nameFieldStyles}> |
120 | | - <NameField name={index.name} keys={index.fields.serialize()} /> |
121 | | - </div> |
122 | | - </Cell> |
123 | | - <Cell data-testid="index-type-field" className={cellStyles}> |
124 | | - <TypeField type={index.type} extra={index.extra} /> |
125 | | - </Cell> |
126 | | - <Cell data-testid="index-size-field" className={cellStyles}> |
127 | | - <SizeField size={index.size} relativeSize={index.relativeSize} /> |
128 | | - </Cell> |
129 | | - <Cell data-testid="index-usage-field" className={cellStyles}> |
130 | | - <UsageField usage={index.usageCount} since={index.usageSince} /> |
131 | | - </Cell> |
132 | | - <Cell data-testid="index-property-field" className={cellStyles}> |
133 | | - <PropertyField |
134 | | - cardinality={index.cardinality} |
135 | | - extra={index.extra} |
136 | | - properties={index.properties} |
137 | | - /> |
138 | | - </Cell> |
139 | | - {/* Delete column is conditional */} |
140 | | - {canDeleteIndex && ( |
141 | | - <Cell data-testid="index-actions-field" className={cellStyles}> |
142 | | - {index.name !== '_id_' && index.extra.status !== 'inprogress' && ( |
143 | | - <div |
144 | | - className={cx(indexActionsCellStyles, 'index-actions-cell')} |
145 | | - > |
146 | | - <IndexActions |
147 | | - index={index} |
148 | | - onDeleteIndex={onDeleteIndex} |
149 | | - ></IndexActions> |
150 | | - </div> |
151 | | - )} |
| 130 | + // LG table does not forward ref |
| 131 | + <div ref={containerRef}> |
| 132 | + <Table |
| 133 | + className={tableStyles} |
| 134 | + data={indexes} |
| 135 | + columns={columns} |
| 136 | + data-testid="indexes-list" |
| 137 | + aria-label="Indexes List Table" |
| 138 | + > |
| 139 | + {({ datum: index }) => ( |
| 140 | + <Row |
| 141 | + key={index.name} |
| 142 | + data-testid={`index-row-${index.name}`} |
| 143 | + className={rowStyles} |
| 144 | + > |
| 145 | + <Cell data-testid="index-name-field" className={cellStyles}> |
| 146 | + <div className={nameFieldStyles}> |
| 147 | + <NameField name={index.name} keys={index.fields.serialize()} /> |
| 148 | + </div> |
| 149 | + </Cell> |
| 150 | + <Cell data-testid="index-type-field" className={cellStyles}> |
| 151 | + <TypeField type={index.type} extra={index.extra} /> |
| 152 | + </Cell> |
| 153 | + <Cell data-testid="index-size-field" className={cellStyles}> |
| 154 | + <SizeField size={index.size} relativeSize={index.relativeSize} /> |
| 155 | + </Cell> |
| 156 | + <Cell data-testid="index-usage-field" className={cellStyles}> |
| 157 | + <UsageField usage={index.usageCount} since={index.usageSince} /> |
| 158 | + </Cell> |
| 159 | + <Cell data-testid="index-property-field" className={cellStyles}> |
| 160 | + <PropertyField |
| 161 | + cardinality={index.cardinality} |
| 162 | + extra={index.extra} |
| 163 | + properties={index.properties} |
| 164 | + /> |
152 | 165 | </Cell> |
153 | | - )} |
154 | | - </Row> |
155 | | - )} |
156 | | - </Table> |
| 166 | + {/* Delete column is conditional */} |
| 167 | + {canDeleteIndex && ( |
| 168 | + <Cell data-testid="index-actions-field" className={cellStyles}> |
| 169 | + {index.name !== '_id_' && index.extra.status !== 'inprogress' && ( |
| 170 | + <div |
| 171 | + className={cx(indexActionsCellStyles, 'index-actions-cell')} |
| 172 | + > |
| 173 | + <IndexActions |
| 174 | + index={index} |
| 175 | + onDeleteIndex={onDeleteIndex} |
| 176 | + ></IndexActions> |
| 177 | + </div> |
| 178 | + )} |
| 179 | + </Cell> |
| 180 | + )} |
| 181 | + </Row> |
| 182 | + )} |
| 183 | + </Table> |
| 184 | + </div> |
157 | 185 | ); |
158 | 186 | }; |
0 commit comments