From e80847b01f660a2c1492932fa91fc514b1f9f422 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 24 Mar 2026 17:36:24 +0200 Subject: [PATCH] Fix project name overflow and add 6-word validation limit (#972) * Fix project name overflow and add validation This commit addresses issue #971 by implementing both UI fixes and validation to prevent excessively long project names. Changes: 1. Add word-break and line-clamp to ProjectBanner.tsx to handle overflow gracefully with line-clamp-3 for names 2. Add frontend validation in ProjectModal.tsx limiting names to 6 words maximum 3. Add backend validation in project.js model with custom wordCount validator 4. Show user-friendly error messages when validation fails This ensures project names remain concise and UI-friendly while preventing the extreme overflow cases that were possible before. Fixes #971 * Add overflow-hidden to make line-clamp work properly The line-clamp utility requires explicit overflow-hidden to function correctly. Without it, the text continues to display in full rather than being truncated with ellipsis. * Fix line-clamp using inline CSS styles Tailwind's line-clamp utilities weren't working, so switched to using inline styles with the standard CSS approach: - display: -webkit-box - -webkit-line-clamp: 3 - -webkit-box-orient: vertical This ensures the text truncation works reliably across browsers. * Use Tailwind line-clamp utilities (already defined in CSS) The project already has line-clamp-1/2/3 utilities properly defined in tailwind.css with all the necessary webkit properties. Simplified the component to use these existing utilities instead of inline styles. * Add dedicated CSS classes with !important for line-clamp Created custom project-name-clamp and project-desc-clamp classes with !important flags to ensure they override any conflicting styles. This should finally fix the text truncation issue. * Use component-scoped styles for line-clamp Adding inline style tag in the component to ensure the line-clamp CSS is definitely loaded and applied. This bypasses any potential issues with external CSS compilation or loading order. * Change project name line-clamp from 3 to 2 lines Limiting project name display to 2 lines with ellipsis for better visual density and cleaner appearance. * Increase line-height for project name in banner Added line-height: 1.3 to project name for better readability and visual spacing between lines. --- backend/models/project.js | 17 ++++++++++++++ frontend/components/Project/ProjectBanner.tsx | 23 ++++++++++++++++--- frontend/components/Project/ProjectModal.tsx | 15 ++++++++++++ frontend/styles/tailwind.css | 15 ++++++++++++ 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/backend/models/project.js b/backend/models/project.js index 52fde35..2abdcc5 100644 --- a/backend/models/project.js +++ b/backend/models/project.js @@ -19,6 +19,23 @@ module.exports = (sequelize) => { name: { type: DataTypes.STRING, allowNull: false, + validate: { + notEmpty: { + msg: 'Project name is required', + }, + wordCount(value) { + const MAX_WORDS = 6; + const wordCount = value + .trim() + .split(/\s+/) + .filter((word) => word.length > 0).length; + if (wordCount > MAX_WORDS) { + throw new Error( + `Project name must be ${MAX_WORDS} words or less` + ); + } + }, + }, }, description: { type: DataTypes.TEXT, diff --git a/frontend/components/Project/ProjectBanner.tsx b/frontend/components/Project/ProjectBanner.tsx index 3211620..03d1f0c 100644 --- a/frontend/components/Project/ProjectBanner.tsx +++ b/frontend/components/Project/ProjectBanner.tsx @@ -45,6 +45,23 @@ const ProjectBanner: React.FC = ({ return (
+
{project.image_url ? ( = ({ )}
-
-

+
+

{project.name}

{project.description && ( -

+

{project.description}

)} diff --git a/frontend/components/Project/ProjectModal.tsx b/frontend/components/Project/ProjectModal.tsx index ca8da87..ee7d554 100644 --- a/frontend/components/Project/ProjectModal.tsx +++ b/frontend/components/Project/ProjectModal.tsx @@ -268,6 +268,21 @@ const ProjectModal: React.FC = ({ return; } + const MAX_WORDS = 6; + const wordCount = formData.name + .trim() + .split(/\s+/) + .filter((word) => word.length > 0).length; + if (wordCount > MAX_WORDS) { + setError( + t( + 'errors.projectNameTooLong', + `Project name must be ${MAX_WORDS} words or less` + ) + ); + return; + } + setIsSaving(true); try { // Add new tags to the global store diff --git a/frontend/styles/tailwind.css b/frontend/styles/tailwind.css index a3e0e2c..538d335 100644 --- a/frontend/styles/tailwind.css +++ b/frontend/styles/tailwind.css @@ -170,6 +170,21 @@ select:focus { display: none; /* Chrome/Safari */ } +/* Project name and description line clamp */ +.project-name-clamp { + display: -webkit-box !important; + -webkit-box-orient: vertical !important; + -webkit-line-clamp: 3 !important; + overflow: hidden !important; +} + +.project-desc-clamp { + display: -webkit-box !important; + -webkit-box-orient: vertical !important; + -webkit-line-clamp: 2 !important; + overflow: hidden !important; +} + @layer utilities { .line-clamp-1, .line-clamp-2,