99 spacing ,
1010 palette ,
1111 IndexKeysBadge ,
12+ KeylineCard ,
13+ useDOMRect ,
1214} from '@mongodb-js/compass-components' ;
1315
1416import TypeField from './type-field' ;
@@ -69,10 +71,19 @@ const tableStyles = css({
6971 } ,
7072} ) ;
7173
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+
7284type IndexesTableProps = {
7385 indexes : IndexDefinition [ ] ;
7486 canModifyIndex : boolean ;
75- scrollHeight : number ;
7687 serverVersion : string ;
7788 onSortTable : ( column : SortColumn , direction : SortDirection ) => void ;
7889 onDeleteIndex : ( index : IndexDefinition ) => void ;
@@ -83,14 +94,14 @@ type IndexesTableProps = {
8394export const IndexesTable : React . FunctionComponent < IndexesTableProps > = ( {
8495 indexes,
8596 canModifyIndex,
86- scrollHeight,
8797 serverVersion,
8898 onSortTable,
8999 onDeleteIndex,
90100 onHideIndex,
91101 onUnhideIndex,
92102} ) => {
93- const containerRef = useRef < HTMLDivElement > ( null ) ;
103+ const cardRef = useRef < HTMLDivElement > ( null ) ;
104+ const [ rectProps , { height : availableHeightInContainer } ] = useDOMRect ( ) ;
94105 const columns = useMemo ( ( ) => {
95106 const sortColumns : SortColumn [ ] = [
96107 'Name and Definition' ,
@@ -121,80 +132,111 @@ export const IndexesTable: React.FunctionComponent<IndexesTableProps> = ({
121132
122133 useEffect ( ( ) => {
123134 /**
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.
126139 */
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` ;
131165 }
132- } , [ scrollHeight ] ) ;
166+ } , [ availableHeightInContainer ] ) ;
133167
134168 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 } />
185198 </ 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+ />
193205 </ 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 >
194236 </ Row >
195- </ Row >
196- ) }
197- </ Table >
237+ ) }
238+ </ Table >
239+ </ KeylineCard >
198240 </ div >
199241 ) ;
200242} ;
0 commit comments