Skip to content

Commit 105ddf9

Browse files
committed
feat: move teams banner to global layout with dismiss functionality
- Created new TeamsBanner component with localStorage-based dismiss - Added banner above navbar in main Layout component - Removed homepage-only banner from DocBreadcrumbs - Banner now appears on all pages and can be dismissed - Dismiss state persists across sessions via localStorage
1 parent 7969511 commit 105ddf9

File tree

5 files changed

+177
-54
lines changed

5 files changed

+177
-54
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import React, { useState, useEffect } from 'react';
2+
import styles from './styles.module.css';
3+
4+
export function TeamsBanner(): React.ReactElement | null {
5+
const [isVisible, setIsVisible] = useState(false);
6+
7+
useEffect(() => {
8+
// Check localStorage to see if banner was dismissed
9+
const isDismissed = localStorage.getItem('teamsBannerDismissed');
10+
if (!isDismissed) {
11+
setIsVisible(true);
12+
}
13+
}, []);
14+
15+
useEffect(() => {
16+
// Add or remove body class based on visibility
17+
if (isVisible) {
18+
document.body.classList.add('teams-banner-visible');
19+
} else {
20+
document.body.classList.remove('teams-banner-visible');
21+
}
22+
23+
// Cleanup on unmount
24+
return () => {
25+
document.body.classList.remove('teams-banner-visible');
26+
};
27+
}, [isVisible]);
28+
29+
const handleDismiss = () => {
30+
setIsVisible(false);
31+
localStorage.setItem('teamsBannerDismissed', 'true');
32+
};
33+
34+
if (!isVisible) {
35+
return null;
36+
}
37+
38+
return (
39+
<div className={styles.teamsBanner} role="banner" aria-label="Roo Code Teams announcement">
40+
<div className={styles.teamsBannerContent}>
41+
<span className={styles.teamsBannerHeadline}>Ship Faster with Roo Code Teams.</span>
42+
<a
43+
className={styles.teamsBannerLink}
44+
href="https://app.roocode.com/l/teams?utm_source=docs&utm_medium=banner&utm_campaign=teams_promo"
45+
target="_blank"
46+
rel="noopener noreferrer">
47+
Get early access now.
48+
</a>
49+
</div>
50+
<button
51+
className={styles.teamsBannerDismiss}
52+
onClick={handleDismiss}
53+
aria-label="Dismiss banner"
54+
type="button">
55+
<svg
56+
width="16"
57+
height="16"
58+
viewBox="0 0 16 16"
59+
fill="none"
60+
xmlns="http://www.w3.org/2000/svg"
61+
aria-hidden="true">
62+
<path
63+
d="M12.5 3.5L3.5 12.5M3.5 3.5L12.5 12.5"
64+
stroke="currentColor"
65+
strokeWidth="1.5"
66+
strokeLinecap="round"
67+
strokeLinejoin="round"
68+
/>
69+
</svg>
70+
</button>
71+
</div>
72+
);
73+
}
74+
75+
export default TeamsBanner;
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
.teamsBanner {
2+
position: fixed;
3+
top: 0;
4+
left: 0;
5+
right: 0;
6+
z-index: 1000; /* Above navbar which typically has z-index: 999 */
7+
display: flex;
8+
align-items: center;
9+
justify-content: center;
10+
padding: 0.85rem 1.1rem;
11+
background: linear-gradient(90deg, #4f46e5, #2563eb);
12+
border-bottom: 1px solid rgba(147, 197, 253, 0.5);
13+
color: #ffffff;
14+
box-shadow: 0 12px 30px rgba(37, 99, 235, 0.25);
15+
}
16+
17+
.teamsBannerContent {
18+
display: flex;
19+
align-items: center;
20+
gap: 0.75rem;
21+
}
22+
23+
.teamsBannerHeadline {
24+
font-weight: 600;
25+
}
26+
27+
.teamsBannerLink {
28+
color: #ffffff;
29+
font-weight: 600;
30+
text-decoration: underline;
31+
text-decoration-color: rgba(255, 255, 255, 0.7);
32+
text-decoration-thickness: 2px;
33+
}
34+
35+
.teamsBannerLink:hover {
36+
color: #ffffff;
37+
text-decoration-color: rgba(255, 255, 255, 0.95);
38+
}
39+
40+
.teamsBannerDismiss {
41+
position: absolute;
42+
right: 1rem;
43+
background: transparent;
44+
border: none;
45+
color: #ffffff;
46+
cursor: pointer;
47+
padding: 0.25rem;
48+
display: flex;
49+
align-items: center;
50+
justify-content: center;
51+
border-radius: 4px;
52+
transition: background-color 0.2s ease;
53+
}
54+
55+
.teamsBannerDismiss:hover {
56+
background-color: rgba(255, 255, 255, 0.1);
57+
}
58+
59+
.teamsBannerDismiss:focus {
60+
outline: 2px solid rgba(255, 255, 255, 0.5);
61+
outline-offset: 2px;
62+
}
63+
64+
/* Add padding to body when banner is visible */
65+
:global(body.teams-banner-visible) {
66+
padding-top: 52px; /* Height of the banner */
67+
}
68+
69+
/* Adjust navbar position when banner is visible */
70+
:global(body.teams-banner-visible) :global(.navbar) {
71+
top: 52px !important; /* Push navbar below banner */
72+
}
73+
74+
@media (max-width: 768px) {
75+
.teamsBanner {
76+
padding: 1rem;
77+
}
78+
79+
.teamsBannerContent {
80+
flex-direction: column;
81+
align-items: flex-start;
82+
gap: 0.5rem;
83+
padding-right: 2rem; /* Space for close button */
84+
}
85+
86+
.teamsBannerDismiss {
87+
right: 0.5rem;
88+
top: 50%;
89+
transform: translateY(-50%);
90+
}
91+
92+
/* Adjust padding for mobile */
93+
:global(body.teams-banner-visible) {
94+
padding-top: 72px; /* Slightly more height on mobile */
95+
}
96+
97+
:global(body.teams-banner-visible) :global(.navbar) {
98+
top: 72px !important;
99+
}
100+
}

src/theme/DocBreadcrumbs/index.tsx

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,24 +60,9 @@ export default function DocBreadcrumbs(): ReactNode {
6060
return null;
6161
}
6262

63-
const lastBreadcrumb = breadcrumbs[breadcrumbs.length - 1];
64-
const showTeamsBanner = lastBreadcrumb?.label === 'Welcome';
65-
6663
return (
6764
<>
6865
<DocBreadcrumbsStructuredData breadcrumbs={breadcrumbs} />
69-
{showTeamsBanner && (
70-
<div className={styles.teamsPromo} role="complementary" aria-label="Roo Code Teams announcement">
71-
<span className={styles.teamsPromoHeadline}>Ship Faster with Roo Code Teams.</span>
72-
<a
73-
className={styles.teamsPromoLink}
74-
href="https://app.roocode.com/l/teams?utm_source=docs&utm_medium=banner&utm_campaign=teams_promo"
75-
target="_blank"
76-
rel="noopener noreferrer">
77-
Get early access now.
78-
</a>
79-
</div>
80-
)}
8166
<nav
8267
className={clsx(
8368
ThemeClassNames.docs.docBreadcrumbs,

src/theme/DocBreadcrumbs/styles.module.css

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -14,42 +14,3 @@
1414
margin: 0;
1515
flex: 1;
1616
}
17-
18-
.teamsPromo {
19-
display: flex;
20-
align-items: center;
21-
justify-content: center;
22-
gap: 0.75rem;
23-
padding: 0.85rem 1.1rem;
24-
border-radius: calc(var(--radius) + 8px);
25-
background: linear-gradient(90deg, #4f46e5, #2563eb);
26-
border: 1px solid rgba(147, 197, 253, 0.5);
27-
margin-bottom: 1rem;
28-
color: #ffffff;
29-
box-shadow: 0 12px 30px rgba(37, 99, 235, 0.25);
30-
}
31-
32-
.teamsPromoHeadline {
33-
font-weight: 600;
34-
}
35-
36-
.teamsPromoLink {
37-
color: #ffffff;
38-
font-weight: 600;
39-
text-decoration: underline;
40-
text-decoration-color: rgba(255, 255, 255, 0.7);
41-
text-decoration-thickness: 2px;
42-
}
43-
44-
.teamsPromoLink:hover {
45-
text-decoration-color: rgba(255, 255, 255, 0.95);
46-
}
47-
48-
@media (max-width: 768px) {
49-
.teamsPromo {
50-
flex-direction: column;
51-
align-items: flex-start;
52-
gap: 0.5rem;
53-
padding: 1rem;
54-
}
55-
}

src/theme/Layout/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import OriginalLayout from '@theme-original/Layout';
33
import { AnimatedBackground } from '../../components/AnimatedBackground';
44
import { CookieConsent } from '../../components/CookieConsent';
55
import { PostHogProvider } from '../../components/PostHogProvider';
6+
import { TeamsBanner } from '../../components/TeamsBanner';
67

78
export default function Layout(props) {
89
return (
910
<PostHogProvider>
11+
<TeamsBanner />
1012
<AnimatedBackground />
1113
<OriginalLayout {...props} />
1214
<CookieConsent />

0 commit comments

Comments
 (0)