Skip to content

Commit c24bdc0

Browse files
Vaibhav  BhallaVaibhav  Bhalla
authored andcommitted
feat(arc): implement breadcrumb feature
GH-126
1 parent c57160d commit c24bdc0

File tree

8 files changed

+81
-17
lines changed

8 files changed

+81
-17
lines changed

projects/arc-lib/src/lib/components/breadcrumb/breadcrumb-demo/user-title/user-title.service.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ export class TitleService {
99
const title = this.titles.find(u => u.id === id);
1010
return of(title);
1111
}
12-
getTitleNameForBreadcrumb(id: string): Observable<string> {
12+
getTitleNameForBreadcrumb(
13+
params: Record<string, string>,
14+
): Observable<string> {
15+
const id = params['id'];
1316
return this.getTitleById(id).pipe(
1417
map(titles => titles?.title || `Document #${id}`),
1518
catchError(() => of(`Document #${id}`)),

projects/arc-lib/src/lib/components/breadcrumb/breadcrumb-demo/user/user.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ export class UserService {
99
const user = this.users.find(u => u.id === id);
1010
return of(user);
1111
}
12-
getUserNameForBreadcrumb(id: string): Observable<string> {
12+
getUserNameForBreadcrumb(params: Record<string, string>): Observable<string> {
13+
const id = params['id']; // Access any param key dynamically
1314
return this.getUserById(id).pipe(
1415
map(user => user?.name || `User #${id}`),
1516
catchError(() => of(`User #${id}`)),

projects/arc-lib/src/lib/components/breadcrumb/breadcrumb.component.html

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,69 @@
55
>
66
<li class="breadcrumb-item">
77
<ng-container *ngIf="!breadcrumbs[0].skipLink; else noLinkFirst">
8-
<a [routerLink]="breadcrumbs[0].url">{{ breadcrumbs[0].label }}</a>
8+
<a
9+
[routerLink]="breadcrumbs[0].url"
10+
[title]="breadcrumbs[0].label"
11+
class="breadcrumb-label"
12+
>
13+
{{ getTrimmedLabel(breadcrumbs[0].label) }}
14+
</a>
915
</ng-container>
1016
<ng-template #noLinkFirst>
11-
<span>{{ breadcrumbs[0].label }}</span>
17+
<span class="breadcrumb-label" [title]="breadcrumbs[0].label">
18+
{{ getTrimmedLabel(breadcrumbs[0].label) }}
19+
</span>
1220
</ng-template>
1321
</li>
14-
<span class="separator">{{ separator }}</span>
22+
23+
<span class="{{ separatorClass }}">{{ separator }}</span>
1524

1625
<li class="breadcrumb-item clickable" (click)="toggleExpand()">...</li>
17-
<span class="separator">{{ separator }}</span>
26+
<span class="{{ separatorClass }}">{{ separator }}</span>
1827

19-
<li class="breadcrumb-item" [class.active]="true">
28+
<li class="breadcrumb-item active">
2029
<ng-container
2130
*ngIf="!breadcrumbs[breadcrumbs.length - 1].skipLink; else noLinkLast"
2231
>
23-
<a [routerLink]="breadcrumbs[breadcrumbs.length - 1].url">
24-
{{ breadcrumbs[breadcrumbs.length - 1].label }}
32+
<a
33+
[routerLink]="breadcrumbs[breadcrumbs.length - 1].url"
34+
[title]="breadcrumbs[breadcrumbs.length - 1].label"
35+
class="breadcrumb-label"
36+
>
37+
{{ getTrimmedLabel(breadcrumbs[breadcrumbs.length - 1].label) }}
2538
</a>
2639
</ng-container>
2740
<ng-template #noLinkLast>
28-
<span>{{ breadcrumbs[breadcrumbs.length - 1].label }}</span>
41+
<span
42+
class="breadcrumb-label"
43+
[title]="breadcrumbs[breadcrumbs.length - 1].label"
44+
>
45+
{{ getTrimmedLabel(breadcrumbs[breadcrumbs.length - 1].label) }}
46+
</span>
2947
</ng-template>
3048
</li>
3149
</ng-container>
3250

51+
<!-- Full breadcrumb trail -->
3352
<ng-template #fullBreadcrumb>
3453
<ng-container *ngFor="let breadcrumb of breadcrumbs; let last = last">
3554
<li class="breadcrumb-item" [class.active]="last">
3655
<ng-container *ngIf="!breadcrumb.skipLink && !last; else noLink">
37-
<a [routerLink]="breadcrumb.url">{{ breadcrumb.label }}</a>
56+
<a
57+
[routerLink]="breadcrumb.url"
58+
[title]="breadcrumb.label"
59+
class="breadcrumb-label"
60+
>
61+
{{ getTrimmedLabel(breadcrumb.label) }}
62+
</a>
3863
</ng-container>
3964
<ng-template #noLink>
40-
<span>{{ breadcrumb.label }}</span>
65+
<span class="breadcrumb-label" [title]="breadcrumb.label">
66+
{{ getTrimmedLabel(breadcrumb.label) }}
67+
</span>
4168
</ng-template>
4269
</li>
43-
<span *ngIf="!last" class="separator">{{ separator }}</span>
70+
<span *ngIf="!last" class="{{ separatorClass }}">{{ separator }}</span>
4471
</ng-container>
4572
</ng-template>
4673
</ul>

projects/arc-lib/src/lib/components/breadcrumb/breadcrumb.component.scss

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
.breadcrumb-item {
1010
display: flex;
1111
align-items: center;
12-
font-size: 14px;
12+
font-size: 0.875rem;
1313
color: #555;
1414

1515
a {
@@ -25,6 +25,7 @@
2525
font-weight: 600;
2626
color: #333;
2727
}
28+
2829
&.clickable {
2930
cursor: pointer;
3031
color: #007bff;
@@ -34,11 +35,20 @@
3435
color: #0056b3;
3536
}
3637
}
38+
39+
.breadcrumb-label {
40+
max-width: 12rem; // You can adjust this
41+
overflow: hidden;
42+
text-overflow: ellipsis;
43+
white-space: nowrap;
44+
display: inline-block;
45+
vertical-align: middle;
46+
}
3747
}
3848

3949
.separator {
40-
margin: 0 6px;
50+
margin: 0 0.375rem;
4151
color: #aaa;
42-
font-size: 14px;
52+
font-size: 0.875rem;
4353
}
4454
}

projects/arc-lib/src/lib/components/breadcrumb/breadcrumb.component.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export class BreadcrumbComponent implements OnInit {
2020
@Input() maxItems = 8;
2121
@Input() separatorClass = 'separator';
2222
@Input() itemClass = 'breadcrumb-item';
23+
@Input() maxLabelLength = 30;
2324

2425
expanded = false;
2526
private destroy$ = new Subject<void>();
@@ -31,6 +32,11 @@ export class BreadcrumbComponent implements OnInit {
3132
}
3233
});
3334
}
35+
getTrimmedLabel(label: string): string {
36+
return label.length > this.maxLabelLength
37+
? label.slice(0, this.maxLabelLength).trimEnd() + '…'
38+
: label;
39+
}
3440
ngOnDestroy(): void {
3541
this.destroy$.next();
3642
this.destroy$.complete();

projects/arc-lib/src/lib/components/breadcrumb/breadcrumb.service.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ export class BreadcrumbService {
6666
const asyncConfig = data?.asyncBreadcrumb;
6767
if (asyncConfig?.service && asyncConfig?.method) {
6868
const params = route.paramMap;
69-
const paramValue = params.get('id');
69+
const paramValue = Object.fromEntries(
70+
params.keys.map(k => [k, params.get(k)]),
71+
);
7072
const fallback =
7173
asyncConfig.fallbackLabel?.(params) || this._toTitleCase(path);
7274
const loadingLabel = asyncConfig.loadingLabel || fallback;

projects/arc/src/app/main/bread-crumb-introduction/bread-crumb-introduction.component.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,20 @@ <h3>3. Breadcrumb Inputs</h3>
121121
<td>itemClass</td>
122122
<td>Custom class applied to each breadcrumb element.</td>
123123
</tr>
124+
<tr>
125+
<td>maxLabelLength</td>
126+
<td>
127+
Maximum number of characters shown in each breadcrumb label before it
128+
gets trimmed with an ellipsis (…)
129+
</td>
130+
</tr>
131+
<tr>
132+
<td>maxItems</td>
133+
<td>
134+
Maximum number of breadcrumb items to display before collapsing the
135+
middle items into an expandable “...” element
136+
</td>
137+
</tr>
124138
</tbody>
125139
</table>
126140
</div>

projects/arc/src/app/main/main.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
[maxItems]="2"
3232
[itemClass]="'breadcrumb-item'"
3333
[separatorClass]="'separator'"
34+
[maxLabelLength]="10"
3435
></app-breadcrumb>
3536
<router-outlet class="main-router"></router-outlet>
3637
</nb-layout-column>

0 commit comments

Comments
 (0)