Skip to content

fix: render control labels as plain text - #2019

Merged
pedrolamas merged 2 commits into
fluidd-core:developfrom
pedrolamas:pedrolamas/plain-text-labels
Nov 7, 2026
Merged

pedrolamas merged 2 commits into
fluidd-core:developfrom
pedrolamas:pedrolamas/plain-text-labels

Conversation

@pedrolamas

Copy link
Copy Markdown
Member

Follow-up to #2014 and #2015. The form controls, StatusLabel and CollapsableCard's subtitle stop losing text that looks like a tag, such as <none>.

Changes

  • AppNamedSwitch, AppNamedSelect, AppNamedSlider, AppNamedTextField, StatusLabel, and CollapsableCard's subTitle render their text as plain text with line breaks kept, instead of through v-safe-html
  • Markup in a label goes through a new label slot, so the label prop is now optional. OutputFan uses it for the RPM in <small>, the only label that relied on HTML
  • New AppNamedContainer holds the label column (cols="12" sm="5", disabled styling, plain-text fallback) that Select, Slider and TextField each repeated. AppNamedSwitch keeps its own layout, which has no column split. Each control forwards its label slot only when it is given one (v-if="$scopedSlots.label")
  • StatusLabel: label and value are aligned on the baseline, so a value that wraps (filename, M117 message) keeps the label next to its first line. The -- placeholder is now the slot's fallback. Ellipsis rules that never applied are removed, and the class is renamed from AppSwitch to StatusLabel, dropping the unused StateMixin
  • AGENTS.md documents the plain-text controls and AppNamedContainer

Notes

  • Every label passed to these components is a plain locale string or a name, so no caller depended on HTML other than OutputFan
  • Values inside StatusLabel are now inline rather than display: block, which baseline alignment needs

Testing

pnpm run lint, type-check, test:unit (685 passed) and circular-check pass. Not yet checked in a browser.

🤖 Generated with Claude Code

The AppNamed* controls, StatusLabel and CollapsableCard's subTitle
rendered their text through v-safe-html, so tag-like text such as
<none> was lost. They now render plain text, keeping line breaks,
and take markup through a label slot instead (OutputFan's RPM).

AppNamedContainer holds the label column shared by the Select,
Slider and TextField controls. StatusLabel gets a baseline-aligned
layout with a slot fallback for empty values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Pedro Lamas <pedrolamas@gmail.com>
@pedrolamas pedrolamas added the Code - Optimizations Everything that relates to code optimizations! label Nov 7, 2026
@pedrolamas pedrolamas added this to the 1.37.8 milestone Nov 7, 2026
@pedrolamas
pedrolamas requested a balanced review from Copilot November 7, 2026 16:50
@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Bundle size report (gzip)

Chunk Base Head Δ
assets/AppNamedSlider-*.js 1.7 kB 1.8 kB +114 B
assets/index-*.js 168.0 kB 168.0 kB -38 B
assets/Dashboard-*.js 63.1 kB 63.1 kB -11 B
assets/Dashboard-*.css 3.8 kB 3.8 kB -6 B
sw.js 11.2 kB 11.2 kB +4 B
assets/Diagnostics-*.js 15.9 kB 15.9 kB +2 B
assets/History-*.js 4.5 kB 4.5 kB -2 B
assets/AfcPrintStartDialogTool-*.js 2.3 kB 2.3 kB -1 B
assets/AppBtnCollapseGroup-*.js 638 B 637 B -1 B
assets/Configure-*.js 776 B 775 B -1 B
assets/Console-*.js 367 B 366 B -1 B
assets/ConsoleCard-*.js 2.0 kB 2.0 kB -1 B
assets/DiskUsageCard-*.js 3.2 kB 3.2 kB -1 B
assets/FullscreenCamera-*.js 423 B 422 B -1 B
assets/GcodePreview-*.js 365 B 364 B -1 B
assets/Icons-*.js 529 B 528 B -1 B
assets/MacroCategorySettings-*.js 2.0 kB 2.0 kB -1 B
assets/NotFound-*.js 437 B 436 B -1 B
assets/Timelapse-*.js 1.9 kB 1.9 kB +1 B
assets/TimelapseRenderSettingsDialog-*.js 1.8 kB 1.8 kB +1 B
Total 2.9 MB 2.9 MB +54 B

120 chunks compared, 20 changed. Sizes are gzip, matching what nginx serves.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Copilot was unable to complete this review at the selected tier due to model policy or plan restrictions.

🟡 Changes recommended

A formatting issue remains in OutputFan.vue where the newly introduced label slot can cause the fan name and RPM text to run together without a separator, so a small UI tweak is needed before approval.

1 open issue
What changed in this PR

This pull request updates several UI components to render control labels and subtitles as plain text (preserving line breaks) instead of using v-safe-html, preventing tag-like strings such as <none> from being treated as markup and disappearing. Where intentional markup is needed, it introduces a dedicated label slot (used by OutputFan).

Changes:

  • Replace v-safe-html label/subtitle rendering with plain-text rendering (with newline preservation) across AppNamed* controls, StatusLabel, and CollapsableCard.
  • Add a label slot (and make label prop optional) to support the rare case where markup is intentional.
  • Introduce AppNamedContainer to deduplicate the shared “label column + control” layout for Select/Slider/TextField.
File Summary
src/​components/​widgets/​status/​StatusLabel.vue Render label/value as plain text; adjust layout for baseline alignment; remove unused styling/mixin and update placeholder behavior.
src/​components/​widgets/​outputs/​OutputFan.vue Move RPM markup usage into the new #label slot (intentional markup path). Nit: add spacing/punctuation between fan.prettyName and the <small> RPM text to avoid run-together output.
src/​components/​ui/​AppNamedTextField.vue Switch to AppNamedContainer for shared label layout; plain-text label fallback; forward label slot only when provided.
src/​components/​ui/​AppNamedSwitch.vue Render label as plain text by default; add label slot and make label optional (keeps its distinct layout).
src/​components/​ui/​AppNamedSlider.vue Use AppNamedContainer; plain-text labels; conditional label slot passthrough; label prop optional.
src/​components/​ui/​AppNamedSelect.vue Use AppNamedContainer; plain-text labels; conditional label slot passthrough; label prop optional.
src/​components/​ui/​AppNamedContainer.vue New shared label+content layout wrapper with disabled styling and plain-text label fallback. Nit: add the conventional kebab-case root class (e.g. class="app-named-container") to match src/components/ui/ conventions.
src/​components/​common/​CollapsableCard.vue Render subTitle as plain text (preserving newlines) instead of using v-safe-html.
components.d.ts Register/add typings for the new AppNamedContainer component.
AGENTS.md Document the “render plain text as plain text” rule plus the new AppNamedContainer / label slot pattern.

This pull request is too complex or risky for automated approval.

Review effort: Balanced

The fan name and the RPM <small> sat on separate template lines, and
condensed whitespace dropped the space between them. Use ml-1 instead.

Give AppNamedContainer its app-named-container root class, as ui/
components require.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Pedro Lamas <pedrolamas@gmail.com>
@pedrolamas
pedrolamas merged commit b6964eb into fluidd-core:develop Nov 7, 2026
6 checks passed
@pedrolamas
pedrolamas deleted the pedrolamas/plain-text-labels branch November 7, 2026 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Code - Optimizations Everything that relates to code optimizations!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants