Skip to content

Commit 8c368bc

Browse files
committed
feat(shared): add reusable expandable-text component and apply to task description tables
1 parent 64b6089 commit 8c368bc

7 files changed

Lines changed: 96 additions & 3 deletions

File tree

src/app/features/projects/components/project-details/project-details.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ <h2>Project Details</h2>
130130
</div>
131131

132132
<div class="project-details-grid__col project-details-grid__col--tasks">
133-
<p-card header="Recent Tasks" styleClass="details-card">
133+
<p-card header="Recent Tasks" styleClass="details-card details-card--tasks">
134134
<p-table [value]="recentTasks" [loading]="isLoadingDetails" [rowHover]="true" [tableStyle]="{ 'min-width': '42rem' }">
135135
<ng-template pTemplate="header">
136136
<tr>
@@ -147,7 +147,7 @@ <h2>Project Details</h2>
147147
<td>
148148
<div class="task-cell">
149149
<span class="task-cell__title">{{ task.title }}</span>
150-
<span class="task-cell__description">{{ task.description || 'No description.' }}</span>
150+
<app-expandable-text [text]="task.description" [maxLength]="110"></app-expandable-text>
151151
</div>
152152
</td>
153153
<td>

src/app/features/projects/components/project-details/project-details.component.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,15 @@
184184
min-height: 0;
185185
}
186186

187+
:host ::ng-deep .details-card--tasks .p-card-content {
188+
overflow: auto;
189+
min-height: 0;
190+
}
191+
192+
:host ::ng-deep .details-card--tasks .p-datatable-wrapper {
193+
overflow: auto;
194+
}
195+
187196
.project-overview {
188197
display: flex;
189198
flex-direction: column;

src/app/features/task-item/components/task-item-list/task-item-list.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ <h2>All Tasks</h2>
135135
<td>
136136
<div class="task-cell">
137137
<span class="task-cell__title">{{ task.title }}</span>
138-
<span class="task-cell__description">{{ task.description || 'No description provided.' }}</span>
138+
<app-expandable-text [text]="task.description" [maxLength]="120"></app-expandable-text>
139139
</div>
140140
</td>
141141

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<div class="expandable-text" *ngIf="normalizedText.length > 0; else emptyText">
2+
<span class="expandable-text__content">{{ displayText }}</span>
3+
<button
4+
*ngIf="canExpand"
5+
type="button"
6+
class="expandable-text__toggle"
7+
(click)="toggle()">
8+
{{ expanded ? 'Show less' : 'Show more' }}
9+
</button>
10+
</div>
11+
12+
<ng-template #emptyText>
13+
<span class="expandable-text__empty">No description provided.</span>
14+
</ng-template>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
.expandable-text {
2+
display: inline-flex;
3+
flex-direction: column;
4+
align-items: flex-start;
5+
gap: 0.2rem;
6+
}
7+
8+
.expandable-text__content {
9+
color: var(--text-color-secondary);
10+
line-height: 1.35;
11+
word-break: break-word;
12+
}
13+
14+
.expandable-text__toggle {
15+
border: 0;
16+
background: transparent;
17+
padding: 0;
18+
margin: 0;
19+
color: var(--primary-color);
20+
font-size: 0.78rem;
21+
font-weight: 600;
22+
cursor: pointer;
23+
}
24+
25+
.expandable-text__toggle:hover {
26+
text-decoration: underline;
27+
}
28+
29+
.expandable-text__empty {
30+
color: var(--text-color-secondary);
31+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { CommonModule } from '@angular/common';
2+
import { Component, Input } from '@angular/core';
3+
4+
@Component({
5+
selector: 'app-expandable-text',
6+
standalone: true,
7+
imports: [CommonModule],
8+
templateUrl: './expandable-text.component.html',
9+
styleUrl: './expandable-text.component.scss'
10+
})
11+
export class ExpandableTextComponent {
12+
@Input() text: string | null | undefined = '';
13+
@Input() maxLength = 120;
14+
15+
expanded = false;
16+
17+
get normalizedText(): string {
18+
return (this.text ?? '').trim();
19+
}
20+
21+
get canExpand(): boolean {
22+
return this.normalizedText.length > this.maxLength;
23+
}
24+
25+
get displayText(): string {
26+
if (!this.canExpand || this.expanded) {
27+
return this.normalizedText;
28+
}
29+
30+
return `${this.normalizedText.slice(0, this.maxLength).trimEnd()}...`;
31+
}
32+
33+
toggle(): void {
34+
this.expanded = !this.expanded;
35+
}
36+
}

src/app/shared/shared.module.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,12 @@ import { CalendarModule } from 'primeng/calendar';
2929
import { StepsModule } from 'primeng/steps';
3030
import { ConfirmDialogModule } from 'primeng/confirmdialog';
3131
import { MessagesModule } from 'primeng/messages';
32+
import { ExpandableTextComponent } from './components/expandable-text/expandable-text.component';
3233

3334
@NgModule({
35+
imports: [ExpandableTextComponent],
3436
exports: [
37+
ExpandableTextComponent,
3538
CommonModule,
3639
CardModule,
3740
InputTextModule,

0 commit comments

Comments
 (0)