Repository navigation
fix: render control labels as plain text - #2019
Conversation
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>
Bundle size report (gzip)
120 chunks compared, 20 changed. Sizes are gzip, matching what nginx serves. |
There was a problem hiding this comment.
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-htmllabel/subtitle rendering with plain-text rendering (with newline preservation) acrossAppNamed*controls,StatusLabel, andCollapsableCard. - Add a
labelslot (and makelabelprop optional) to support the rare case where markup is intentional. - Introduce
AppNamedContainerto 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>

Follow-up to #2014 and #2015. The form controls,
StatusLabelandCollapsableCard's subtitle stop losing text that looks like a tag, such as<none>.Changes
AppNamedSwitch,AppNamedSelect,AppNamedSlider,AppNamedTextField,StatusLabel, andCollapsableCard'ssubTitlerender their text as plain text with line breaks kept, instead of throughv-safe-htmllabelslot, so thelabelprop is now optional.OutputFanuses it for the RPM in<small>, the only label that relied on HTMLAppNamedContainerholds the label column (cols="12" sm="5", disabled styling, plain-text fallback) that Select, Slider and TextField each repeated.AppNamedSwitchkeeps its own layout, which has no column split. Each control forwards itslabelslot 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 fromAppSwitchtoStatusLabel, dropping the unusedStateMixinAGENTS.mddocuments the plain-text controls andAppNamedContainerNotes
OutputFanStatusLabelare now inline rather thandisplay: block, which baseline alignment needsTesting
pnpm run lint,type-check,test:unit(685 passed) andcircular-checkpass. Not yet checked in a browser.🤖 Generated with Claude Code