Skip to content

[#75274] Unify and document ExpandableTextComponent#23328

Open
myabc wants to merge 7 commits into
devfrom
code-maintenance/75274-document-expandable-text
Open

[#75274] Unify and document ExpandableTextComponent#23328
myabc wants to merge 7 commits into
devfrom
code-maintenance/75274-document-expandable-text

Conversation

@myabc
Copy link
Copy Markdown
Contributor

@myabc myabc commented May 22, 2026

Ticket

https://community.openproject.org/wp/75274

What are you trying to accomplish?

Introduces a reusable ExpandableTextComponent and collapses the two overlapping truncation Stimulus controllers into a single, private expandable-text controller.

The component truncates block content either horizontally (one line, via Primer::Beta::Truncate) or vertically (multi-line, via the new OpPrimer::VerticalTruncateComponent), exposing an expander that reveals the full text inline or opens a dialog. AttributeComponent is recomposed on top of it (choosing the truncation direction from its lines count) and the legacy attribute.controller.ts is removed.

Screenshots

Screenshot 2026-05-29 at 22 16 53 Screenshot 2026-05-29 at 22 16 39

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) and expansion: (:inline/:external) — validated through Primer's fetch_or_fallback, and is documented in Lookbook.

The expandable-text controller is private to ExpandableTextComponent: it operates on the DOM the component renders (including Primer::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-clamp truncation 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 dropping line-clamp for a max-height clamp plus either per-mode markup divergence (float-spacer) or reviving the removed absolute-overlay + text-hider machinery. To be discussed in review.

Merge checklist

  • Added/updated tests
  • Added/updated documentation in Lookbook (patterns, previews, etc)
  • Tested major browsers (Chrome, Firefox, Edge, ...)

@myabc myabc changed the title code maintenance/75274 document expandable text [#75274] Unify and document ExpandableTextComponent May 22, 2026
@myabc myabc added maintenance needs review styling ruby Pull requests that update Ruby code and removed needs review labels May 22, 2026
Base automatically changed from bug/75275-truncated-text-hellip-misalignment to release/17.5 May 26, 2026 12:28
@myabc myabc changed the base branch from release/17.5 to dev May 26, 2026 14:50
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 26, 2026

Deploying openproject with PullPreview

Field Value
Latest commit ba70cd6
Job deploy
Status ✅ Deploy successful
Preview URL https://pr-23328-75274-document-e-ip-178-105-243-35.my.opf.run:443

View logs

@myabc myabc force-pushed the code-maintenance/75274-document-expandable-text branch from 8d912e3 to c4c0187 Compare May 29, 2026 20:16
@myabc myabc requested a review from Copilot May 29, 2026 20:17
@myabc myabc marked this pull request as ready for review May 29, 2026 20:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 truncation controller 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::AttributeComponent to compose ExpandableTextComponent, removing the legacy attribute controller 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.

Comment thread frontend/src/stimulus/controllers/expandable-text.controller.ts
Comment thread app/components/op_primer/expandable_text_component.html.erb Outdated
Comment thread app/components/op_primer/expandable_text_component.rb Outdated
Comment thread app/components/op_primer/expandable_text_component.rb
@myabc myabc force-pushed the code-maintenance/75274-document-expandable-text branch 2 times, most recently from 7ae6625 to 376bc80 Compare May 29, 2026 22:01
@myabc myabc requested a review from Copilot May 29, 2026 22:03
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.

Comment thread app/components/op_primer/expandable_text_component.rb
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
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@HDinger this is a horrible hack - and I need to find a better fix.

@myabc myabc force-pushed the code-maintenance/75274-document-expandable-text branch from 376bc80 to c2f0ee7 Compare May 30, 2026 15:28
myabc added 3 commits May 30, 2026 17:32
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
@myabc myabc force-pushed the code-maintenance/75274-document-expandable-text branch from c2f0ee7 to da299b9 Compare May 30, 2026 15:32
@myabc myabc requested a review from Copilot May 30, 2026 15:42
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.

Comment thread app/components/open_project/common/attribute_component.html.erb
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
@myabc myabc requested a review from HDinger May 30, 2026 16:12
myabc added 3 commits May 30, 2026 19:17
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.
@myabc myabc force-pushed the code-maintenance/75274-document-expandable-text branch from 712c3d7 to ba70cd6 Compare May 30, 2026 17:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

2 participants