Skip to content

Commit 23e90ee

Browse files
authored
Merge pull request #3 from actionanand/feature/1-angular-versions
Feature/1 angular versions
2 parents a628857 + c9a84bc commit 23e90ee

18 files changed

Lines changed: 2066 additions & 10 deletions

src/app/app.html

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,36 @@
1-
<div style="text-align: center; color: green; font-size: 24px;"> {{title()}} </div>
1+
<main class="page">
2+
<section class="hero" aria-labelledby="page-title">
3+
<div class="hero__content">
4+
<p class="hero__eyebrow">Angular release explorer</p>
5+
<h1 id="page-title">Major changes from Angular 8 to Angular 22</h1>
6+
<p>
7+
A practical, version-by-version guide for teams moving from Ivy-era Angular to standalone,
8+
signals, modern templates, and Angular 22 signal-first defaults.
9+
</p>
10+
</div>
211

3-
<router-outlet />
12+
<div class="hero__panel" aria-label="Current focus">
13+
<span>Current focus</span>
14+
<strong>{{ selectedRelease().label }}</strong>
15+
<p>{{ selectedRelease().theme }}</p>
16+
</div>
17+
</section>
18+
19+
<app-summary-panel [releases]="releases" />
20+
21+
<section class="section" aria-label="Select a release">
22+
<app-release-timeline
23+
[releases]="releases"
24+
[selectedKey]="selectedKey()"
25+
(selected)="selectRelease($event)"
26+
/>
27+
</section>
28+
29+
<section class="section">
30+
<app-release-detail [release]="selectedRelease()" />
31+
</section>
32+
33+
<section class="section">
34+
<app-compare-panel [releases]="releases" />
35+
</section>
36+
</main>

src/app/app.scss

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
:host {
2+
display: block;
3+
min-height: 100vh;
4+
background: #f8fafc;
5+
color: #172033;
6+
}
7+
8+
.page {
9+
display: grid;
10+
gap: 1.5rem;
11+
width: min(calc(100% - 2rem), 76rem);
12+
margin: 0 auto;
13+
padding: 2rem 0 3rem;
14+
}
15+
16+
.page > * {
17+
min-width: 0;
18+
}
19+
20+
.hero {
21+
display: grid;
22+
grid-template-columns: minmax(0, 1fr) minmax(16rem, 22rem);
23+
gap: 1.25rem;
24+
align-items: end;
25+
padding: 1rem 0 0.25rem;
26+
}
27+
28+
.hero > * {
29+
min-width: 0;
30+
}
31+
32+
.hero__content {
33+
display: grid;
34+
gap: 0.85rem;
35+
}
36+
37+
.hero__eyebrow {
38+
margin: 0;
39+
color: #1967d2;
40+
font-size: 0.86rem;
41+
font-weight: 900;
42+
text-transform: uppercase;
43+
}
44+
45+
h1 {
46+
max-width: 18ch;
47+
margin: 0;
48+
color: #172033;
49+
font-size: clamp(2rem, 5vw, 4rem);
50+
line-height: 1.02;
51+
}
52+
53+
.hero__content p:not(.hero__eyebrow) {
54+
max-width: 48rem;
55+
margin: 0;
56+
color: #314158;
57+
font-size: clamp(1rem, 1.5vw, 1.18rem);
58+
line-height: 1.65;
59+
}
60+
61+
.hero__panel {
62+
display: grid;
63+
gap: 0.4rem;
64+
border: 1px solid #cfd8e3;
65+
border-radius: 8px;
66+
background: #ffffff;
67+
padding: 1rem;
68+
box-shadow: 0 18px 45px rgba(23, 32, 51, 0.09);
69+
}
70+
71+
.hero__panel span {
72+
color: #1967d2;
73+
font-size: 0.78rem;
74+
font-weight: 900;
75+
text-transform: uppercase;
76+
}
77+
78+
.hero__panel strong {
79+
color: #172033;
80+
font-size: 1.5rem;
81+
}
82+
83+
.hero__panel p {
84+
margin: 0;
85+
color: #4a5568;
86+
line-height: 1.5;
87+
}
88+
89+
.section,
90+
app-summary-panel {
91+
display: block;
92+
min-width: 0;
93+
max-width: 100%;
94+
border: 1px solid #d8e0ea;
95+
border-radius: 8px;
96+
background: rgba(255, 255, 255, 0.78);
97+
padding: 1rem;
98+
box-shadow: 0 1px 0 rgba(16, 24, 40, 0.04);
99+
}
100+
101+
@media (max-width: 760px) {
102+
.page {
103+
width: min(calc(100% - 1rem), 76rem);
104+
padding-top: 1rem;
105+
}
106+
107+
.hero {
108+
grid-template-columns: 1fr;
109+
padding-top: 1rem;
110+
}
111+
112+
h1 {
113+
max-width: 11ch;
114+
}
115+
116+
.section,
117+
app-summary-panel {
118+
padding: 0.85rem;
119+
}
120+
}

src/app/app.spec.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,21 @@ describe('App', () => {
1414
expect(app).toBeTruthy();
1515
});
1616

17-
it('should render title', async () => {
17+
it('should render the release explorer title', async () => {
1818
const fixture = TestBed.createComponent(App);
1919
await fixture.whenStable();
2020
const compiled = fixture.nativeElement as HTMLElement;
21-
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, angular-22');
21+
expect(compiled.querySelector('h1')?.textContent).toContain(
22+
'Major changes from Angular 8 to Angular 22',
23+
);
24+
});
25+
26+
it('should include the Angular 21.2 milestone', async () => {
27+
const fixture = TestBed.createComponent(App);
28+
await fixture.whenStable();
29+
const compiled = fixture.nativeElement as HTMLElement;
30+
31+
expect(compiled.textContent).toContain('Angular 21.2');
32+
expect(compiled.textContent).toContain('Arrow functions directly in templates');
2233
});
2334
});

src/app/app.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,27 @@
1-
import { Component, signal } from '@angular/core';
2-
import { RouterOutlet } from '@angular/router';
1+
import { Component, computed, signal } from '@angular/core';
2+
import { ComparePanel } from './components/compare-panel/compare-panel';
3+
import { ReleaseDetail } from './components/release-detail/release-detail';
4+
import { ReleaseTimeline } from './components/release-timeline/release-timeline';
5+
import { SummaryPanel } from './components/summary-panel/summary-panel';
6+
import { AngularRelease, angularReleases } from './data/angular-releases';
37

48
@Component({
59
selector: 'app-root',
6-
imports: [RouterOutlet],
10+
imports: [ComparePanel, ReleaseDetail, ReleaseTimeline, SummaryPanel],
711
templateUrl: './app.html',
8-
styleUrl: './app.scss'
12+
styleUrl: './app.scss',
913
})
1014
export class App {
11-
protected readonly title = signal('angular-22');
15+
protected readonly releases = angularReleases;
16+
protected readonly selectedKey = signal('22');
17+
18+
protected readonly selectedRelease = computed<AngularRelease>(() => {
19+
const release = this.releases.find((item) => item.key === this.selectedKey());
20+
21+
return release ?? this.releases[this.releases.length - 1];
22+
});
23+
24+
protected selectRelease(key: string): void {
25+
this.selectedKey.set(key);
26+
}
1227
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
:host {
2+
display: block;
3+
min-width: 0;
4+
}
5+
6+
.example {
7+
min-width: 0;
8+
border: 1px solid #d8e0ea;
9+
border-radius: 8px;
10+
background: #111827;
11+
color: #e5edf7;
12+
overflow: hidden;
13+
}
14+
15+
.example__header {
16+
display: flex;
17+
align-items: center;
18+
justify-content: space-between;
19+
gap: 1rem;
20+
border-bottom: 1px solid rgba(255, 255, 255, 0.14);
21+
padding: 0.8rem 1rem;
22+
}
23+
24+
h3 {
25+
margin: 0;
26+
color: #ffffff;
27+
font-size: 0.98rem;
28+
line-height: 1.35;
29+
}
30+
31+
span {
32+
border: 1px solid rgba(255, 255, 255, 0.24);
33+
border-radius: 999px;
34+
padding: 0.15rem 0.55rem;
35+
color: #b9c7d8;
36+
font-size: 0.78rem;
37+
font-weight: 700;
38+
}
39+
40+
pre {
41+
max-width: 100%;
42+
margin: 0;
43+
padding: 1rem;
44+
overflow-x: auto;
45+
background: #0b1020;
46+
}
47+
48+
code {
49+
font-family: 'Cascadia Code', 'SFMono-Regular', Consolas, 'Liberation Mono', monospace;
50+
font-size: 0.86rem;
51+
line-height: 1.6;
52+
white-space: pre;
53+
}
54+
55+
p {
56+
margin: 0;
57+
padding: 0.9rem 1rem 1rem;
58+
color: #d7e0ed;
59+
font-size: 0.92rem;
60+
line-height: 1.55;
61+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Component, input } from '@angular/core';
2+
import { CodeExample } from '../../data/angular-releases';
3+
4+
@Component({
5+
selector: 'app-code-example',
6+
template: `
7+
<article class="example">
8+
<div class="example__header">
9+
<h3>{{ example().title }}</h3>
10+
<span>{{ example().language }}</span>
11+
</div>
12+
<pre><code>{{ example().code }}</code></pre>
13+
<p>{{ example().explanation }}</p>
14+
</article>
15+
`,
16+
styleUrl: './code-example.scss',
17+
})
18+
export class CodeExampleComponent {
19+
readonly example = input.required<CodeExample>();
20+
}

0 commit comments

Comments
 (0)