From 93c815f3a704616ea0633f353adf3b966a24c2d5 Mon Sep 17 00:00:00 2001 From: Lukas Wallrich Date: Fri, 9 Oct 2026 09:30:35 +0100 Subject: [PATCH 1/3] Keep Browse identifiers on one line and widen title columns The desktop Browse table broke DOIs mid-token across several lines (overflow-wrap: anywhere in narrow 12% columns), while titles were squeezed into 20% columns. - Titles wrap only between words; title columns widen to 22%. - DOI and report-link cells stay on one line with an ellipsis; the full value remains in the link, its tooltip, the evidence row and the CSV. - DataTables autoWidth is off so the declared widths apply and the table fits its container; headers no longer break mid-word. At 1280px: mean row height 96 -> 85px; no table overflow. Co-Authored-By: Claude Opus 5.5 --- assets/app.js | 16 ++++++++++------ assets/styles.css | 6 +++++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/assets/app.js b/assets/app.js index f6a4e8c9..d966f095 100644 --- a/assets/app.js +++ b/assets/app.js @@ -259,7 +259,11 @@ function formatUrlOrDoi(url, doi) { if (href) return `${escapeHtml(truncateText(url,40))}`; return formatDOI(doi,true); } -function formatUrlOrDoiShort(url, doi) { return formatUrlOrDoi(url,doi); } +function formatUrlOrDoiShort(url, doi) { + const href = safeHref(url); + if (href) return `${escapeHtml(url.replace(/^https?:\/\/(www\.)?/i, ''))}`; + return formatDOI(doi, true); +} function formatAuthors(authorData) { if (!authorData) return '-'; @@ -720,22 +724,22 @@ function initDataTable(data) { row.year_r || '-', { display: getOutcomeBadgeShort(row.outcome), search: `${row.outcome || ''} ${row.outcome_quote || ''}` }, truncateText(row.type, 15) || '-', - { display: formatDOI(row.doi_o), search: row.doi_o || '' }, + { display: formatDOI(row.doi_o, true), search: row.doi_o || '' }, { display: formatUrlOrDoiShort(row.url_r, row.doi_r), search: `${row.url_r || ''} ${row.doi_r || ''}` } ]); dataTable = $('#flora-table').DataTable({ - data: tableData, responsive: false, pageLength: 25, dom: 'lrtip', + data: tableData, responsive: false, autoWidth: false, pageLength: 25, dom: 'lrtip', lengthMenu: [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]], order: [[4, 'desc']], language: { search: "Search:", searchPlaceholder: "Filter studies (searches full references)..." }, columnDefs: [ { targets: 0, className: 'details-control', orderable: false, data: null, defaultContent: '', width: '30px' }, - { targets: [1, 3], width: '20%', render: (d, t) => t === 'display' ? (typeof d === 'object' ? d.display : d) : (typeof d === 'object' ? d.search : d) }, + { targets: [1, 3], width: '22%', render: (d, t) => t === 'display' ? (typeof d === 'object' ? d.display : d) : (typeof d === 'object' ? d.search : d) }, { targets: [2, 4], width: '5%' }, { targets: 5, width: '9%', render: (d, t) => t === 'display' ? (typeof d === 'object' ? d.display : d) : (typeof d === 'object' ? d.search : d) }, - { targets: 6, width: '6%' }, - { targets: [7, 8], width: '12%', render: (d, t) => t === 'display' ? (typeof d === 'object' ? d.display : d) : (typeof d === 'object' ? d.search : d) } + { targets: 6, width: '8%' }, + { targets: [7, 8], width: '14%', className: 'link-cell', render: (d, t) => t === 'display' ? (typeof d === 'object' ? d.display : d) : (typeof d === 'object' ? d.search : d) } ], createdRow: (row, d, dataIndex) => { $(row).attr('data-index', dataIndex); row.querySelector('.study-details').setAttribute('aria-label', 'Show evidence for ' + (data[dataIndex].title_o || 'original report')); } }); diff --git a/assets/styles.css b/assets/styles.css index 42699312..1f751fd7 100644 --- a/assets/styles.css +++ b/assets/styles.css @@ -413,7 +413,11 @@ tr.shown td.details-control .study-details::before { transform: rotate(90deg); } /* Browse mobile */ .browse-desktop { display: block; overflow-x: auto; } .browse-desktop #flora-table { table-layout: fixed; } -.browse-desktop #flora-table td, .browse-desktop #flora-table th { word-wrap: break-word; overflow-wrap: anywhere; } +/* Text wraps between words; identifiers stay on one line and are shortened + with an ellipsis (full value in the link, its tooltip and the evidence row). */ +.browse-desktop #flora-table td, .browse-desktop #flora-table th { overflow-wrap: break-word; } +.browse-desktop #flora-table th { overflow-wrap: normal; } +.browse-desktop #flora-table td.link-cell { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .browse-desktop #flora-table .badge { display: inline-block; max-width: 100%; white-space: normal; word-break: break-word; text-align: left; line-height: 1.3; } .browse-mobile { display: none; } .browse-mobile-search { margin-bottom: 1rem; } From 800fae162dbc311b6a2c53f1b7a00675fe99350a Mon Sep 17 00:00:00 2001 From: Lukas Wallrich Date: Fri, 9 Oct 2026 13:23:13 +0100 Subject: [PATCH 2/3] Fit Browse widths to 100%, keep link focus visible, wrap evidence links Addresses the cubic review of this PR: - Column widths now sum to exactly 100% (details column 3%, link columns 13%), so the fixed layout cannot exceed its container. - The link inside each ellipsis cell carries its own ellipsis and an inset focus outline, so the keyboard focus ring is not clipped. - The expanded evidence row wraps full URLs/DOIs anywhere again, so long identifiers cannot push it wider than the cell. - At narrow desktop widths the Type and outcome labels hyphenate (replica-tion) instead of breaking mid-syllable. Co-Authored-By: Claude Opus 5.5 --- assets/app.js | 6 +++--- assets/styles.css | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/assets/app.js b/assets/app.js index d966f095..001b8f61 100644 --- a/assets/app.js +++ b/assets/app.js @@ -734,12 +734,12 @@ function initDataTable(data) { order: [[4, 'desc']], language: { search: "Search:", searchPlaceholder: "Filter studies (searches full references)..." }, columnDefs: [ - { targets: 0, className: 'details-control', orderable: false, data: null, defaultContent: '', width: '30px' }, + { targets: 0, className: 'details-control', orderable: false, data: null, defaultContent: '', width: '3%' }, { targets: [1, 3], width: '22%', render: (d, t) => t === 'display' ? (typeof d === 'object' ? d.display : d) : (typeof d === 'object' ? d.search : d) }, { targets: [2, 4], width: '5%' }, { targets: 5, width: '9%', render: (d, t) => t === 'display' ? (typeof d === 'object' ? d.display : d) : (typeof d === 'object' ? d.search : d) }, - { targets: 6, width: '8%' }, - { targets: [7, 8], width: '14%', className: 'link-cell', render: (d, t) => t === 'display' ? (typeof d === 'object' ? d.display : d) : (typeof d === 'object' ? d.search : d) } + { targets: 6, width: '8%', className: 'type-cell' }, + { targets: [7, 8], width: '13%', className: 'link-cell', render: (d, t) => t === 'display' ? (typeof d === 'object' ? d.display : d) : (typeof d === 'object' ? d.search : d) } ], createdRow: (row, d, dataIndex) => { $(row).attr('data-index', dataIndex); row.querySelector('.study-details').setAttribute('aria-label', 'Show evidence for ' + (data[dataIndex].title_o || 'original report')); } }); diff --git a/assets/styles.css b/assets/styles.css index 1f751fd7..c310f6d8 100644 --- a/assets/styles.css +++ b/assets/styles.css @@ -416,8 +416,16 @@ tr.shown td.details-control .study-details::before { transform: rotate(90deg); } /* Text wraps between words; identifiers stay on one line and are shortened with an ellipsis (full value in the link, its tooltip and the evidence row). */ .browse-desktop #flora-table td, .browse-desktop #flora-table th { overflow-wrap: break-word; } +/* Narrow desktop widths: the short Type and outcome labels hyphenate instead of breaking mid-syllable. */ +.browse-desktop #flora-table td.type-cell, .browse-desktop #flora-table .badge { hyphens: auto; } .browse-desktop #flora-table th { overflow-wrap: normal; } .browse-desktop #flora-table td.link-cell { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +/* The link itself carries the ellipsis so its focus ring can sit inside the clipped cell. */ +.browse-desktop #flora-table td.link-cell a { display: block; overflow: hidden; text-overflow: ellipsis; } +.browse-desktop #flora-table td.link-cell a:focus-visible { outline-offset: -3px; } +/* The expanded evidence row shows full URLs and DOIs; let them wrap anywhere. */ +.browse-desktop #flora-table .detail-row { overflow-wrap: anywhere; } +.browse-desktop #flora-table .detail-grid > * { min-width: 0; } .browse-desktop #flora-table .badge { display: inline-block; max-width: 100%; white-space: normal; word-break: break-word; text-align: left; line-height: 1.3; } .browse-mobile { display: none; } .browse-mobile-search { margin-bottom: 1rem; } From 3a2e4ae6ce3a6d965023052e2cc4d50de38bd625 Mon Sep 17 00:00:00 2001 From: Lukas Wallrich Date: Fri, 9 Oct 2026 13:29:37 +0100 Subject: [PATCH 3/3] Add -webkit-hyphens for older Safari (cubic review) Co-Authored-By: Claude Opus 5.5 --- assets/styles.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/styles.css b/assets/styles.css index c310f6d8..2566ee50 100644 --- a/assets/styles.css +++ b/assets/styles.css @@ -417,7 +417,7 @@ tr.shown td.details-control .study-details::before { transform: rotate(90deg); } with an ellipsis (full value in the link, its tooltip and the evidence row). */ .browse-desktop #flora-table td, .browse-desktop #flora-table th { overflow-wrap: break-word; } /* Narrow desktop widths: the short Type and outcome labels hyphenate instead of breaking mid-syllable. */ -.browse-desktop #flora-table td.type-cell, .browse-desktop #flora-table .badge { hyphens: auto; } +.browse-desktop #flora-table td.type-cell, .browse-desktop #flora-table .badge { -webkit-hyphens: auto; hyphens: auto; } .browse-desktop #flora-table th { overflow-wrap: normal; } .browse-desktop #flora-table td.link-cell { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* The link itself carries the ellipsis so its focus ring can sit inside the clipped cell. */