[#75274] Unify and document ExpandableTextComponent#23328
Open
myabc wants to merge 7 commits into
Open
Conversation
ExpandableTextComponent
Base automatically changed from
bug/75275-truncated-text-hellip-misalignment
to
release/17.5
May 26, 2026 12:28
Deploying openproject with ⚡ PullPreview
|
8d912e3 to
c4c0187
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR standardizes truncation/expansion behavior around OpPrimer::ExpandableTextComponent, adds Lookbook documentation/previews for it, and migrates OpenProject::Common::AttributeComponent from a bespoke Stimulus/CSS implementation to the shared truncation controller + component.
Changes:
- Extend the Stimulus
truncationcontroller to support horizontal vs vertical truncation and inline vs dialog-style expansion. - Enhance
OpPrimer::ExpandableTextComponent(API + docs) and add Lookbook previews/spec coverage. - Refactor
OpenProject::Common::AttributeComponentto composeExpandableTextComponent, removing the legacyattributecontroller and styles.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| spec/components/open_project/common/inplace_edit_fields/display_fields/rich_text_area_component_spec.rb | Updates expectations to the unified truncation controller / expander visibility. |
| spec/components/op_primer/expandable_text_component_spec.rb | Expands component specs to cover modes, options, and validation. |
| spec/components/op_primer/expandable_text_component_preview_spec.rb | Adds preview rendering specs (including Lookbook path shim). |
| lookbook/previews/op_primer/expandable_text_component_preview.rb | Adds preview class with multiple scenarios + playground params. |
| lookbook/previews/op_primer/expandable_text_component_preview/default.html.erb | Default horizontal example template. |
| lookbook/previews/op_primer/expandable_text_component_preview/in_table.html.erb | Table layout example template. |
| lookbook/previews/op_primer/expandable_text_component_preview/vertical.html.erb | Vertical line-clamp example template. |
| lookbook/previews/op_primer/expandable_text_component_preview/dialog.html.erb | Dialog expansion example template. |
| lookbook/previews/op_primer/expandable_text_component_preview/playground.html.erb | Param-driven playground template. |
| lookbook/docs/components/expandable-text.md.erb | Adds component documentation and usage guidance. |
| frontend/src/stimulus/controllers/truncation.controller.ts | Adds mode/inline values and vertical truncation + class toggling. |
| frontend/src/stimulus/controllers/truncation.controller.spec.ts | Updates/expands unit tests for new controller behavior. |
| frontend/src/stimulus/controllers/dynamic/attribute.controller.ts | Removes legacy attribute truncation controller. |
| frontend/src/global_styles/content/_text_utils.sass | Adds .expandable-text--expanded to undo line-clamp when expanded. |
| app/components/open_project/common/attribute_component.rb | Drops legacy params and adapts to new expander logic. |
| app/components/open_project/common/attribute_component.html.erb | Replaces bespoke truncation markup with ExpandableTextComponent. |
| app/components/open_project/common/attribute_component.sass | Removes legacy CSS for the old attribute truncation implementation. |
| app/components/op_primer/expandable_text_component.rb | Documents/unifies component API; wires controller values and expander args. |
| app/components/op_primer/expandable_text_component.html.erb | Adds vertical rendering path and uses unified expander arguments. |
| app/components/_index.sass | Removes import of deleted legacy attribute component stylesheet. |
7ae6625 to
376bc80
Compare
myabc
commented
May 30, 2026
Comment on lines
+35
to
+51
| # TODO: replace this path shim with a cleaner mechanism for exercising | ||
| # lookbook previews in specs (e.g. a shared support helper). | ||
| # | ||
| # Lookbook is disabled in the test environment, so its preview path (which hosts the | ||
| # `render_with_template` ERB files) is not registered. Register it for these examples so | ||
| # `render_preview` can resolve the templates, then restore the original paths. | ||
| around do |example| | ||
| path = Rails.root.join("lookbook/previews").to_s | ||
| paths = ViewComponent::Base.previews.paths | ||
| added = paths.exclude?(path) | ||
| paths << path if added | ||
| begin | ||
| example.run | ||
| ensure | ||
| paths.delete(path) if added | ||
| end | ||
| end |
Contributor
Author
There was a problem hiding this comment.
@HDinger this is a horrible hack - and I need to find a better fix.
376bc80 to
c2f0ee7
Compare
Two controllers solved the same truncation-detection problem independently. Unifies them with orthogonal truncation/expansion axes on `ExpandableTextComponent`. Extends `TruncationController` with `mode` (horizontal/vertical) and `inline` (true/false) values. Vertical detection uses `scrollHeight` vs `clientHeight`, working with `-webkit-line-clamp`. Extends `ExpandableTextComponent` with `truncation:`, `lines:`, `inline:`, and `expander_arguments:` params. Adds `expandable-text--expanded` CSS class for vertical inline expansion. https://community.openproject.org/wp/75274
`AttributeComponent` now uses `ExpandableTextComponent` with `truncation: :vertical, inline: false` instead of managing its own truncation markup. Deletes the now-redundant `AttributeController` Stimulus controller and text-hider overlay. https://community.openproject.org/wp/75274
Adds the ExpandableTextComponent Lookbook preview covering the horizontal, vertical, short-text, in-table, dialog, and playground variants and documenting each truncation mode, plus a spec that smoke-tests every preview renders. https://community.openproject.org/work_packages/75274
c2f0ee7 to
da299b9
Compare
Extracts vertical (multi-line) truncation out of the shared `ExpandableTextComponent` into a dedicated `VerticalTruncateComponent`, the vertical counterpart to `Primer::Beta::Truncate`. The new component owns an `.op-vertical-truncate` class hierarchy (`--lines-N` and `--expanded`) rather than the shared `.line-clamp-N` utility, and takes an overridable `tag` defaulting to `:div` for safe block-content nesting. `ExpandableTextComponent` builds the truncate component matching its mode, collapsing the template to a single wrapper render shared by both truncation axes. https://community.openproject.org/wp/75274
Renames the `truncation` Stimulus controller to `expandable-text` and documents it as private to `ExpandableTextComponent`: it operates on the component's DOM (including `Primer::Beta::Truncate`'s internal `.Truncate-text`), so it is not a reusable behavior. The controller again owns the mode-keyed expanded class rather than receiving it injected. Also renames the component's public axes for clarity, and to avoid the clash with `HiddenTextExpander`'s own `inline`: `truncation:` becomes `direction:` and `inline:` becomes `expansion: :inline | :external`.
`set_expander_arguments!` only shallow-copied the hash, but `Primer::Alpha::HiddenTextExpander` mutates the nested `button_arguments` (adding `aria-label` and `classes`), leaking changes back to a caller that reuses it. `deep_dup` isolates nested hashes too, matching the precedent in primer_view_components' `sub_header.rb`.
Gives the component its own preview (with a configurable line count) and drops the `OpenProject/AddPreviewForViewComponent` rubocop disable that stood in for it.
712c3d7 to
ba70cd6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ticket
https://community.openproject.org/wp/75274
What are you trying to accomplish?
Introduces a reusable
ExpandableTextComponentand collapses the two overlapping truncation Stimulus controllers into a single, privateexpandable-textcontroller.The component truncates block content either horizontally (one line, via
Primer::Beta::Truncate) or vertically (multi-line, via the newOpPrimer::VerticalTruncateComponent), exposing an expander that reveals the full text inline or opens a dialog.AttributeComponentis recomposed on top of it (choosing the truncation direction from itslinescount) and the legacyattribute.controller.tsis removed.Screenshots
the behaviour is best seen on the new ExpandableText Lookbook page (horizontal, vertical, in-table, dialog, and playground previews).
What approach did you choose and why?
A single Stimulus controller replaces the duplicated logic, so horizontal/vertical truncation and inline/dialog expansion share one code path. The component exposes two orthogonal axes —
direction:(:horizontal/:vertical) andexpansion:(:inline/:external) — validated through Primer'sfetch_or_fallback, and is documented in Lookbook.The
expandable-textcontroller is private toExpandableTextComponent: it operates on the DOM the component renders (includingPrimer::Beta::Truncate's internal.Truncate-text), so it is not a reusable behavior.The new preview spec registers the Lookbook preview path with a small shim because Lookbook is disabled in the test environment; a cleaner mechanism is left for a follow-up.
Vertical expander alignment. In vertical mode the expander is a flex sibling cross-aligned to the last visible line (
align_items: :flex_end), which keeps-webkit-line-clamptruncation detection simple and robust. A bottom-right wrap-around expander (text flowing around the control on the last line) was considered but deferred — it would mean droppingline-clampfor amax-heightclamp plus either per-mode markup divergence (float-spacer) or reviving the removed absolute-overlay + text-hider machinery. To be discussed in review.Merge checklist