Skip to content

Conversation

@MaxFrank13
Copy link
Member

@MaxFrank13 MaxFrank13 commented Dec 11, 2025

Description

Corresponding issue: #3311

This refactors the Truncate component to use CSS properties instead of complex JS. The -webkit-line-clamp property has support for most common browsers (source). Eventually, line-clamp should have support but that is not currently the case.

This was discussed in Paragon Working Group (session notes).

Both title and aria-label are used for accessibility in the same way it was used before. The assembleStringFromChildrenArray utility function has been moved to a utils.ts file and thus converted to TypeScript.

The deprecated component as well as it's utils file still exist under the Truncate directory. The deprecated component is still accessible at Truncate.Deprecated. The utils file has been renamed to utils.deprecated. It didn't make sense to convert the entire utils file to TS when only the one utility function (assembleStringFromChildrenArray) was needed.

The tests for the deprecated component are under TruncateDeprecated.test.jsx.

src/
└── Truncate/
    ├── index.js                  
    ├── index.scss                
    ├── README.md                 
    ├── Truncate.test.jsx         
    ├── Truncate.tsx              
    ├── TruncateDeprecated.jsx    
    ├── TruncateDeprecated.test.jsx 
    ├── utils.deprecated.js       
    ├── utils.deprecated.test.js  
    ├── utils.test.ts             
    └── utils.ts 

Deploy Preview

https://deploy-preview-4037--paragon-openedx-v23.netlify.app/components/truncate/

Merge Checklist

  • If your update includes visual changes, have they been reviewed by a designer? Send them a link to the Netlify deploy preview, if applicable.
  • Does your change adhere to the documented style conventions?
  • Do any prop types have missing descriptions in the Props API tables in the documentation site (check deploy preview)?
  • Were your changes tested using all available themes (see theme switcher in the header of the deploy preview, under the "Settings" icon)?
  • Were your changes tested in the example app?
  • Is there adequate test coverage for your changes?
  • Consider whether this change needs to reviewed/QA'ed for accessibility (a11y). If so, please request an a11y review for the PR in the #wg-paragon Open edX Slack channel.

Post-merge Checklist

  • Verify your changes were released to NPM at the expected version.
  • If you'd like, share your contribution in #show-and-tell.
  • 🎉 🙌 Celebrate! Thanks for your contribution.

@netlify
Copy link

netlify bot commented Dec 11, 2025

Deploy Preview for paragon-openedx-v23 ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 947cdc2
🔍 Latest deploy log https://app.netlify.com/projects/paragon-openedx-v23/deploys/693c58900bd5c00008b9e119
😎 Deploy Preview https://deploy-preview-4037--paragon-openedx-v23.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@MaxFrank13 MaxFrank13 force-pushed the mfrank/truncate-component-refactor branch from d13ac64 to cca4d3a Compare December 12, 2025 17:22
@MaxFrank13 MaxFrank13 marked this pull request as ready for review December 12, 2025 18:12
@codecov
Copy link

codecov bot commented Dec 12, 2025

Codecov Report

❌ Patch coverage is 97.29730% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 94.50%. Comparing base (fb678e3) to head (947cdc2).

Files with missing lines Patch % Lines
src/Truncate/utils.ts 96.66% 1 Missing ⚠️
Additional details and impacted files
@@               Coverage Diff                @@
##           release-23.x    #4037      +/-   ##
================================================
+ Coverage         94.39%   94.50%   +0.11%     
================================================
  Files               242      245       +3     
  Lines              4296     4328      +32     
  Branches            981     1034      +53     
================================================
+ Hits               4055     4090      +35     
+ Misses              237      230       -7     
- Partials              4        8       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@brian-smith-tcril
Copy link
Contributor

On slack you mentioned needing to use inline styles. I wasn't able to completely get away from them but I was able to at least minimize it down to setting a css var

diff --git a/src/Truncate/Truncate.tsx b/src/Truncate/Truncate.tsx
index fa421b68f6..ab9dd95753 100644
--- a/src/Truncate/Truncate.tsx
+++ b/src/Truncate/Truncate.tsx
@@ -9,11 +9,6 @@ interface TruncateProps {
 }
 
 function Truncate({ children, lines = 1 }: TruncateProps) {
-  const style = {
-    lineClamp: lines,
-    WebkitLineClamp: lines,
-  };
-
   const initialText = Array.isArray(children) ? assembleStringFromChildrenArray(children) : String(children);
 
   return (
@@ -21,7 +16,7 @@ function Truncate({ children, lines = 1 }: TruncateProps) {
       title={initialText}
       aria-label={initialText}
       className="truncate-text"
-      style={style}
+      style={{ "--truncate-prop-lines": lines } as React.CSSProperties}
       data-testid="truncate-element"
     >
       {children}
diff --git a/src/Truncate/index.scss b/src/Truncate/index.scss
index a2f9fbde1f..418641008b 100644
--- a/src/Truncate/index.scss
+++ b/src/Truncate/index.scss
@@ -2,6 +2,6 @@
   overflow: hidden;
   display: -webkit-box;
   -webkit-box-orient: vertical;
-  -webkit-line-clamp: 1;
-  line-clamp: 1;
+  -webkit-line-clamp: var(--truncate-prop-lines);
+  line-clamp: var(--truncate-prop-lines);
 }

As for the naming of the variable, this is definitely setting a new pattern so I'd love to hear opinions. My reasoning behind --truncate-prop-lines is:

  • I want to make sure it's clear that this CSS var isn't related to tokens (I think just not having the --pgn- prefix helps with that)
  • I want someone reading the scss file to know where the var is coming from

@MaxFrank13
Copy link
Member Author

I want to make sure it's clear that this CSS var isn't related to tokens (I think just not having the --pgn- prefix helps with that)

Yes I think this makes sense and would be a clear way of indicating that this is a local variable and not a design token.

W.r.t the style conventions, it also mentions that all CSS classes should be prefixed with pgn__. I feel like this differs from the variable question. Should the CSS classes added in this PR have the pgn__ prefix? My inclination is to think yes because they are classes from Paragon for a specific Paragon component, and are not utility classes.

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.

2 participants