Skip to content

fix: visual defects in tables, dropdowns and the table of contents - #2

Open
l-limon-l wants to merge 1 commit into
tickcount:masterfrom
l-limon-l:fix/visual-defects
Open

fix: visual defects in tables, dropdowns and the table of contents#2
l-limon-l wants to merge 1 commit into
tickcount:masterfrom
l-limon-l:fix/visual-defects

Conversation

@l-limon-l

Copy link
Copy Markdown

Hi! Thanks for this theme — I've been running it on my router and ended up fixing a batch of visual defects along the way. Sending them back in case they're useful.

Everything here was measured on a live OpenWrt 25.12 router (ASUS RT-AX52, LuCI 26.217) rather than eyeballed. I run LuCI in Russian, which is what surfaced most of these: longer words expose the places where the layout has no answer for overflow. The fixes are not locale-specific — English simply hides the same problems.

Scope: two source files only, .dev/src/media/main.css and .dev/src/resource/menu-outline.js. I have not rebuilt htdocs/ — your Build and Commit workflow regenerates it on push to master, and leaving it out keeps this diff reviewable.

Layout

Content column had a max-w-[720px] cap On a 2560px viewport that left 384px unused while LuCI's own tables overflowed their container
Empty TOC still reserved its gutter Another 304px of content width on pages that build no TOC
Tables placed directly in .cbi-section were clipped by nobody On the UPnP page a 933px table in a 752px column spilled 181px right, sliding under the fixed TOC

Typography and tables

  • word-break: break-alloverflow-wrap: anywhere. break-all splits every word at whatever character meets the edge — "Статический" wrapped as "Статическ / ий". anywhere breaks only what genuinely does not fit, and still lets a column shrink below its longest word, which is what break-all was there for.
  • Rows that wrap to several lines align every cell to the top. Middle alignment left short cells floating against a block of text; single-line rows render identically either way.
  • The DHCP leases table loses table-layout: fixed. It gave the actions column 107px for a 113px button — clipping "Reserve IP" — and left the table 5px wider than its box, i.e. a scrollbar with nothing to scroll.

Dropdowns

This was the largest piece. .cbi-dropdown is positioned by LuCI itself, .outline-select by the theme, so two dropdowns on one form behaved differently, and inside a modal the list was clipped by the modal's overflow box.

Both now share one positioner and render in the top layer via the Popover API:

  • pinned to the trigger in viewport coordinates, clamped to stay on screen
  • flipped above only when the panel truly does not fit below, decided from the panel's own height rather than a flat 200px guess that used to drop panels on top of their own field
  • followed per frame while open — scroll and resize handlers alone left a panel stranded at the top of the window while its field sat mid-page
  • handed back to LuCI on close. This one is subtle: LuCI swaps the dropdown and preview classes between its two <ul>s, so marking one as a popover permanently also caught the closed-state value display, which then floated free of the page (measured at x=3359 on a 2560px viewport).

.cbi-dropdown also gets the same chevron and the same 180° turn on open that .outline-select already had.

Table of contents

  • Entries read "System" instead of "SystemHide" — the collapse toggle LuCI puts inside section headings was being swept up with the title.
  • Sections that render empty (DSL on hardware without it) are no longer listed; their entry could not be scrolled to.
  • Every entry is now reachable. The highlight moved only once a section's top edge climbed past the header, which is impossible on a page that scrolls less than its sections are tall — the firewall page scrolls 470px while its second section starts at 796px and its third at 1081px. The fold now sits a third of the way down the viewport, and clicking an entry pins it for the length of the scroll.
  • The fixed panel measures its position after the entry list exists. Measuring earlier, while the gutter was still hidden, pinned it to the far left of the window.

Forms and lists

  • Form controls share a width floor, so a column of them no longer starts at six different offsets (measured 1048, 1112, 1140, 1190, 1225, 1297 down one page).
  • Select replacement and description placement observe document.body rather than #maincontent. LuCI mounts #modal_overlay on body, so selects inside modals kept their unstyled native look and field descriptions only moved into the label column once an unrelated poll mutated the page behind the modal — visible as the description jumping columns a moment after the modal opened.
  • List badges and interface boxes take their column's width instead of each sizing to its own content (badges measured 96, 138, 94 and 141px wide in one four-row table).
  • Firewall zone pairs keep their width on narrow screens instead of shrinking below their own badges.

Happy to split this into smaller PRs, drop any part you disagree with, or adjust to your preferences — just say the word.

Every change here was made against measurements taken on a live OpenWrt 25.12
router (ASUS RT-AX52, LuCI 26.217) with a Russian locale, which is what
surfaced most of these — longer words expose places where the layout has no
answer for overflow.

Layout

- Drop the 720px cap on the content column. On a 2560px viewport it left 384px
  of the available width unused while LuCI's own tables overflowed their
  container.
- An empty table of contents no longer reserves its gutter. Pages with fewer
  than two sections build no TOC, and holding the space regardless cost another
  304px of content width.
- Scroll wide tables that sit directly in a .cbi-section. Only the div-wrapped
  form was being clipped, so on the UPnP page a 933px table inside a 752px
  column spilled 181px to the right and slid under the fixed TOC.

Typography and tables

- Replace word-break: break-all with overflow-wrap: anywhere. break-all splits
  every word at whatever character meets the edge; "Статический" wrapped as
  "Статическ / ий". anywhere breaks only what genuinely does not fit.
- Align cells to the top in rows that wrap to several lines. Middle alignment
  left short cells floating against a block of text. Single-line rows are
  unaffected.
- Drop table-layout: fixed from the DHCP leases table. It handed the actions
  column 107px for a 113px button, clipping it, and left the table 5px wider
  than its box — a scrollbar with nothing to scroll.

Dropdowns

- .cbi-dropdown and .outline-select now share one positioner and both render in
  the top layer. Previously LuCI placed one and the theme placed the other, so
  two dropdowns on the same form behaved differently, and a list opened inside
  a modal was clipped by the modal's overflow box.
- Panels follow their trigger per frame while open. Scroll and resize events
  alone left them behind, stranding a panel at the top of the window while its
  field sat mid-page.
- Flip above the trigger only when the panel does not fit below, decided from
  the panel's own height rather than a flat 200px guess that dropped panels on
  top of their own field.
- Hand the list back on close. LuCI swaps the `dropdown` and `preview` classes
  between its two <ul>s, so marking one as a popover permanently also caught
  the closed-state value display, which then floated free of the page.
- Give .cbi-dropdown the same chevron and the same 180 degree turn on open that
  .outline-select has.

Table of contents

- Strip the inline controls LuCI puts inside section headings, so entries read
  "System" rather than "SystemHide".
- Skip sections that render empty, such as DSL on hardware without it. Their
  entry could not be scrolled to.
- Make every entry reachable. The highlight moved only when a section's top
  edge climbed past the header, which cannot happen on a page that scrolls less
  than its sections are tall: the firewall page scrolls 470px while its second
  section starts at 796px. The fold now sits a third of the way down the
  viewport, and clicking an entry pins it.
- Measure the fixed panel's position after the entry list exists. It was
  measured while the gutter was still hidden, which pinned the panel to the far
  left of the window.

Forms and lists

- Give form controls a shared width floor so a column of them no longer starts
  at six different offsets.
- Watch document.body rather than #maincontent for select replacement and
  description placement. LuCI mounts #modal_overlay on body, so selects inside
  modals kept their native look and descriptions only moved once an unrelated
  poll mutated the page behind the modal.
- Size list badges and interface boxes to their column instead of to their own
  content.
- Keep firewall zone pairs from shrinking below their own badges on narrow
  screens.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant