Skip to content

Commit 6688cbd

Browse files
committed
layout improvements
1 parent 6a6443a commit 6688cbd

File tree

1 file changed

+47
-25
lines changed

1 file changed

+47
-25
lines changed

website/src/components/Submission/FileUpload/ColumnMappingModal.tsx

+47-25
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export const ColumnMappingModal: FC<ColumnMappingModalProps> = ({
7575

7676
const openModalButtonText = columnMapping !== null ? 'Edit column mapping' : 'Add column mapping';
7777
const saveButtonText = columnMapping === null ? 'Add this mapping' : 'Save';
78+
const minWidthStyle = calculateMinWidthStyleFromPossibleOptions(groupedInputFields);
7879

7980
return (
8081
<>
@@ -101,8 +102,8 @@ export const ColumnMappingModal: FC<ColumnMappingModalProps> = ({
101102
<table>
102103
<thead>
103104
<tr>
104-
<th className='pr-12 py-2'>Column in your file</th>
105-
<th className='min-w-56'>Submission column</th>
105+
<th className='pr-16 py-2'>Column in your file</th>
106+
<th style={minWidthStyle}>Submission column</th>
106107
</tr>
107108
</thead>
108109
<tbody>
@@ -184,10 +185,39 @@ export const ColumnSelectorRow: FC<ColumnSelectorRowProps> = ({
184185
: undefined;
185186
const selectedOptionText = selectedField?.displayName ?? selectedField?.name;
186187

188+
const minWidthStyle = calculateMinWidthStyleFromPossibleOptions(options);
189+
190+
const inputFieldToListboxOption = (header: string, field: InputField): React.JSX.Element => (
191+
<ListboxOption
192+
key={`${header}-${field.name}`}
193+
value={field.name}
194+
className={`data-[focus]:bg-primary-200 p-1 pl-3 rounded-sm ${selectedOption === field.name ? 'bg-gray-200' : ''}`}
195+
data-tooltip-id={`${header}-${field.name}-tooltip`}
196+
>
197+
<span className={usedOptions.includes(field.name) ? 'text-gray-400' : ''}>
198+
{field.displayName ?? field.name}
199+
</span>
200+
{(field.definition ?? field.guidance) && (
201+
<Tooltip
202+
id={`${header}-${field.name}-tooltip`}
203+
place='right'
204+
positionStrategy='fixed'
205+
className='z-20 max-w-80 space-y-2'
206+
>
207+
<p>
208+
<span className='font-mono font-semibold text-gray-300'>{field.name}</span>
209+
</p>
210+
{field.definition && <p>{field.definition}</p>}
211+
{field.guidance && <p>{field.guidance}</p>}
212+
</Tooltip>
213+
)}
214+
</ListboxOption>
215+
);
216+
187217
return (
188218
<tr key={selectingFor} className='border-gray-400 border-solid border-x-0 border-y'>
189219
<td className='pr-4'>{selectingFor}</td>
190-
<td>
220+
<td style={minWidthStyle}>
191221
<Listbox
192222
value={selectedOption}
193223
onChange={(newValue) =>
@@ -220,28 +250,7 @@ export const ColumnSelectorRow: FC<ColumnSelectorRowProps> = ({
220250
return (
221251
<div key={header} className='pt-1'>
222252
<div className='p-1 font-semibold'>{header}</div>
223-
{fields.map((field) => (
224-
<ListboxOption
225-
key={`${header}-${field.name}`}
226-
value={field.name}
227-
className='data-[focus]:bg-primary-200 p-1 pl-3 rounded-sm'
228-
data-tooltip-id={`${header}-${field.name}-tooltip`}
229-
>
230-
<span className={usedOptions.includes(field.name) ? 'text-gray-400' : ''}>
231-
{field.displayName ?? field.name}
232-
</span>
233-
{(field.definition ?? field.guidance) && (
234-
<Tooltip
235-
id={`${header}-${field.name}-tooltip`}
236-
place='right'
237-
positionStrategy='fixed'
238-
className='z-20 max-w-80'
239-
>
240-
{field.definition} {field.guidance}
241-
</Tooltip>
242-
)}
243-
</ListboxOption>
244-
))}
253+
{fields.map((field) => inputFieldToListboxOption(header, field))}
245254
</div>
246255
);
247256
})}
@@ -251,3 +260,16 @@ export const ColumnSelectorRow: FC<ColumnSelectorRowProps> = ({
251260
</tr>
252261
);
253262
};
263+
264+
/* Estimate the min width of a column with select for these input fields,
265+
* so you don't get layout shifts when selecting different, longer, values. */
266+
function calculateMinWidthStyleFromPossibleOptions(options: Map<string, InputField[]>): React.CSSProperties {
267+
const maxOptionTextLength = Math.max(
268+
...Array.from(options.values())
269+
.flat()
270+
.flatMap((x) => [x.name, x.displayName])
271+
.map((text) => text?.length ?? 0),
272+
);
273+
274+
return { minWidth: `${Math.ceil(maxOptionTextLength / 2) + 2}rem` };
275+
}

0 commit comments

Comments
 (0)