Skip to content

webui: one design system across the app - #129

Open
zelfroster wants to merge 22 commits into
RetroShare:masterfrom
zelfroster:feat/design-system
Open

zelfroster wants to merge 22 commits into
RetroShare:masterfrom
zelfroster:feat/design-system

Conversation

@zelfroster

@zelfroster zelfroster commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #121. Makes the whole web UI look like one app.

Design

  • One set of colours, sizes and spacing, used everywhere.
  • One button, card, modal, tab, search box and side rail, instead of 57 card styles and 48 button styles.
  • All inputs, dropdowns and buttons are now the same height.
  • Font Awesome replaced with 132 Phosphor icons in one sprite.
  • Roboto and the icon font dropped. Archivo and DM Mono ship as 3 local files.

Mail

  • Drafts work: save, reopen, finish, discard.
  • Click a column to sort. Third click resets.
  • New date/time and tags columns.
  • Attachment reminder if you mention one but forget to attach it.

Chat

  • One emoji picker everywhere, 946 emoji, search actually works.
  • Room details moved to a button so chat is the default view.

Files

  • Slimmer transfer rows.
  • My Files and Friends' Files share one table. Nested folders indent properly.

People, Network, Config, Boards, Channels, Forums, Statistics

  • All on the same side rail, page header and list styles.
  • People sidebar reworked: tabs and filter on one row.
  • Network and People had inline styles with their own colours. Moved to the stylesheet.

Bugs fixed along the way

  • Editing an identity erased its avatar. Deleting one left it in the list.
  • Channel list stopped refreshing after the first interval.
  • Chat messages could land in an invisible array, so a conversation looked one-way.
  • Text typed to one contact stayed in the box when you opened the next.
  • Drafts opened with Reply and Spam buttons that do not apply to them.
  • Channel posts were in no particular order.

Other

  • Mobile layouts reworked across the app.

Also includes the work from #33 and #34. Details in the commit message.

This carries the whole revamp, which had been sitting uncommitted: design
tokens, the Phosphor icon sprite replacing FontAwesome, one dropdown and
one field treatment, one emoji picker, the mail table (tri-state sort,
date & time, drafts) and the composer. Roboto and the FontAwesome webfont
are gone; Archivo and DM Mono ship as woff2.

It also settles the pull of RetroShare#33/RetroShare#34, which revamped the same screens in
parallel. The two approaches collided in the library sections, so the
reconciliation was done by hand rather than by the merge.

Ported from their commits, restyled on our tokens where they carried CSS:

  6f37dd1  channel posts newest-first, by mPublishTs
  47fb3dc  keyed channel cards and keyed recipient <li>s -- both needed:
           unkeyed, the newest-first sort makes mithril reuse DOM by
           position, so one post's onerror display:none sticks to
           whatever post shifts into that slot
  788ffbc  avatars and full GXS ids in the To/Cc/Bcc autocomplete, with
           the avatar fetch deferred to IntersectionObserver, and the
           identity tooltip anchored below the id instead of over the row
  5f35ca1  board post images on a media stage: object-fit contain, click
           or Enter opens the PhotoViewModal we already had. Their dark
           #0b0f19 stage, blurred ambient backdrop and drop shadows are
           not ported -- chrome here is a well and a hairline
  c45fc1e  the Debug mobile action row only: minmax(0, 1fr) so three
           buttons share the width, and a .debug-btn__suffix that leaves
           just the verb

Not ported, with reasons:

  c45fc1e  library_layout.js and _library.scss. 183 lines of #f1f5f9 /
           #cbd5e1 / #3ba4d7, box shadows and 700 weights, @use'd last so
           it overrode the token layer at every breakpoint. The nav-rail
           and list-pane mixins already do this job.
  c45fc1e  rails pinned to a flat 280px. Ours flex 250/230/280.
  c45fc1e  'New email' -> 'New mail' and 'Select an email' -> 'Select an
           mail', which reintroduced the typo b332299 had just fixed.
  731cceb  .chat-create-room-btn hard-coded to #3ba4d7. It is already
           btn-base + btn-strong, which renders the same thing.
  b332299  "All means all". There is no All tab on this branch -- the
           sections are My / Subscribed / Popular / Other -- so the
           Popular u Other merge it fixes does not exist here.
  c223473  library_layout props and icon swaps for that shell. Its
           Forums comments -> bullhorn is also a downgrade.
Mail
  Drafts had two definitions of "draft": the folder listed anything with
  the DRAFT bit, the reading pane asked for the exact DRAFTBOX value
  (OUTGOING|DRAFT). A draft the core had not also marked OUTGOING was
  listed and then opened with the Reply / Forward / Spam toolbar of a
  received mail. One predicate now, read by both.
  A draft is written by us, so an empty `from` means the core recorded no
  identity, not that the sender is a stranger -- it falls back to our
  first identity, which also fixes the "Sender is not known" sheet that
  Edit draft opened. Star and spam are judgements about mail someone sent
  you, so they are gone from draft rows and the Drafts folder drops both
  columns rather than heading blank cells.
  rs.userList.username() returns the id itself while its fetch is in
  flight and forever for an identity this node has never seen, so the To:
  chips and the From column were 32-character hex strings; identityLabel()
  shortens what it cannot name. Subjects: one subjectOf(), so the table
  says (No Subject) like the cards and the reading pane already did, and
  whitespace-only titles count as empty.
  Tags get a column of their own after Date, with the named badge the
  cards use -- lifted out of .mail-card-item so one badge serves all three.

Files
  My Files and Friends' Files are one tree treatment instead of the base
  table's centred 18px black headings. The twist moved into the name cell
  and the indent became padding: it was `position: relative; left:`, which
  moves the text and leaves every level's chevron in the same column.
  My Files tested `children !== undefined` for a folder, true for a file
  too, so every shared file wore a folder icon; a non-zero hash is the
  test. A friend's file in progress rendered the whole File card inside a
  table cell -- it is a percentage and an info tooltip now.
  Transfers: the chunk select used one `chunkTag` id on every row, the
  chunk bar was 32px to hold a centred percentage, and the stat icons were
  styled through `span > i`, which has matched nothing since Phosphor.
  Search: `.search-form { width: 40% }` on a shrink-to-fit flex item
  collapsed the field to a white square; the page header sizes it now, and
  the page has empty states instead of a bare "Results".

Tooltips
  Three implementations became one component. The hint was
  white-on-near-black with `margin-left: -120px` standing in for centring,
  undone again in two responsive blocks; the identity card was 53
  `!important` declarations on --warn-bg, the warning colour, for
  something that is not a warning. Both sit on one tip-surface mixin with
  a new --lift-sm. The !importants were beating UserAvatar's inline
  sizing, so the callers pass `size: 48` instead.

Also
  Statistics uses the shared rail like every other section, which needed
  Sidebar to work from local state as well as from the route; its refresh
  button had `.icon { display: none }`. Forum search was offset by a 250px
  margin left over from the old two-row header. Hovering the selected rail
  item repainted it: `.sidebar a:hover` is (0,2,1) and the selected rule
  was (0,2,0). Debug KPI cards no longer lift on hover -- they are
  readouts, not controls. Chat room info: the lobby id fits a column, the
  topic is a sentence, so they swap.
@zelfroster

Copy link
Copy Markdown
Contributor Author

@defnax @jolavillette I was working on this, and still will be pushing fixes to this.

Please try it out and let me know what more things need fix/improvement.

@defnax

defnax commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

not works on windows, howto install it

  1. add name: 'phosphor-name' to MAP in make-src/icon-map.js
  2. npm run icons:sync (installs the package, copies what is missing,
    removes it again)

@zelfroster

Copy link
Copy Markdown
Contributor Author

@defnax i was experimenting with it, removed it and its back to original way.

you have to once run npm install and then npm run build in webui-src

@defnax

defnax commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

ok its not to much light for your eyes its vey light
image
This contacts combobox will not fit on phone and by default it takes extra space (desktop/phone)
maybe i would use icon only for the selector box

@defnax

defnax commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

this is broken on phone
image

@defnax

defnax commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

channels thumbnails broken
image

@defnax

defnax commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

board on phone
image

phonebar
image

@defnax

defnax commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

the new buttons looks lots of better then the old one only phone ui is broken, i did lots of fixes for phone :)
not forget the dark theme too :)

@defnax

defnax commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

the new icons and new buttons realy nice like a new fresh webui :)

@defnax

defnax commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

on phone the compose layout takes more space
the file and image needs to be shipped toggether on phone mode
image

master
image

telegram web:
image
image

One back button everywhere a detail view can be left, replacing four
separate implementations across Forums, Boards, Channels and Mail. It is
part of the page header row now instead of taking a row of its own, so
PageHead gains a `back` attribute.

Forums and Channels listed the same thing with two copies of the same
table, so both now use one `.group-table` component.

formatTimestamp and getTimestampValue lived only in forums_util; moved to
rswebui so other sections use them instead of their own copies.

userList.username() printed the raw id for an unsigned post, whose author
id is all zeros. There is no identity to fetch, so it returns [Unknown].

Selection colours raised: the previous band measured 1.14:1 against the
surface behind it, which is below where a tint is reliably visible.
The thread list was read out of Data.Threads, a flat index of every post,
so every reply appeared as a thread of its own. It now starts from
Data.ParentThreads and walks each struct's replies, giving the tree the
hierarchy call already returned. Columns are Threads, Unread, Date and
Author, with replies indented and collapsible.

Unread was tested as `mMsgStatus === 3`. It is a bit, not a value
(GXS_MSG_STATUS_GUI_UNREAD = 0x02), so the column was permanently empty.

Selecting a thread fills a reading pane below the list instead of loading
a page, with previous, next and next-unread arrows. A post reached by link
opens its parent threads so its row is on screen. On a phone the reader
replaces the list, since two panes do not fit.

Forum details moved into a dropdown off the header: description,
subscribers, posts, last post, sync and storage windows, distribution,
owner and anti-spam, matching what the desktop client reports.

Each forum list row used to mount a component that fetched that forum's
info and its whole post hierarchy. All Forums with 98 forums meant 196
requests before the list could draw. The summaries already carry the name,
post count and last post, so the list makes none, and descriptions come
from one batched getForumsInfo.

All Forums was empty for two reasons: other_forums.js was a placeholder
returning "No forums to show", and getForums had no key for the tab.

Creating a forum or a thread left the modal open.
Channels uses the shared group table: icon, name, description, posts and
last post. Like Forums, each row used to fetch its own channel info, so
the list now renders from the summaries and takes descriptions from one
batched getChannelsInfo.

The channel header showed "Invalid Date" and "No Description" because
readChannel ran before the fetch resolved and nothing re-read it after.

A post card rendered the image and its fallback together, relying on the
hidden attribute to suppress the fallback; the placeholder's display rule
outranks it, so both drew. The card renders one or the other, with failed
thumbnails tracked in a set rather than by writing display:none onto the
DOM node. Cards also get an explicit column direction, a covering image
and a single-line title so a row of them ends level.

Boards and Channels detail headers use the shared page header, which drops
the row that held only a back arrow and lets the phone overflow menus sit
in the flow instead of being positioned against the panel.
Chat header buttons held 44px of content in a 32px box, so the labels ran
outside them; the labels are in spans the stylesheet can hide. The
participants sheet takes the full width on a phone rather than half the
viewport.

Overflow menus in Forums, Boards and Channels sized themselves from their
widest button, which btn-base keeps on one line, so a long label pushed
the panel off the side of the screen.

Mail date column and its header are left aligned like the subject beside
them, and the sender row can wrap.

Debug panels and tables can shrink below their content width, and the KPI
grid collapses to one column instead of overflowing at 320px.

Page headers wrap on the space they have rather than at a viewport
breakpoint, since each sits to the right of a 250px rail.
@defnax

defnax commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

what i like without the phone issues>

  • New Buttons ✅
  • New icons ✅
  • Phone menu for Settings/Files/Forums/Channels/Boards ✅

on master what i changed seems not so usefull on phone when it has more then 3 entries

@jolavillette

Copy link
Copy Markdown
Contributor

Thanks for the ping. Full disclosure before anything else: this is an AI-assisted audit (Claude, driven by me) — several independent review passes over the diff, then each claim re-verified against the sources before it made the list. Take it for what it is worth: the line references and the reasoning are checked, but do double-check anything before acting on it, and feel free to push back on any point — some "findings" may be deliberate choices on your side.

With that said: I read the whole diff (JS and SCSS) against master, rebuilt it (sass reproduces styles.css byte for byte, eslint clean, build.js --check passes), and cross-checked against the fixes that went into #121. The design-system half is a big net win: page hex colours 1159 → 0, ~1250 dead selectors gone, 4.4 MB of Roboto/FA replaced by 120 KB, and everything regenerates reproducibly. What follows is the list of things I would fix before merging, in the order I'd do them. Line numbers are on d21dc9e, paths under webui-src/.

Blocks a merge

  1. Every create/post/reply modal stays open after success, with the button live. On master the success path called widget.popupMessage([h3 'Success'…]), and popupMessage re-mounts #modal-container, so the form was replaced. The PR swaps that for toast.success() and nothing calls closePopupMessage() (its only callers on this branch are Cancel buttons). A second click creates a second channel / forum / board / post / thread / identity, or re-sends the friend certificate. Sites: channels/channel_view.js:271,414, forums/forum_view.js:151,478, boards/board_view.js:123,266, home.js:202,219, people/people_ownids.js:33,152,201,297, files/files_manager.js:67, files/files_downloads.js:97-114. Fix: widget.closePopupMessage() in every success branch before the toast.

  2. Mail drafts cannot be re-saved or finished. mail_compose.js:508-510 and :625-627 call MessageDelete on the previous draft id, but p3MsgService::MessageDelete (p3msgservice.cc:1319-1385) searches received/sent/trash/outgoing and never mDraftMessages, so it returns false: each re-save leaves a duplicate and a sent draft stays in Drafts forever. MessageToTrash does handle drafts (:2106-2114, it moves the item into trash and erases it from the draft box), so the fix is to chain MessageToTrash({msgId, bTrash: true})MessageDelete. The Discard path (mail_util.js:868-870) fires both concurrently and has the same race; chain it too. (The Qt composer has the same core limitation, I'll report it separately.)

  3. Mail identity lookups loop while the core is unreachable. mail_util.js:64-79 identityDetails() clears its in-flight marker before checking !data.details and caches nothing on failure; rsJsonApiRequest runs the callback on status 0 and m.request redraws, so failed request → redraw → identityLabel() → new request → … per unresolved address. This is the class of loop javascript not found #15 fixed. Also identityLabel consults identityDetails() before rs.userList.username(), and MessageCard.oninit (:474-508) still fires master's own fetch, so a first paint is two getIdDetails per sender the summaries already name. Fix: mark the address as tried on any answer, check username() first.

Regressions against #121

  1. "All" tab removed, "Other" relabelled "All …" (UI improvement && logic code for people Webpage #33). channels.js:58,66 labels the Other section "All Channels" while :31 still feeds it popular.slice(5) of the non-subscribed list, so "All Channels" hides every subscribed channel and the top five; getChannels.All (:23) is dead. Same for boards (boards.js:25,54,62); for forums the "All Forums" section renders "No forums to show" (other_forums.js:6). And /channels/All, /boards/All, /forums/All (the phone default tab on master, so in bookmarks) now hit m(undefined) at channels.js:134 / boards.js:125 / forums.js:126 — blank page. Restore an All section fed by getX.All, or rename the section and keep the route resolving.

  2. Channel thumbnails (defnax's screenshot). channel_view.js:51 relies on [hidden] to hide the "No image" placeholder, but no sheet has a [hidden] rule and _channel.scss:82-85 sets it display: flex, which beats the UA stylesheet. Add [hidden] { display: none !important } to _base.scss (or keep the inline display master used at :47).

  3. Distant chat: a removed attachment comes back. people_chat_tab.js:296 drops master's session.attachedImage = null; attachImage still writes the session and people_state.js:813 restores it on contact switch, so the picture you removed is sent with the next message after switching contacts.

  4. Ctrl/Cmd+Enter no longer inserts a newline in any chat: chat_composer.js:34-41 returns on any modifier. Master used execCommand('insertText', '\n') with a splice fallback on all three surfaces (master chat.js:604-613, people_chat_tab.js:437-452, network_chat_tab.js:364-380). enterkeyhint: 'send' was dropped too.

  5. In-channel post search is gone on desktop (channels.js:112-121 renders PageHead only when no channel is open; .channel-mobile-search is display: none outside ≤700 px, _channel.scss:478), and the forum in-thread search is gone on phones (_forums.scss:103-107 hides .forum-mobile-search and the ≤700 block at :276-280 no longer sets display: flex, unlike master :263).

  6. Forums/channels filter has no way back. forums_util.js:268 onclear calls updatedisplayforums() with no argument — that is the per-forum content loader, it POSTs getForumsInfo with forumIds: [null] and the isSearched flags set at :271-277 are never reset. And because the PageHead that hosts the search field is now unmounted on detail routes (forums.js:104, channels.js:114; master rendered .top-heading unconditionally), typing a query, opening a group and going back leaves the box empty while every non-matching group stays hidden (module state, forums_util.js:211, channels_util.js:191).

  7. Modal close buttons are 26×26 px on phones (Updated Readme for window #18): _mixins.scss:206-213 btn-close applies to every .close-btn/.modal__close; master's phone padding rule (_files.scss:498-500) is gone and --touch is never applied. Give them a 40–44 px box under @include touch.

defnax's phone list, located

  1. Phone header pill light-on-light: the header went var(--ink) on var(--chrome) (_navbar.scss:522-524) but .mobile-status-trigger keeps color: var(--line-soft) on rgba(255,255,255,.08) (:541-558): 1.2:1. Use --ink-dim / --sunken / --line.

  2. Composer: the ≤700 px File/Picture menu was deleted with the old JS (master chat.js:477-517), so chat_composer.js:86-113 now shows paperclip, image, emoji and a wide send side by side; the menu CSS at _chat.scss:1451-1492 and the closest('.mobile-chat-attachment') guards at chat.js:405, people_chat_tab.js:83, network_chat_tab.js:107 are dead. The strip itself is not taller than master (~47 vs ~51 px); what grew is the wide send button (btn-base padding with the label hidden) and the fifth header button.

  3. Emoji picker clipped on phones: .emoji-picker is absolute, 320 px, left: 0 on the third tool (~92 px in), inside overflow: hidden panes (_chat.scss:591-595, _network.scss:642-647, the latter also used by People). Master's ≤700 px rule (right: -2.7rem; width: min(320px, calc(100vw - 1rem)); max-height: min(420px, calc(100dvh - 8rem))) died with the old selectors; nothing touches .emoji-picker in a media query now. Same box overflows the 344 px forum composer modal.

  4. Boards on phone: _board.scss:1046-1056 keeps the detail widget as a three-row grid but dropped master's > .widget__heading { grid-area: 2 / 1 } and moved .widget__body to row 2, so the unplaced heading auto-places into row 3: back arrow, post list, then the board name and Subscribe button underneath (board_view.js:394,427,435 still emit the three children; channels have no explicit placement and are fine). Also the view toggle is a Segmented with labels always visible (board_kanban.js:459-468); master hid them at ≤768 px (_board.scss:256-258). With .board-toolbar__right { flex-shrink: 0 } the toolbar overflows a 360 px screen by ~50 px. **And the phone overflow menu's Subscribe/Unsubscribe item is button.is-danger unconditionally (forum_view.js:675, channel_view.js:516, board_view.js:417), so joining a group is a red button. Contacts combobox: the select now shares the tabs' row (people_sidebar.js:130-177, master had .sub-filter-row), has no width rule and flex: none, so it wraps to its own line even in the 250 px desktop pane.

  5. Too light: --ink-dim: #788d9c (_tokens.scss:41) is 3.45:1 on white, used 165 times at 12–13 px (AA needs 4.5:1; master's #64748b was 4.76:1). --brand as text/white-on-brand is 3.61:1. #5f7382 and #0b7cb2 pass on white (selected rows still need their own ink).

Emoji table

  1. chat_emoji.js:12-86 holds bare code points only (0 VS16, 0 ZWJ; master had 129/5). Net: 205 of master's emoji gone (❤️ ☕ ✔️ ☀️ ✈️ 🐻‍❄️ 🧑‍🎄 …), 21 demoted to monochrome text glyphs, 8 non-emoji code points that render as tofu everywhere (🛦 🛧 🛨 🛪 🛱 🛲 🥆 📾) plus two Emoji 16.0 ones, 25 that draw as outlines without VS16; the category icons ✈️/❤️ themselves are not insertable. Categories are Unicode blocks (🙈 in Smileys, 💐🤌 in Symbols). Search (:371-373) is a substring over raw Unicode names ("smile" → 😼 only, "sad"/"coffee"/"100" → nothing). Generating from emoji-test.txt (fully-qualified) with CLDR groups and annotations fixes all of it; 248 additions over master are welcome.

Build, a11y, misc

  1. npm run build now exits 1 without @phosphor-icons/core (icons.js:196-199), which is what hit defnax on Windows; warn and skip regeneration when the package is absent.
  2. widgets.js:280-288 document-level Escape closes any modal unconditionally, including composers with text (confirmMessage.onCancel is never called); skip when the target is a textarea/input or the modal is dirty.
  3. icon('external-link-alt') (home.js:43) and icon('user-friends', {duo: isId}) (friends_files.js:100-105, user-friends is not in STATEFUL) have no sprite symbol — blank icons.
  4. widget.Sidebar (widgets.js:123-141): <a> without href in onSelect mode (Statistics rail, not keyboard-operable; master had buttons) and href without m.route.prefix for the section links (middle-click / copy-link give a bare path; master used m.route.Link). Segmented has no arrow keys.
  5. _ui.scss (44 selectors) is unused except .empty, and it is the only place var(--touch) is applied, so real buttons get no touch enlargement; .icon--sm/md/lg/xl unused. Either migrate to it or delete it and put the touch rule in btn-base/field-base.
  6. For Dark mode #126: ~47 baked colours remain outside _tokens.scss (white in _chat.scss:55,60,67,95,122,199,249,298, _files.scss:670,770,839, _mail.scss:1621,1634, _login.scss:12, _widget.scss:7, _navbar.scss:377; gray/grey/green/silver/black/red; 23 rgba() literals; the select chevron data URI at _mixins.scss:279). With those tokenised, dark mode is one :root override.
  7. Mail: reopened drafts lose Bcc, attachments and identity (the core never stores from on drafts, so draftSenderId always falls back to the first own id — don't claim it); loadTagTypes (mail_util.js:185-196) reads res.body in callback form, so tag types never load (pre-existing, one-line fix res && res.tags && res.tags.types); SortState starts on date so the first click on Date unsorts; the attachment reminder trips on every forward (-----Forwarded Message-----/.original-message are not stripped, :427-441); saveDraft calls onDone() even on failure; table.mails { min-width: 720px } scrolls horizontally between 769 and ~1020 px.
  8. The PR body credits five fixes already on master (avatar on edit, delete refresh, channel list refresh, invisible message array, draft text per contact) — the diff only reworded the comments; and the Network friend chat still has one State.chatInputMsg for all peers. Worth an honest changelog.
  9. Small: no OFL/MIT notices shipped for Archivo, DM Mono and Phosphor; docs/design-system.html cited in three files does not exist; dead FA selectors and the .mobile-chat-attachment/lobby blocks; boards_util.js/channels_util.js search fields pass no onclear so they have no clear button; files_downloads.js:83 reports an error with toast.info; debug buttons lost their aria-labels (names collapse on phones); engines.node >= 24 is stricter than needed (everything reproduces on 18); Safari will paint its native search chrome inside .search-field until -webkit-appearance: none is on the input (new for the people/friends/transfers filters, which were type=text on master).

I checked that the #121 follow-ups not listed above are intact (channel batching, split-retry, freshVnode, dvh overlays, request-storm guards, 5-minute friend sweep cache, vote tally, keyed channel cards, mail unread/untrash/reload-loop fixes, statistics polls, inert-lock). Happy to send PRs against feat/design-system for 1, 4–10 and 13 if that helps.

@zelfroster

Copy link
Copy Markdown
Contributor Author

@jolavillette feel free to send PRs for improvements, would be very helpful

jolavillette and others added 4 commits September 16, 2026 03:08
On master every create/post/add form ended its success path with
popupMessage([h3 'Success' ...]), and popupMessage re-mounts
#modal-container, so the form was replaced by the notice and the modal
was effectively closed. The design-system branch swaps those notices
for toast.success(), which does not touch the modal: the form stays
open with its fields filled and its button live, and a second click
creates the channel / forum / board / post / thread / identity again,
re-adds the shared directory or the file, or re-sends the friend
certificate.

Every success branch now calls widget.closePopupMessage() before the
toast. Failure branches keep the form open so the user can correct and
retry, as before. The forum reply toast also says "Reply" rather than
"Thread" when it was a reply.

Sites: channel create/post, forum create/thread/reply, board
create/post, add-friend Finish (both certificate kinds), identity
create (signed and pseudonymous), identity edit (signed and
pseudonymous), add shared directory, add file by link.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Seven regressions against master, each with the master behaviour as
the reference:

- The All section is back for channels, boards and forums, fed by the
  full list sorted by popularity (all_*.js). Popular and Other are the
  two halves of the NON-subscribed list, so the section labelled "All
  Channels" hid every subscribed channel and the five most popular
  ones; Other is labelled Other again. /channels/All, /boards/All and
  /forums/All -- the phone default tab on master, so in bookmarks --
  resolve again instead of rendering m(undefined). Forums have no
  popularity split, so their empty "Other" page is gone.

- [hidden] { display: none !important } in the base sheet. The UA
  sheet hides the attribute, but an author display rule on the same
  element wins regardless of specificity, and the channel post
  placeholder sets display: flex on itself: the "No image" box showed
  under every real thumbnail. The image error fallback now clears the
  attribute instead of writing an inline display.

- Distant chat: removing an attached picture clears the session's
  copy too, or selectChatContact restores it and it goes out with the
  next message after a contact switch.

- Ctrl/Cmd+Enter inserts a newline again in the shared composer
  (execCommand first, keeps the undo stack, splice fallback), and the
  field carries enterkeyhint=send again for phone keyboards.

- The in-channel post search is rendered at every width: the page
  head, which hosts the channels search, is not rendered inside a
  channel, so there was no post search on a desktop.

- The forum thread search shows on phones again: the <= 700px block
  lost its display: flex.

- The channel and forum list filters live in module state, like the
  isSearched flags they set: the field is unmounted inside a group and
  recreated on the way back, and came back empty while every
  non-matching group stayed hidden. Clearing the field resets the
  flags instead of calling the per-forum loader with no id (which
  POSTed getForumsInfo with forumIds [null]); a group reloaded while a
  filter is active is filtered too. The channels and posts fields gain
  a clear button.

- Modal close buttons get the 44px touch box under the touch mixin;
  the 26px pointer target is what master's phone padding rule used to
  correct.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
defnax's list, each located and fixed at its cause:

- Phone header status pill: the header went from dark to --chrome but
  the pill kept near-white text over a white tint (1.2:1). Now
  --ink-dim on --sunken with a --line border, the dot outlined in
  --surface.

- Composer: the <= 700px File / Picture menu came back inside the
  shared ChatComposer -- one paperclip opening the menu (the shared
  .mobile-chat-attachment rules), the two wide tools hidden there --
  and the send button is a round glyph on phones, as on master. The
  three copies of the old menu's click-outside guard, which watched an
  element nothing rendered any more, are removed with it.

- Emoji picker: no media rule touched .emoji-picker any more, so the
  320px box anchored on the emoji tool ran past the panes' overflow:
  hidden. It now opens at the strip's left padding, capped to the
  viewport width and to the visible height.

- Boards on a phone: the detail widget is a three-row grid with only
  two children placed, so the board's name and Subscribe button
  auto-placed under the post list; the heading is placed in row 2 and
  the body in row 3. The view toggle keeps its glyphs only, since
  toggle plus pagination outgrew a 360px toolbar by ~50px.

- The overflow menu's Subscribe was painted as a destructive action
  (is-danger on both states); only Unsubscribe is.

- Two blank icons: external-link-alt (Web Help "Open link") had no
  sprite symbol -- mapped to arrow-square-out -- and the Friends'
  Files friend row asked for user-friends in duotone, which does not
  exist; it uses users, the same glyph, which does.

Not touched, as they are design calls: the --ink-dim contrast token,
the contacts select sharing the tabs' row, the forum composer's picker
inside its modal.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- Deleting a draft. The core's MessageDelete searches the received,
  sent, trash and outgoing boxes and never the draft box
  (p3msgservice.cc), so the deletes that saveDraft and the send path
  issued for the previous draft id always failed: every re-save of a
  reopened draft left a copy, and a sent draft stayed in Drafts. The
  new mail_api.deleteMessage() goes through the trash -- MessageToTrash
  does move drafts -- and chains the two calls, since fired together
  the delete could land first. The reading pane's Discard uses it too;
  it fired both at once. A draft the core keeps flagged DRAFT after a
  move to Trash is no longer listed in both folders. A failed draft
  save keeps the composer open instead of discarding the text.

- identityDetails() re-fired /rsIdentity/getIdDetails on every redraw
  after a failed answer: the in-flight marker was cleared before the
  check and nothing was cached on failure, and the request's own
  redraw called it again from the view -- one request per unresolved
  address for as long as the core stayed unreachable (the RetroShare#15 class of
  loop). A miss is now remembered for a minute. identityLabel() asks
  the bulk identity list first, so a name it already knows costs no
  request, and the row and card fetches go through the same shared
  fetch instead of their own, so a first paint is one request per
  identity rather than two.

- loadTagTypes() read res.body in the callback form, which is handed
  the body itself: the cache stayed empty and every tag rendered as
  "Tag <id>" in grey. Pre-existing; one line.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@jolavillette

Copy link
Copy Markdown
Contributor

Four PRs against feat/design-system, one per group of the list above: zelfroster#1 (modals close on success), #2 (the #121 regressions), #3 (defnax's phone items), #4 (mail drafts, identity lookups, tag types). Checked with sass/eslint/build.js only, no phone here — screenshots welcome.

@defnax

defnax commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Boards Subscribed:
image

  • Page selector height is more heigh then View Buttons
  • The Border of Vote Buttons higher then the comment button
  • The 3 dot Menu is on the left side ( on channels i saw it after the search item)
  • Phone Bar ist not Centered
  • Extra space

@defnax

defnax commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Channel subscribed looks better only see a wasted space
image

@defnax

defnax commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

On Mails i would use a normal back icon not this , same like what i use in Master for Network/People/Chats/Boards/Channels/forums, seems you use now not good looking one
image
seems you use now on all back buttons this one
image

@defnax

defnax commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

forums
image
image
image

on my & subscribed forums i see a scrollbar on bottom
image

@defnax

defnax commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Channels
On Phone Icon only needed
There often is see wasted space more then needed
image

@defnax

defnax commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

now looks better in people but the button border is 1px more? else looks good
image

@defnax

defnax commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

here on bottom chat bar it can be more improved? i mean the empty spaces
image
and the file , emoji and the send icon can be more bigger? on phone needs little bit bigger

@defnax

defnax commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

on config page on phone the burger menu is here
image

@defnax

defnax commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

here PR for turtle page:
zelfroster#5

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.

3 participants