9
9
spacing ,
10
10
palette ,
11
11
IndexKeysBadge ,
12
+ KeylineCard ,
13
+ useDOMRect ,
12
14
} from '@mongodb-js/compass-components' ;
13
15
14
16
import TypeField from './type-field' ;
@@ -69,10 +71,19 @@ const tableStyles = css({
69
71
} ,
70
72
} ) ;
71
73
74
+ const cardStyles = css ( {
75
+ padding : spacing [ 3 ] ,
76
+ } ) ;
77
+
78
+ const spaceProviderStyles = css ( {
79
+ flex : 1 ,
80
+ position : 'relative' ,
81
+ overflow : 'hidden' ,
82
+ } ) ;
83
+
72
84
type IndexesTableProps = {
73
85
indexes : IndexDefinition [ ] ;
74
86
canModifyIndex : boolean ;
75
- scrollHeight : number ;
76
87
serverVersion : string ;
77
88
onSortTable : ( column : SortColumn , direction : SortDirection ) => void ;
78
89
onDeleteIndex : ( index : IndexDefinition ) => void ;
@@ -83,14 +94,14 @@ type IndexesTableProps = {
83
94
export const IndexesTable : React . FunctionComponent < IndexesTableProps > = ( {
84
95
indexes,
85
96
canModifyIndex,
86
- scrollHeight,
87
97
serverVersion,
88
98
onSortTable,
89
99
onDeleteIndex,
90
100
onHideIndex,
91
101
onUnhideIndex,
92
102
} ) => {
93
- const containerRef = useRef < HTMLDivElement > ( null ) ;
103
+ const cardRef = useRef < HTMLDivElement > ( null ) ;
104
+ const [ rectProps , { height : availableHeightInContainer } ] = useDOMRect ( ) ;
94
105
const columns = useMemo ( ( ) => {
95
106
const sortColumns : SortColumn [ ] = [
96
107
'Name and Definition' ,
@@ -121,80 +132,111 @@ export const IndexesTable: React.FunctionComponent<IndexesTableProps> = ({
121
132
122
133
useEffect ( ( ) => {
123
134
/**
124
- * For table header to be sticky, the wrapper element of table needs to have a height.
125
- * LG wraps table in a div at multiple levels, so height can not be direclty applied to the wrapper we use.
135
+ * For table header to be sticky, the wrapper element of table needs to have
136
+ * a height. LG wraps table in a div at multiple levels, so height can not
137
+ * be applied directly to the wrapper we have in this markup which is why we
138
+ * look for the parent element to apply the height.
126
139
*/
127
- const container =
128
- containerRef . current ?. getElementsByTagName ( 'table' ) [ 0 ] ?. parentElement ;
129
- if ( container ) {
130
- container . style . height = `${ scrollHeight } px` ;
140
+ const table = cardRef . current ?. getElementsByTagName ( 'table' ) [ 0 ] ;
141
+ const tableParent = table ?. parentElement ;
142
+
143
+ if ( table && tableParent ) {
144
+ // We add a top and bottom padding of spacing[3] and our root container
145
+ // has a bottom margin of spacing[3] which is why the actual usable
146
+ // height of the container is less than what we get here
147
+ const heightWithoutSpacing = availableHeightInContainer - spacing [ 3 ] * 3 ;
148
+
149
+ // This will be the height of the table. We take whichever is the max of
150
+ // the actual table height vs the half of the height available to make
151
+ // sure that our table does not always render in a super small keyline
152
+ // card when there are only a few rows in the table.
153
+ const tableHeight = Math . max (
154
+ table . clientHeight ,
155
+ heightWithoutSpacing / 2
156
+ ) ;
157
+
158
+ // When we have enough space available to render the table, we simply want
159
+ // our keyline card to have a height as much as that of the table content
160
+ const tableParentHeight = Math . max (
161
+ 0 ,
162
+ Math . min ( tableHeight , heightWithoutSpacing )
163
+ ) ;
164
+ tableParent . style . height = `${ tableParentHeight } px` ;
131
165
}
132
- } , [ scrollHeight ] ) ;
166
+ } , [ availableHeightInContainer ] ) ;
133
167
134
168
return (
135
- // LG table does not forward ref
136
- < div ref = { containerRef } >
137
- < Table
138
- className = { tableStyles }
139
- data = { indexes }
140
- columns = { columns }
141
- data-testid = "indexes-list"
142
- aria-label = "Indexes List Table"
143
- >
144
- { ( { datum : index } ) => (
145
- < Row
146
- key = { index . name }
147
- data-testid = { `index-row-${ index . name } ` }
148
- className = { rowStyles }
149
- >
150
- < Cell data-testid = "index-name-field" className = { cellStyles } >
151
- { index . name }
152
- </ Cell >
153
- < Cell data-testid = "index-type-field" className = { cellStyles } >
154
- < TypeField type = { index . type } extra = { index . extra } />
155
- </ Cell >
156
- < Cell data-testid = "index-size-field" className = { cellStyles } >
157
- < SizeField size = { index . size } relativeSize = { index . relativeSize } />
158
- </ Cell >
159
- < Cell data-testid = "index-usage-field" className = { cellStyles } >
160
- < UsageField usage = { index . usageCount } since = { index . usageSince } />
161
- </ Cell >
162
- < Cell data-testid = "index-property-field" className = { cellStyles } >
163
- < PropertyField
164
- cardinality = { index . cardinality }
165
- extra = { index . extra }
166
- properties = { index . properties }
167
- />
168
- </ Cell >
169
- { /* Index actions column is conditional */ }
170
- { canModifyIndex && (
171
- < Cell data-testid = "index-actions-field" className = { cellStyles } >
172
- { index . name !== '_id_' && index . extra . status !== 'inprogress' && (
173
- < div
174
- className = { cx ( indexActionsCellStyles , 'index-actions-cell' ) }
175
- >
176
- < IndexActions
177
- index = { index }
178
- serverVersion = { serverVersion }
179
- onDeleteIndex = { onDeleteIndex }
180
- onHideIndex = { onHideIndex }
181
- onUnhideIndex = { onUnhideIndex }
182
- > </ IndexActions >
183
- </ div >
184
- ) }
169
+ < div className = { spaceProviderStyles } { ...rectProps } >
170
+ < KeylineCard ref = { cardRef } data-testid = "indexes" className = { cardStyles } >
171
+ < Table
172
+ className = { tableStyles }
173
+ data = { indexes }
174
+ columns = { columns }
175
+ data-testid = "indexes-list"
176
+ aria-label = "Indexes List Table"
177
+ >
178
+ { ( { datum : index } ) => (
179
+ < Row
180
+ key = { index . name }
181
+ data-testid = { `index-row-${ index . name } ` }
182
+ className = { rowStyles }
183
+ >
184
+ < Cell data-testid = "index-name-field" className = { cellStyles } >
185
+ { index . name }
186
+ </ Cell >
187
+ < Cell data-testid = "index-type-field" className = { cellStyles } >
188
+ < TypeField type = { index . type } extra = { index . extra } />
189
+ </ Cell >
190
+ < Cell data-testid = "index-size-field" className = { cellStyles } >
191
+ < SizeField
192
+ size = { index . size }
193
+ relativeSize = { index . relativeSize }
194
+ />
195
+ </ Cell >
196
+ < Cell data-testid = "index-usage-field" className = { cellStyles } >
197
+ < UsageField usage = { index . usageCount } since = { index . usageSince } />
185
198
</ Cell >
186
- ) }
187
- < Row >
188
- < Cell
189
- className = { cx ( nestedRowCellStyles , cellStyles ) }
190
- colSpan = { canModifyIndex ? 6 : 5 }
191
- >
192
- < IndexKeysBadge keys = { index . fields } />
199
+ < Cell data-testid = "index-property-field" className = { cellStyles } >
200
+ < PropertyField
201
+ cardinality = { index . cardinality }
202
+ extra = { index . extra }
203
+ properties = { index . properties }
204
+ />
193
205
</ Cell >
206
+ { /* Index actions column is conditional */ }
207
+ { canModifyIndex && (
208
+ < Cell data-testid = "index-actions-field" className = { cellStyles } >
209
+ { index . name !== '_id_' &&
210
+ index . extra . status !== 'inprogress' && (
211
+ < div
212
+ className = { cx (
213
+ indexActionsCellStyles ,
214
+ 'index-actions-cell'
215
+ ) }
216
+ >
217
+ < IndexActions
218
+ index = { index }
219
+ serverVersion = { serverVersion }
220
+ onDeleteIndex = { onDeleteIndex }
221
+ onHideIndex = { onHideIndex }
222
+ onUnhideIndex = { onUnhideIndex }
223
+ > </ IndexActions >
224
+ </ div >
225
+ ) }
226
+ </ Cell >
227
+ ) }
228
+ < Row >
229
+ < Cell
230
+ className = { cx ( nestedRowCellStyles , cellStyles ) }
231
+ colSpan = { canModifyIndex ? 6 : 5 }
232
+ >
233
+ < IndexKeysBadge keys = { index . fields } />
234
+ </ Cell >
235
+ </ Row >
194
236
</ Row >
195
- </ Row >
196
- ) }
197
- </ Table >
237
+ ) }
238
+ </ Table >
239
+ </ KeylineCard >
198
240
</ div >
199
241
) ;
200
242
} ;
0 commit comments