Skip to content

Commit 08bb41c

Browse files
committed
Program: energizing tabs
1 parent 0554a01 commit 08bb41c

4 files changed

Lines changed: 142 additions & 33 deletions

File tree

src/app/components/CommunityResources.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const COMMUNITY_RESOURCES: Resource[] = [
3636
export default function CommunityResources() {
3737
return (
3838
<>
39-
<div className="wrapper-full bg-brand-dark text-white">
39+
<div className="wrapper-full">
4040
<div className="wrapper py-6 my-6">
4141
<h3 className="h3">Community Resources</h3>
4242
<div className="d-md-flex">

src/app/program/Content.tsx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//
2+
// Copyright (c) Microsoft.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
'use client';
7+
8+
import { useState, useEffect } from 'react';
9+
import Contributing from './Contributing';
10+
import Overview from './Overview';
11+
import Releasing from './Releasing';
12+
import Tools from './Tools';
13+
import Using from './Using';
14+
15+
const FIRST_TAB = 'program-overview';
16+
17+
// If no JavaScript, no content at all.
18+
// Otherwise, show the active content appropriately.
19+
20+
const ProgramDynamicContent = () => {
21+
// Initialize with a default value
22+
const [activeTab, setActiveTab] = useState(FIRST_TAB);
23+
24+
// Update the active tab once the component mounts in the browser
25+
useEffect(() => {
26+
const hash = window.location.hash;
27+
const newActiveTab = hash ? hash.replace('#', '') : FIRST_TAB;
28+
setActiveTab(newActiveTab);
29+
30+
const handleHashChange = () => {
31+
const newHash = window.location.hash;
32+
const newTab = newHash ? newHash.replace('#', '') : FIRST_TAB;
33+
setActiveTab(newTab);
34+
}
35+
window.addEventListener('hashchange', handleHashChange);
36+
return () => {
37+
window.removeEventListener('hashchange', handleHashChange);
38+
}
39+
}, [setActiveTab]);
40+
41+
return (
42+
<div className="col-md-10 col-lg-7 mx-auto">
43+
<div className={['tabs__content', activeTab === 'program-overview' ? 'is-active' : ''].filter(x => x).join(' ')} data-tab="program-overview">
44+
<Overview />
45+
</div>
46+
<div className={['tabs__content', activeTab === 'program-tools' ? 'is-active' : ''].filter(x => x).join(' ')} data-tab="program-tools">
47+
<Tools />
48+
</div>
49+
<div className={['tabs__content', activeTab === 'program-using' ? 'is-active' : ''].filter(x => x).join(' ')} data-tab="program-using">
50+
<Using />
51+
</div>
52+
<div className={['tabs__content', activeTab === 'program-contributing' ? 'is-active' : ''].filter(x => x).join(' ')} data-tab="program-contributing">
53+
<Contributing />
54+
</div>
55+
<div className={['tabs__content', activeTab === 'program-releasing' ? 'is-active' : ''].filter(x => x).join(' ')} data-tab="program-releasing">
56+
<Releasing />
57+
</div>
58+
</div>
59+
);
60+
}
61+
62+
export default ProgramDynamicContent;

src/app/program/Tabs.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//
2+
// Copyright (c) Microsoft.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
'use client';
7+
8+
import { useState, useEffect } from 'react';
9+
10+
const FIRST_TAB = 'program-overview';
11+
12+
const ProgramTabs = () => {
13+
// Initialize with a default value
14+
const [activeTab, setActiveTab] = useState(FIRST_TAB);
15+
16+
// Update the active tab once the component mounts in the browser
17+
useEffect(() => {
18+
const hash = window.location.hash;
19+
const newActiveTab = hash ? hash.replace('#', '') : FIRST_TAB;
20+
setActiveTab(newActiveTab);
21+
22+
const handleHashChange = () => {
23+
const newHash = window.location.hash;
24+
const newTab = newHash ? newHash.replace('#', '') : FIRST_TAB;
25+
setActiveTab(newTab);
26+
}
27+
window.addEventListener('hashchange', handleHashChange);
28+
return () => {
29+
window.removeEventListener('hashchange', handleHashChange);
30+
}
31+
}, [setActiveTab]);
32+
33+
return (
34+
<div className="tabs__tabs" role="tablist">
35+
<a className={['tabs__tab', activeTab === 'program-overview' ? 'is-active' : ''].filter(x => x).join(' ')} role="tab" href="#program-overview" data-tab="program-overview">Overview</a>
36+
<a className={['tabs__tab', activeTab === 'program-tools' ? 'is-active' : ''].filter(x => x).join(' ')} role="tab" href="#program-tools" data-tab="program-tools">Tools &amp; resources</a>
37+
<a className={['tabs__tab', activeTab === 'program-using' ? 'is-active' : ''].filter(x => x).join(' ')} role="tab" href="#program-using" data-tab="program-using">Using open source</a>
38+
<a className={['tabs__tab', activeTab === 'program-contributing' ? 'is-active' : ''].filter(x => x).join(' ')} role="tab" href="#program-contributing" data-tab="program-contributing">Contributing</a>
39+
<a className={['tabs__tab', activeTab === 'program-releasing' ? 'is-active' : ''].filter(x => x).join(' ')} role="tab" href="#program-releasing" data-tab="program-releasing">Releasing projects</a>
40+
</div>
41+
);
42+
}
43+
44+
export default ProgramTabs;

src/app/program/page.tsx

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@
33
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
44
//
55

6-
import Contributing from "./Contributing";
7-
import Overview from "./Overview";
8-
import Releasing from "./Releasing";
9-
import Tools from "./Tools";
10-
import Using from "./Using";
11-
126
import { Metadata } from 'next';
137

8+
import ProgramDynamicContent from './Content';
9+
import Contributing from './Contributing';
10+
import Overview from './Overview';
11+
import Releasing from './Releasing';
12+
import ProgramTabs from './Tabs';
13+
import Tools from './Tools';
14+
import Using from './Using';
15+
1416
export const metadata: Metadata = {
1517
title: 'Microsoft\'s Open Source Program',
1618
};
@@ -58,37 +60,38 @@ export default function Program() {
5860
<nav className="wrapper my-6" data-require-javascript="yes" data-javascript-show="immediate">
5961
<div className="col-md-10 col-lg-7 mx-auto">
6062
<div className="tabs__tabs" role="tablist">
61-
<a className="tabs__tab is-active" role="tab" href="#program-overview" data-tab="program-overview">Overview</a>
62-
<a className="tabs__tab" role="tab" href="#program-tools" data-tab="program-tools">Tools &amp; resources</a>
63-
<a className="tabs__tab" role="tab" href="#program-using" data-tab="program-using">Using open source</a>
64-
<a className="tabs__tab" role="tab" href="#program-contributing" data-tab="program-contributing">Contributing</a>
65-
<a className="tabs__tab" role="tab" href="#program-releasing" data-tab="program-releasing">Releasing projects</a>
63+
<ProgramTabs />
6664
</div>
6765
</div>
6866
</nav>
6967
<div className="wrapper my-6 pt-lg-3 pb-4">
70-
<div className="col-md-10 col-lg-7 mx-auto">
71-
<noscript><h2>Overview</h2></noscript>
72-
<div className="tabs__content is-active" data-tab="program-overview">
73-
<Overview />
74-
</div>
75-
<div className="tabs__content" data-tab="program-tools">
76-
<noscript><h2>Tools &amp; resources</h2></noscript>
77-
<Tools />
68+
{/* No JavaScript entire set of content */}
69+
<noscript>
70+
<div className="col-md-10 col-lg-7 mx-auto">
71+
<h2>Overview</h2>
72+
<div className="tabs__content is-active" data-tab="program-overview">
73+
<Overview />
74+
</div>
75+
<div className="tabs__content" data-tab="program-tools">
76+
<h2>Tools &amp; resources</h2>
77+
<Tools />
78+
</div>
79+
<div className="tabs__content" data-tab="program-using">
80+
<h2>Using open source</h2>
81+
<Using />
82+
</div>
83+
<div className="tabs__content" data-tab="program-contributing">
84+
<h2>Contributing</h2>
85+
<Contributing />
86+
</div>
87+
<div className="tabs__content" data-tab="program-releasing">
88+
<h2>Releasing projects</h2>
89+
<Releasing />
90+
</div>
7891
</div>
79-
<div className="tabs__content" data-tab="program-using">
80-
<noscript><h2>Using open source</h2></noscript>
81-
<Using />
82-
</div>
83-
<div className="tabs__content" data-tab="program-contributing">
84-
<noscript><h2>Contributing</h2></noscript>
85-
<Contributing />
86-
</div>
87-
<div className="tabs__content" data-tab="program-releasing">
88-
<noscript><h2>Releasing projects</h2></noscript>
89-
<Releasing />
90-
</div>
91-
</div>
92+
</noscript>
93+
{/* Equivalent content for JavaScript */}
94+
<ProgramDynamicContent />
9295
</div>
9396
</div>
9497
</article>

0 commit comments

Comments
 (0)