Copilot commented on code in PR #1962:
URL: https://github.com/apache/apisix-website/pull/1962#discussion_r2807191230
##########
website/src/css/customTheme.scss:
##########
@@ -291,23 +512,63 @@ a:hover {
}
.hero-sec-wrap {
- display: block;
- height: fit-content;
+ display: flex !important;
+ height: 100vh !important;
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%) !important;
+ position: relative !important;
}
.homeCanvas-overlay {
position: absolute;
- width: 100vw;
- height: 50vh;
- background: #ebe6dc;
- top: -1px;
- right: 0;
+ width: 100%;
+ height: 100%;
+ background: transparent;
+ top: 0;
+ left: 0;
+ z-index: 1;
+ pointer-events: none;
}
- .hero-text {
- height: 50%;
+ .homeCanvas {
+ width: 100% !important;
+ height: 100% !important;
+ position: absolute !important;
+ top: 0 !important;
+ left: 0 !important;
+ z-index: 0 !important;
+ opacity: 0.2 !important;
+ }
+
+ .hero-infograph {
+ position: absolute !important;
+ top: 0 !important;
+ left: 0 !important;
+ width: 100% !important;
+ height: 100% !important;
+ z-index: 0 !important;
+ pointer-events: none !important;
+ }
+
+ .add-margin {
+ position: absolute;
+ top: 0;
+ left: 0;
width: 100%;
- padding: 5rem 0 0 6vw;
+ height: 100%;
+ z-index: 0;
+ pointer-events: none;
+ }
+
+ .hero-text {
+ height: 100%;
+ width: 50%;
+ padding: 0 4vw 0 6vw;
+ position: relative;
+ z-index: 2;
+ display: flex;
+ flex-wrap: wrap;
+ align-content: center;
+ box-sizing: border-box;
}
Review Comment:
The media query @media only screen and (min-width: 300px) and (max-width:
1100px) in customTheme.scss defines alternative hero section styles that
conflict with the new styles in hero.scss. For example, at line 515-519 it sets
.hero-sec-wrap to display: flex with a gradient background, but hero.scss sets
it to display: block with transparent background. This creates a specificity
battle and inconsistent styling depending on which styles load last. The hero
section styles should be consolidated into hero.scss, and this conflicting code
in customTheme.scss should be removed or refactored.
##########
website/src/css/landing-sections/hero.scss:
##########
@@ -158,3 +312,339 @@
width: 40vw;
}
}
+
+@media (max-width: 996px) {
+ .hero-sec-wrap {
+ display: block !important;
+ height: 100vh !important;
+ min-height: 100vh;
+ }
+
+ .hero-text {
+ width: 90%;
+ max-width: 800px;
+ padding: 40px 30px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ text-align: center;
+ }
+
+ .hero-title {
+ width: 100%;
+ max-width: 100%;
+ font-size: 3rem;
+ }
+
+ .hero-title::after {
+ width: 60px;
+ left: 50%;
+ transform: translateX(-50%);
+ }
+
+ .hero-subtitle {
+ width: 100%;
+ padding-right: 0;
+ }
+
+ .homeCanvas {
+ width: 100% !important;
+ height: 100% !important;
+ opacity: 0.85 !important;
+ }
+
+ .hero-ctas {
+ justify-content: center;
+ gap: 15px;
+ }
+}
+
+@media (max-width: 768px) {
+ .hero-text {
+ width: 95%;
+ max-width: 600px;
+ padding: 30px 25px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ }
+
+ .hero-title {
+ font-size: 2.5rem;
+ max-width: 100%;
+ }
+
+ .hero-subtitle {
+ font-size: 1rem;
+ }
+
+ .btn {
+ padding: 16px 32px;
+ font-size: 1.1rem;
+ }
+}
+
+@media (max-width: 768px) {
+ .hero-sec-wrap {
+ width: 100vw !important;
+ height: 100vh !important;
+ min-height: 100vh;
+ margin: 0 !important;
+ padding: 0 !important;
+ left: 50% !important;
+ right: 50% !important;
+ margin-left: -50vw !important;
+ margin-right: -50vw !important;
+ overflow: hidden;
+ position: relative;
+ }
+
+ .homeCanvas {
+ width: 100% !important;
+ height: 100% !important;
+ opacity: 0.9 !important;
+ filter: none !important;
+ backdrop-filter: none !important;
+ }
+
+ .hero-text {
+ width: 95%;
+ max-width: none;
+ padding: 20px 15px;
+ margin: 0;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ filter: none !important;
+ backdrop-filter: none !important;
+ text-align: center;
+ background: rgba(0, 0, 0, 0.4);
+ border-radius: 10px;
+ box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5);
+ max-height: 85vh;
+ overflow-y: auto;
+ }
Review Comment:
The hero-text container at mobile breakpoints (768px and 480px) has
overflow-y: auto which will add a scrollbar if content exceeds max-height
(85vh/80vh). This creates a poor user experience where users have to scroll
within a scrollable container that's itself on a scrollable page. This nested
scrolling is confusing and should be avoided. Consider either increasing
max-height to fit all content or restructuring the layout to avoid the need for
internal scrolling.
##########
website/src/css/landing-sections/hero.scss:
##########
@@ -23,98 +52,223 @@
.hero-subtitle {
z-index: 100;
- font-size: 1.1rem;
+ font-size: clamp(0.6rem, 2vw, 1.3rem);
font-family: MaisonNeue-Light, sans-serif;
position: relative;
- color: #615d5d;
- line-height: 30px;
- letter-spacing: 0.2px;
+ color: #f1f5f9;
+ line-height: 1.6;
+ letter-spacing: 0.3px;
margin: 25px 0;
- padding-right: 20px;
+ padding-right: 0;
animation-delay: 0.25s;
+ width: 100%;
+ max-width: 100%;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ hyphens: auto;
+ box-sizing: border-box;
+ text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6), 0 0 15px rgba(0, 0, 0, 0.4);
+ font-weight: 500;
+}
+
+.hero-subtitle[style*="color: #E8433E"] {
+ color: #ff4757 !important;
+ background: none !important;
+ -webkit-background-clip: unset !important;
+ -webkit-text-fill-color: unset !important;
+ background-clip: unset !important;
+ font-weight: 800;
+ font-size: clamp(0.8rem, 3vw, 2.2rem);
+ text-shadow: 2px 2px 6px rgba(0, 0, 0, 0.7), 0 0 20px rgba(0, 0, 0, 0.5);
+ margin: 20px 0 30px 0;
}
.hero-ctas {
display: flex;
align-items: center;
animation-delay: 0.5;
+ gap: 20px;
+ margin-top: 32px;
}
.hero-sec-wrap {
- display: flex;
- background: #f4f4f4ad;
- height: 100vh;
+ display: block !important;
+ background: transparent !important;
+ height: 100vh !important;
+ position: relative !important;
+ width: 100% !important;
+ margin-top: -60px !important;
+ padding-top: 60px !important;
}
+
.homeCanvas-overlay {
position: absolute;
- width: 50vw;
- height: 100vh;
- background: #fff;
- top: -1px;
- right: 0;
+ width: 100%;
+ height: 100%;
+ background: transparent;
+ top: 0;
+ left: 0;
+ z-index: 1;
+ pointer-events: none;
}
.homeCanvas {
- width: 50vw;
- height: 100vh;
+ width: 100% !important;
+ height: 100% !important;
+ position: absolute !important;
+ top: 0 !important;
+ left: 0 !important;
+ z-index: 1 !important;
+ opacity: 1 !important;
+ animation: float 6s ease-in-out infinite;
+ filter: contrast(1.1) brightness(1.05) saturate(1.1);
+}
+
+.hero-infograph {
+ position: absolute !important;
+ top: -60px !important;
+ left: 0 !important;
+ width: 100% !important;
+ height: calc(100% + 60px) !important;
+ z-index: 1 !important;
+ pointer-events: none !important;
}
+
.hero-text {
height: 100%;
display: flex;
flex-wrap: wrap;
align-content: center;
- width: 50%;
- padding: 0 0 0 6vw;
+ justify-content: center;
+ width: 80%;
+ max-width: 1200px;
+ padding: 60px 40px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ box-sizing: border-box;
+ z-index: 3;
+ text-align: center;
}
Review Comment:
The z-index layering has inconsistencies: .hero-subtitle has z-index: 100,
while .homeCanvas-overlay, .homeCanvas, and .hero-infograph all have z-index:
1, and .hero-text has z-index: 3. The subtitle with z-index: 100 is
unnecessarily high and creates a confusing stacking context, especially since
it's a child of .hero-text (z-index: 3). Child elements don't need such high
z-index values. Consider simplifying the z-index values to create a clear and
logical stacking order (e.g., background: 1, overlay: 2, text container: 3).
##########
website/src/components/sections/Architecture.tsx:
##########
@@ -42,10 +42,10 @@ const Architecture: FC = () => (
</div>
<div className="arch-card-caption">
<p>
- <Translate id="architecture.component.card.caption">
- Apache APISIX is based on NGINX and etcd. Compared with
traditional API Gateways, APISIX
- has features like dynamic routing and hot-loading plugins, etc.
- </Translate>
+ Apache APISIX is based on NGINX and etcd.
+ Compared with traditional API Gateways,
+ APISIX has features like dynamic routing<br />
+ and hot-loading plugins, etc.
Review Comment:
The Translate component with id "architecture.component.card.caption" has
been removed and replaced with hardcoded English text split across multiple
lines with a br tag. This breaks internationalization support - the Chinese
translation in website/i18n/zh/code.json will no longer work. The Translate
component should be retained to maintain i18n functionality, or the text should
be properly refactored while preserving translation support.
```suggestion
<Translate id="architecture.component.card.caption">
Apache APISIX is based on NGINX and etcd. Compared with
traditional API Gateways,
APISIX has features like dynamic routing and hot-loading
plugins, etc.
</Translate>
```
##########
website/src/css/landing-sections/hero.scss:
##########
@@ -23,98 +52,223 @@
.hero-subtitle {
z-index: 100;
- font-size: 1.1rem;
+ font-size: clamp(0.6rem, 2vw, 1.3rem);
font-family: MaisonNeue-Light, sans-serif;
position: relative;
- color: #615d5d;
- line-height: 30px;
- letter-spacing: 0.2px;
+ color: #f1f5f9;
+ line-height: 1.6;
+ letter-spacing: 0.3px;
margin: 25px 0;
- padding-right: 20px;
+ padding-right: 0;
animation-delay: 0.25s;
+ width: 100%;
+ max-width: 100%;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ hyphens: auto;
+ box-sizing: border-box;
+ text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6), 0 0 15px rgba(0, 0, 0, 0.4);
+ font-weight: 500;
+}
+
+.hero-subtitle[style*="color: #E8433E"] {
+ color: #ff4757 !important;
+ background: none !important;
+ -webkit-background-clip: unset !important;
+ -webkit-text-fill-color: unset !important;
+ background-clip: unset !important;
+ font-weight: 800;
+ font-size: clamp(0.8rem, 3vw, 2.2rem);
+ text-shadow: 2px 2px 6px rgba(0, 0, 0, 0.7), 0 0 20px rgba(0, 0, 0, 0.5);
+ margin: 20px 0 30px 0;
}
.hero-ctas {
display: flex;
align-items: center;
animation-delay: 0.5;
+ gap: 20px;
+ margin-top: 32px;
}
.hero-sec-wrap {
- display: flex;
- background: #f4f4f4ad;
- height: 100vh;
+ display: block !important;
+ background: transparent !important;
+ height: 100vh !important;
+ position: relative !important;
+ width: 100% !important;
+ margin-top: -60px !important;
+ padding-top: 60px !important;
}
+
.homeCanvas-overlay {
position: absolute;
- width: 50vw;
- height: 100vh;
- background: #fff;
- top: -1px;
- right: 0;
+ width: 100%;
+ height: 100%;
+ background: transparent;
+ top: 0;
+ left: 0;
+ z-index: 1;
+ pointer-events: none;
}
.homeCanvas {
- width: 50vw;
- height: 100vh;
+ width: 100% !important;
+ height: 100% !important;
+ position: absolute !important;
+ top: 0 !important;
+ left: 0 !important;
+ z-index: 1 !important;
+ opacity: 1 !important;
+ animation: float 6s ease-in-out infinite;
+ filter: contrast(1.1) brightness(1.05) saturate(1.1);
+}
+
+.hero-infograph {
+ position: absolute !important;
+ top: -60px !important;
+ left: 0 !important;
+ width: 100% !important;
+ height: calc(100% + 60px) !important;
+ z-index: 1 !important;
+ pointer-events: none !important;
}
+
.hero-text {
height: 100%;
display: flex;
flex-wrap: wrap;
align-content: center;
- width: 50%;
- padding: 0 0 0 6vw;
+ justify-content: center;
+ width: 80%;
+ max-width: 1200px;
+ padding: 60px 40px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ box-sizing: border-box;
+ z-index: 3;
+ text-align: center;
}
.hero-title {
font-family: MaisonNeue-Bold, sans-serif;
- color: #121212;
- width: 42vw;
- font-size: 4.2rem;
+ color: #ffffff !important;
+ width: 100% !important;
+ max-width: 100% !important;
+ font-size: clamp(1rem, 4vw, 4.5rem) !important;
letter-spacing: 0.2px;
- margin: 0;
+ margin: 0 0 30px 0;
+ position: relative;
+ line-height: 1.2;
+ word-wrap: break-word !important;
+ overflow-wrap: break-word !important;
+ hyphens: auto !important;
+ text-align: center;
+ text-shadow: 4px 4px 12px rgba(0, 0, 0, 1), 0 0 30px rgba(0, 0, 0, 0.9), 2px
2px 6px rgba(0, 0, 0, 1);
+ font-weight: 900;
+}
+
+.hero-title::after {
+ content: '';
+ position: absolute;
+ bottom: -8px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 60px;
+ height: 3px;
+ background: #E8433E;
+ border-radius: 2px;
+ opacity: 0;
+ animation: slideInUnderline 1.5s ease-out 1s forwards;
+}
+
+@keyframes slideInUnderline {
+ from {
+ width: 0;
+ opacity: 0;
+ }
+ to {
+ width: 60px;
+ opacity: 1;
+ }
}
.btn {
- background: #030c16;
- border-style: solid;
- border-width: 1px;
- border: none;
- color: white;
- padding: 5px 20px;
- border-radius: 20px;
- font-size: 1rem;
+ background: linear-gradient(135deg, #ff4757 0%, #ff3742 100%);
+ border: 2px solid rgba(255, 255, 255, 0.6);
+ color: #ffffff;
+ padding: 14px 28px;
+ border-radius: 30px;
+ font-size: 0.9rem;
+ font-weight: 800;
text-decoration: none;
- margin: 0 10px 0 0;
- transition: all 0.3s;
+ margin: 0 15px 0 0;
+ transition: all 0.3s ease;
+ box-shadow: 0 6px 20px rgba(255, 71, 87, 0.4);
+ position: relative;
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
+ width: 200px;
+ height: 50px;
+ text-align: center;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
}
.btn:hover {
- background: #9b9b9b;
- color: white;
+ color: #eae2e2;
text-decoration: none;
+ box-shadow: 0 8px 20px rgba(255, 71, 87, 0.4);
+}
+
+.btn:active {
+ color: #ffffff;
}
.btn-docs {
- display: flex;
+ display: inline-flex;
flex-direction: row;
align-items: center;
+ justify-content: center;
+ text-decoration: none;
+ transition: all 0.3s ease;
+ padding: 14px 28px;
+ border-radius: 30px;
+ background: rgba(255, 255, 255, 0.4);
+ border: 2px solid rgba(255, 255, 255, 0.7);
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
+ width: 200px;
+ height: 50px;
+ text-align: center;
+ font-size: 0.9rem;
+ font-weight: 800;
+}
Review Comment:
The same issue exists here - fixed dimensions (width: 200px, height: 50px)
combined with padding (14px 28px) can cause layout issues and content overflow.
This is particularly problematic because the button contains text with varying
lengths across different languages (i18n), which could cause the text to be cut
off or overflow.
##########
website/src/css/landing-sections/hero.scss:
##########
@@ -158,3 +312,339 @@
width: 40vw;
}
}
+
+@media (max-width: 996px) {
+ .hero-sec-wrap {
+ display: block !important;
+ height: 100vh !important;
+ min-height: 100vh;
+ }
+
+ .hero-text {
+ width: 90%;
+ max-width: 800px;
+ padding: 40px 30px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ text-align: center;
+ }
+
+ .hero-title {
+ width: 100%;
+ max-width: 100%;
+ font-size: 3rem;
+ }
+
+ .hero-title::after {
+ width: 60px;
+ left: 50%;
+ transform: translateX(-50%);
+ }
+
+ .hero-subtitle {
+ width: 100%;
+ padding-right: 0;
+ }
+
+ .homeCanvas {
+ width: 100% !important;
+ height: 100% !important;
+ opacity: 0.85 !important;
+ }
+
+ .hero-ctas {
+ justify-content: center;
+ gap: 15px;
+ }
+}
+
+@media (max-width: 768px) {
+ .hero-text {
+ width: 95%;
+ max-width: 600px;
+ padding: 30px 25px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ }
+
+ .hero-title {
+ font-size: 2.5rem;
+ max-width: 100%;
+ }
+
+ .hero-subtitle {
+ font-size: 1rem;
+ }
+
+ .btn {
+ padding: 16px 32px;
+ font-size: 1.1rem;
+ }
+}
+
+@media (max-width: 768px) {
+ .hero-sec-wrap {
+ width: 100vw !important;
+ height: 100vh !important;
+ min-height: 100vh;
+ margin: 0 !important;
+ padding: 0 !important;
+ left: 50% !important;
+ right: 50% !important;
+ margin-left: -50vw !important;
+ margin-right: -50vw !important;
+ overflow: hidden;
+ position: relative;
+ }
+
+ .homeCanvas {
+ width: 100% !important;
+ height: 100% !important;
+ opacity: 0.9 !important;
+ filter: none !important;
+ backdrop-filter: none !important;
+ }
+
+ .hero-text {
+ width: 95%;
+ max-width: none;
+ padding: 20px 15px;
+ margin: 0;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ filter: none !important;
+ backdrop-filter: none !important;
+ text-align: center;
+ background: rgba(0, 0, 0, 0.4);
+ border-radius: 10px;
+ box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5);
+ max-height: 85vh;
+ overflow-y: auto;
+ }
+
+ .hero-title {
+ font-size: clamp(1.2rem, 4.5vw, 1.6rem);
+ max-width: 100%;
+ line-height: 1.3;
+ margin-bottom: 10px;
+ text-shadow: 2px 2px 6px rgba(0, 0, 0, 1), 0 0 15px rgba(0, 0, 0, 0.9),
1px 1px 2px rgba(0, 0, 0, 1);
+ font-weight: 900;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ hyphens: auto;
+ white-space: normal;
+ text-align: center;
+ padding: 0 10px;
+ }
+
+ .hero-title::after {
+ width: 30px;
+ height: 1px;
+ left: 50%;
+ transform: translateX(-50%);
+ }
+
+ .hero-subtitle {
+ font-size: clamp(0.75rem, 2.8vw, 0.9rem);
+ line-height: 1.4;
+ margin: 8px 0;
+ text-shadow: 1px 1px 4px rgba(0, 0, 0, 1), 0 0 10px rgba(0, 0, 0, 0.9),
1px 1px 1px rgba(0, 0, 0, 1);
+ font-weight: 600;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ hyphens: auto;
+ white-space: normal;
+ text-align: center;
+ padding: 0 10px;
+ max-width: 100%;
+ }
+
+ .hero-subtitle[style*="color: #E8433E"] {
+ font-size: clamp(1rem, 4vw, 1.2rem);
+ margin: 8px 0 12px 0;
+ text-shadow: 2px 2px 6px rgba(0, 0, 0, 1), 0 0 15px rgba(0, 0, 0, 0.9),
1px 1px 2px rgba(0, 0, 0, 1);
+ font-weight: 800;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ hyphens: auto;
+ white-space: normal;
+ text-align: center;
+ padding: 0 10px;
+ max-width: 100%;
+ line-height: 1.3;
+ }
+
+ .hero-ctas {
+ margin-top: 15px;
+ gap: 10px;
+ justify-content: center;
+ padding: 0 10px;
+ }
+
+ .btn {
+ padding: 9px 18px;
+ font-size: 0.8rem;
+ font-weight: 700;
+ text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7);
+ max-width: 200px;
+ border-radius: 20px;
+ }
+
+ .btn-docs {
+ background: rgba(255, 255, 255, 0.3);
+ padding: 7px 14px;
+ max-width: 200px;
+ border-radius: 18px;
+ }
+
+ .btn-docs .goto {
+ font-size: 0.75rem;
+ font-weight: 700;
+ text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7);
+ margin-right: 6px;
+ }
+}
Review Comment:
There are duplicate media query blocks for max-width 768px (lines 363-387
and 389-512). The second block starting at line 389 completely overrides the
first one, making the first block redundant. These should be consolidated into
a single media query block to avoid confusion and reduce code duplication.
##########
website/src/css/landing-sections/hero.scss:
##########
@@ -23,98 +52,223 @@
.hero-subtitle {
z-index: 100;
- font-size: 1.1rem;
+ font-size: clamp(0.6rem, 2vw, 1.3rem);
font-family: MaisonNeue-Light, sans-serif;
position: relative;
- color: #615d5d;
- line-height: 30px;
- letter-spacing: 0.2px;
+ color: #f1f5f9;
+ line-height: 1.6;
+ letter-spacing: 0.3px;
margin: 25px 0;
- padding-right: 20px;
+ padding-right: 0;
animation-delay: 0.25s;
+ width: 100%;
+ max-width: 100%;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ hyphens: auto;
+ box-sizing: border-box;
+ text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6), 0 0 15px rgba(0, 0, 0, 0.4);
+ font-weight: 500;
+}
Review Comment:
The hero subtitle color has been changed from #615d5d (dark gray) to #f1f5f9
(very light gray/white) with text-shadow on a potentially light background.
Without verifying the contrast ratio against the actual background image, this
could create accessibility issues for users with visual impairments. WCAG 2.1
Level AA requires a contrast ratio of at least 4.5:1 for normal text. Consider
testing the color contrast to ensure it meets accessibility standards.
##########
website/src/css/landing-sections/hero.scss:
##########
@@ -23,98 +52,223 @@
.hero-subtitle {
z-index: 100;
- font-size: 1.1rem;
+ font-size: clamp(0.6rem, 2vw, 1.3rem);
font-family: MaisonNeue-Light, sans-serif;
position: relative;
- color: #615d5d;
- line-height: 30px;
- letter-spacing: 0.2px;
+ color: #f1f5f9;
+ line-height: 1.6;
+ letter-spacing: 0.3px;
margin: 25px 0;
- padding-right: 20px;
+ padding-right: 0;
animation-delay: 0.25s;
+ width: 100%;
+ max-width: 100%;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ hyphens: auto;
+ box-sizing: border-box;
+ text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6), 0 0 15px rgba(0, 0, 0, 0.4);
+ font-weight: 500;
+}
+
+.hero-subtitle[style*="color: #E8433E"] {
+ color: #ff4757 !important;
+ background: none !important;
+ -webkit-background-clip: unset !important;
+ -webkit-text-fill-color: unset !important;
+ background-clip: unset !important;
+ font-weight: 800;
+ font-size: clamp(0.8rem, 3vw, 2.2rem);
+ text-shadow: 2px 2px 6px rgba(0, 0, 0, 0.7), 0 0 20px rgba(0, 0, 0, 0.5);
+ margin: 20px 0 30px 0;
}
.hero-ctas {
display: flex;
align-items: center;
animation-delay: 0.5;
+ gap: 20px;
+ margin-top: 32px;
}
.hero-sec-wrap {
- display: flex;
- background: #f4f4f4ad;
- height: 100vh;
+ display: block !important;
+ background: transparent !important;
+ height: 100vh !important;
+ position: relative !important;
+ width: 100% !important;
+ margin-top: -60px !important;
+ padding-top: 60px !important;
}
+
.homeCanvas-overlay {
position: absolute;
- width: 50vw;
- height: 100vh;
- background: #fff;
- top: -1px;
- right: 0;
+ width: 100%;
+ height: 100%;
+ background: transparent;
+ top: 0;
+ left: 0;
+ z-index: 1;
+ pointer-events: none;
}
.homeCanvas {
- width: 50vw;
- height: 100vh;
+ width: 100% !important;
+ height: 100% !important;
+ position: absolute !important;
+ top: 0 !important;
+ left: 0 !important;
+ z-index: 1 !important;
+ opacity: 1 !important;
+ animation: float 6s ease-in-out infinite;
+ filter: contrast(1.1) brightness(1.05) saturate(1.1);
+}
+
+.hero-infograph {
+ position: absolute !important;
+ top: -60px !important;
+ left: 0 !important;
+ width: 100% !important;
+ height: calc(100% + 60px) !important;
+ z-index: 1 !important;
+ pointer-events: none !important;
Review Comment:
Excessive use of !important flags throughout this file (over 60 occurrences)
indicates a specificity issue in the CSS architecture. Using !important should
be a last resort, as it makes the CSS difficult to maintain and override.
Instead of using !important, consider increasing selector specificity or
restructuring the CSS to avoid specificity conflicts. This is particularly
problematic for maintainability as it makes future style updates more difficult.
##########
website/src/components/sections/HeroSection.tsx:
##########
@@ -24,39 +21,69 @@ const LazyLoadHeroCanvas = () => {
);
};
-const HeroSection: FC = () => (
- <div className="hero-sec-wrap" style={{ width: '100%' }}>
- <div className="hero-text">
- <h1 className="hero-title">
- <Translate id="hero.component.title.fragment1">API Gateway & AI
Gateway for APIs and AI Agents</Translate>
- </h1>
- <h2
- className="hero-subtitle"
- style={{
- color: '#E8433E', fontSize: 32, fontWeight: 700, lineHeight: 1.2,
- }}
- >
- <Translate id="hero.component.title.fragment2">
- Open-Source, Community-Driven, Future-Ready
- </Translate>
- </h2>
- <h3 className="hero-subtitle">
- <Translate id="hero.component.subtitle.content">
- APISIX API Gateway provides rich traffic management features like
load balancing, dynamic
- upstream, canary release, circuit breaking, auth, and observability.
- </Translate>
- </h3>
- <div className="hero-ctas">
- <Link target="_parent" to={useBaseUrl('docs/apisix/getting-started')}
className="btn btn-download">
- <Translate id="hero.component.download.btn">Getting
Started</Translate>
- </Link>
- <ArrowAnim />
- </div>
- </div>
- <div className="add-margin">
+const HeroSection: FC = () => {
+ useEffect(() => {
+ const handleScroll = () => {
+ const heroSection = document.querySelector('.hero-sec-wrap');
+ const navbar = document.querySelector('.navbar');
+
+ if (heroSection && navbar) {
+ const heroRect = heroSection.getBoundingClientRect();
+ const isInHeroSection = heroRect.top <= 100 && heroRect.bottom >= 0;
+
+ if (isInHeroSection) {
+ document.body.classList.add('hero-navbar');
+ } else {
+ document.body.classList.remove('hero-navbar');
+ }
+ }
+ };
+
+ // Set initial state
+ handleScroll();
+
+ // Add scroll listener
+ window.addEventListener('scroll', handleScroll);
Review Comment:
The scroll event listener does not use passive event handling, which can
negatively impact scroll performance. Modern browsers recommend using passive
listeners for scroll events. Consider adding { passive: true } as the third
argument to addEventListener to improve scroll performance:
window.addEventListener('scroll', handleScroll, { passive: true });
```suggestion
window.addEventListener('scroll', handleScroll, { passive: true });
```
##########
website/src/css/landing-sections/hero.scss:
##########
@@ -158,3 +312,339 @@
width: 40vw;
}
}
+
+@media (max-width: 996px) {
+ .hero-sec-wrap {
+ display: block !important;
+ height: 100vh !important;
+ min-height: 100vh;
+ }
+
+ .hero-text {
+ width: 90%;
+ max-width: 800px;
+ padding: 40px 30px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ text-align: center;
+ }
+
+ .hero-title {
+ width: 100%;
+ max-width: 100%;
+ font-size: 3rem;
+ }
+
+ .hero-title::after {
+ width: 60px;
+ left: 50%;
+ transform: translateX(-50%);
+ }
+
+ .hero-subtitle {
+ width: 100%;
+ padding-right: 0;
+ }
+
+ .homeCanvas {
+ width: 100% !important;
+ height: 100% !important;
+ opacity: 0.85 !important;
+ }
+
+ .hero-ctas {
+ justify-content: center;
+ gap: 15px;
+ }
+}
+
+@media (max-width: 768px) {
+ .hero-text {
+ width: 95%;
+ max-width: 600px;
+ padding: 30px 25px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ }
+
+ .hero-title {
+ font-size: 2.5rem;
+ max-width: 100%;
+ }
+
+ .hero-subtitle {
+ font-size: 1rem;
+ }
+
+ .btn {
+ padding: 16px 32px;
+ font-size: 1.1rem;
+ }
+}
+
+@media (max-width: 768px) {
+ .hero-sec-wrap {
+ width: 100vw !important;
+ height: 100vh !important;
+ min-height: 100vh;
+ margin: 0 !important;
+ padding: 0 !important;
+ left: 50% !important;
+ right: 50% !important;
+ margin-left: -50vw !important;
+ margin-right: -50vw !important;
+ overflow: hidden;
+ position: relative;
+ }
+
+ .homeCanvas {
+ width: 100% !important;
+ height: 100% !important;
+ opacity: 0.9 !important;
+ filter: none !important;
+ backdrop-filter: none !important;
Review Comment:
The filter property is set to "none !important" at mobile breakpoints (768px
and 480px), but at line 125 it's set to "contrast(1.1) brightness(1.05)
saturate(1.1)". This creates an inconsistency - the enhanced background
visibility mentioned in the PR description won't apply on mobile devices. If
the enhanced filters are important for visibility, they should be adjusted for
mobile rather than completely removed, or the PR description should clarify
that the enhancements are desktop-only.
##########
website/src/css/landing-sections/architecture.scss:
##########
@@ -113,6 +121,83 @@
.docs-promo-subtitle,
.oss-promo-subtitle {
left: 7%;
- width: 85%;
+ width: 80%;
+ max-width: 80%;
+ padding-right: 13%;
+ box-sizing: border-box;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ hyphens: auto;
+ line-height: 1.5;
+ }
+
+ .arch-card-caption > p {
+ width: 95%;
+ font-size: 0.9rem;
+ padding: 5px;
+ }
+}
+
+/* Medium tablets and large phones */
+@media (max-width: 768px) {
+ .arch-card-caption > p {
+ width: 92%;
+ font-size: 0.85rem;
+ padding: 6px;
+ line-height: 1.5;
+ }
+}
+
+@media (max-width: 480px) {
+ .arch-card-border {
+ width: 85% !important;
+ left: 7.5% !important;
+ height: 110% !important;
+ }
+
+ .arch-card-caption {
+ padding: 0 10px;
+ overflow: hidden;
+ width: 100%;
+ max-width: 100%;
+ box-sizing: border-box;
+ }
+
+ .arch-card-caption > p {
+ font-size: 0.65rem;
+ width: 80%;
+ max-width: 80%;
+ padding: 8px 0;
+ margin: 15px 0;
+ word-wrap: break-word !important;
+ overflow-wrap: break-word !important;
+ word-break: break-word !important;
+ hyphens: auto;
+ line-height: 1.4;
+ box-sizing: border-box;
+ overflow: hidden;
+ }
+}
+
+/* Extra small devices */
+@media (max-width: 360px) {
+ .arch-card-border {
+ width: 90% !important;
+ left: 5% !important;
+ height: 115% !important;
+ }
+
+ .arch-card-caption {
+ padding: 0 8px;
+ }
+
+ .arch-card-caption > p {
+ font-size: 0.6rem;
+ width: 75%;
+ max-width: 75%;
+ word-break: break-all !important;
Review Comment:
Using word-break: break-all at 360px breakpoint will break words at any
character, which severely impacts readability and looks unprofessional,
especially for technical terms. Unlike word-wrap: break-word and overflow-wrap:
break-word which break at word boundaries, break-all can split words like
"APISIX" into "API-SIX" mid-word. Consider removing word-break: break-all and
relying on the existing word-wrap and overflow-wrap properties which provide
better typography.
```suggestion
```
##########
website/src/css/landing-sections/endcta.module.scss:
##########
@@ -42,6 +42,82 @@ $apisix-color: #e8433e;
& .links {
display: flex;
+
+ :global(.btn-download) {
+ background: #030c16;
+ border-style: solid;
+ border-width: 1px;
+ border: none;
+ color: white;
+ padding: 5px 20px;
+ border-radius: 20px;
+ font-size: 1rem;
+ text-decoration: none;
+ margin: 0 10px 0 0;
+ transition: all 0.3s;
+ box-shadow: none;
+
+ &:hover {
+ background: #000000;
+ color: white;
+ text-decoration: none;
+ box-shadow: 0 4px 12px rgba(244, 89, 89, 0.4);
+ }
+ }
+
+ :global(.btn-docs) {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+
+ &:hover {
+ text-decoration: none;
+ }
+
+ :global(.goto) {
+ color: #000;
+ text-shadow: none;
+ }
+
+ &:hover :global(.goto),
+ &:active :global(.goto) {
+ opacity: 0.8;
+ text-shadow: none;
+ }
+
+ :global(.arrow) {
+ width: 30px;
+ height: 30px;
+ position: relative;
+
+ svg {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ }
+
+ polygon,
+ rect {
+ transition: all 250ms;
+ }
+
+ rect {
+ opacity: 0;
+ }
+ }
+
+ &:hover :global(.arrow) {
+ polygon {
+ transform: translateX(100px);
+ }
+
+ rect {
+ transform: translateX(240px);
+ opacity: 1;
+ }
+ }
+ }
Review Comment:
The button styles in endcta.module.scss appear to duplicate styles from
hero.scss but with different values. For example, .btn-download in endcta has
background: #030c16 while .btn in hero has a gradient background. The arrow
animation styles (lines 88-119) are repeated across multiple sections. Consider
extracting common button styles and arrow animations into a shared SCSS file or
mixin to reduce code duplication and ensure consistent behavior across the site.
##########
website/src/css/customTheme.scss:
##########
@@ -150,15 +150,236 @@ header h2 {
}
}
-/* navbar */
-.navbar__link:hover,
-.navbar__link--active {
- color: var(--color-primary);
+/* navbar - Default styling for all pages */
+.navbar {
+ background: #ffffff !important;
+ backdrop-filter: blur(10px) !important;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.15) !important;
+ box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1) !important;
+ transition: all 0.3s ease !important;
}
.navbar__title {
font-size: 18px;
height: 30px;
+ color: #000000 !important;
+ font-weight: 800 !important;
+}
+
+.navbar__link {
+ color: #1a202c !important;
+ font-weight: 600 !important;
+ transition: all 0.3s ease !important;
+ padding: 8px 14px !important;
+ border-radius: 8px !important;
+ margin: 0 2px !important;
+}
+
+.navbar__link:hover,
+.navbar__link--active {
+ color: #000000 !important;
+ background: rgba(0, 0, 0, 0.08) !important;
+ font-weight: 700 !important;
+}
+
+.navbar__toggle {
+ color: #1a202c !important;
+ font-weight: 700 !important;
+ background: none !important;
+ border: none !important;
+ cursor: pointer !important;
+ z-index: 9999 !important;
+}
+
+.navbar__toggle:hover,
+.navbar__toggle:focus {
+ background: rgba(0, 0, 0, 0.1) !important;
+ border-radius: 4px !important;
+}
+
+.navbar__search-input {
+ background: rgba(0, 0, 0, 0.08) !important;
+ border: 1px solid rgba(0, 0, 0, 0.2) !important;
+ color: #000000 !important;
+ border-radius: 8px !important;
+ font-weight: 500 !important;
+}
+
+.navbar__search-input::placeholder {
+ color: rgba(0, 0, 0, 0.6) !important;
+ font-weight: 500 !important;
+}
+
+/* Mobile menu styling */
+.navbar-sidebar {
+ background: #ffffff !important;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1) !important;
+ z-index: 9999 !important;
+ position: fixed !important;
+ top: 0 !important;
+ right: 0 !important;
+ height: 100vh !important;
+ width: 300px !important;
+ transform: translateX(0) !important;
+}
+
+.navbar-sidebar__brand {
+ background: #ffffff !important;
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1) !important;
+ padding: 16px !important;
+}
+
+.navbar-sidebar__items {
+ background: #ffffff !important;
+ padding: 20px 0 !important;
+ overflow-y: auto !important;
+}
+
+.navbar-sidebar .menu__link {
+ color: #1a202c !important;
+ font-weight: 600 !important;
+ padding: 12px 16px !important;
+ border-radius: 8px !important;
+ margin: 4px 8px !important;
+ display: block !important;
+ text-decoration: none !important;
+}
+
+.navbar-sidebar .menu__link:hover,
+.navbar-sidebar .menu__link--active {
+ background: rgba(0, 0, 0, 0.08) !important;
+ color: #000000 !important;
+}
+
+.navbar-sidebar__backdrop {
+ background: rgba(0, 0, 0, 0.5) !important;
+ z-index: 9998 !important;
+}
+
+/* Hero section mobile menu */
+.hero-navbar .navbar-sidebar {
+ background: rgba(0, 0, 0, 0.95) !important;
+ z-index: 9999 !important;
+ position: fixed !important;
+ top: 0 !important;
+ right: 0 !important;
+ height: 100vh !important;
+ width: 300px !important;
+}
+
+.hero-navbar .navbar-sidebar__brand {
+ background: rgba(0, 0, 0, 0.95) !important;
+ padding: 16px !important;
+}
+
+.hero-navbar .navbar-sidebar__items {
+ background: rgba(0, 0, 0, 0.95) !important;
+ padding: 20px 0 !important;
+}
+
+.hero-navbar .navbar-sidebar .menu__link {
+ color: #ffffff !important;
+ text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5) !important;
+ font-weight: 600 !important;
+ padding: 12px 16px !important;
+ border-radius: 8px !important;
+ margin: 4px 8px !important;
+ display: block !important;
+ text-decoration: none !important;
+}
+
+.hero-navbar .navbar-sidebar .menu__link:hover,
+.hero-navbar .navbar-sidebar .menu__link--active {
+ background: rgba(255, 255, 255, 0.2) !important;
+ color: #ffffff !important;
+}
+
+.hero-navbar .navbar-sidebar__backdrop {
+ background: rgba(0, 0, 0, 0.7) !important;
+ z-index: 9998 !important;
+}
+
+/* Hero section specific navbar styling - only when in hero viewport */
+.hero-navbar .navbar {
+ background: rgba(0, 0, 0, 0.7) !important;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3) !important;
+}
+
+/* Mobile specific navbar enhancement */
+@media (max-width: 768px) {
+ .hero-navbar .navbar {
+ background: rgba(0, 0, 0, 0.85) !important;
+ border-bottom: 2px solid rgba(255, 255, 255, 0.4) !important;
+ box-shadow: 0 6px 25px rgba(0, 0, 0, 0.4) !important;
+ }
+
+ .hero-navbar .navbar__title {
+ font-size: 1.1rem !important;
+ font-weight: 900 !important;
+ text-shadow: 2px 2px 6px rgba(0, 0, 0, 1) !important;
+ }
+
+ .hero-navbar .navbar__link {
+ font-size: 0.9rem !important;
+ font-weight: 700 !important;
+ text-shadow: 2px 2px 6px rgba(0, 0, 0, 1) !important;
+ padding: 10px 14px !important;
+ }
+
+ .hero-navbar .navbar__toggle {
+ font-size: 1.2rem !important;
+ font-weight: 900 !important;
+ text-shadow: 2px 2px 6px rgba(0, 0, 0, 1) !important;
+ }
+}
+
+.hero-navbar .navbar__title {
+ color: #ffffff !important;
+ text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3) !important;
+}
+
+.hero-navbar .navbar__link {
+ color: rgba(255, 255, 255, 0.9) !important;
+ text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3) !important;
+ padding: 8px 16px !important;
+ border-radius: 20px !important;
+ margin: 0 4px !important;
+}
+
+.hero-navbar .navbar__link:hover,
+.hero-navbar .navbar__link--active {
+ color: #ffffff !important;
+ background: rgba(255, 255, 255, 0.2) !important;
+ backdrop-filter: blur(10px) !important;
+ text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.5) !important;
+ transform: translateY(-1px) !important;
+}
+
+.hero-navbar .navbar__toggle {
+ color: #ffffff !important;
+ background: none !important;
+ border: none !important;
+ cursor: pointer !important;
+ z-index: 9999 !important;
+}
+
+.hero-navbar .navbar__toggle:hover,
+.hero-navbar .navbar__toggle:focus {
+ background: rgba(255, 255, 255, 0.2) !important;
+ border-radius: 4px !important;
+}
+
+.hero-navbar .navbar__search-input {
+ background: rgba(255, 255, 255, 0.2) !important;
+ border: 1px solid rgba(255, 255, 255, 0.3) !important;
+ color: #ffffff !important;
+ backdrop-filter: blur(10px) !important;
+ border-radius: 20px !important;
+}
+
+.hero-navbar .navbar__search-input::placeholder {
+ color: rgba(255, 255, 255, 0.7) !important;
Review Comment:
The new navbar styling section adds over 120 !important declarations to
override existing styles. This approach creates significant technical debt and
makes the CSS extremely difficult to maintain. The heavy reliance on !important
suggests that the CSS architecture needs restructuring. Consider using higher
specificity selectors or creating a dedicated class for hero-specific navbar
styling instead of forcing overrides with !important flags.
```suggestion
:root .hero-navbar .navbar__toggle {
color: #ffffff;
background: none;
border: none;
cursor: pointer;
z-index: 9999;
}
:root .hero-navbar .navbar__toggle:hover,
:root .hero-navbar .navbar__toggle:focus {
background: rgba(255, 255, 255, 0.2);
border-radius: 4px;
}
:root .hero-navbar .navbar__search-input {
background: rgba(255, 255, 255, 0.2);
border: 1px solid rgba(255, 255, 255, 0.3);
color: #ffffff;
backdrop-filter: blur(10px);
border-radius: 20px;
}
:root .hero-navbar .navbar__search-input::placeholder {
color: rgba(255, 255, 255, 0.7);
```
##########
website/src/css/landing-sections/hero.scss:
##########
@@ -12,6 +12,35 @@
}
}
+@keyframes float {
+ 0%, 100% {
+ transform: translateY(0px);
+ }
+ 50% {
+ transform: translateY(-10px);
+ }
+}
+
+@keyframes pulse {
+ 0%, 100% {
+ opacity: 1;
+ transform: scale(1);
+ }
+ 50% {
+ opacity: 0.8;
+ transform: scale(1.05);
+ }
+}
+
+@keyframes glow {
+ 0%, 100% {
+ box-shadow: 0 0 20px rgba(102, 126, 234, 0.3);
+ }
+ 50% {
+ box-shadow: 0 0 40px rgba(102, 126, 234, 0.6);
+ }
+}
+
Review Comment:
The keyframe animations "pulse" and "glow" are defined but never used
anywhere in the stylesheet. These should be removed to reduce CSS bundle size
and avoid code clutter.
```suggestion
```
##########
website/src/components/sections/HeroSection.tsx:
##########
@@ -24,39 +21,69 @@ const LazyLoadHeroCanvas = () => {
);
};
-const HeroSection: FC = () => (
- <div className="hero-sec-wrap" style={{ width: '100%' }}>
- <div className="hero-text">
- <h1 className="hero-title">
- <Translate id="hero.component.title.fragment1">API Gateway & AI
Gateway for APIs and AI Agents</Translate>
- </h1>
- <h2
- className="hero-subtitle"
- style={{
- color: '#E8433E', fontSize: 32, fontWeight: 700, lineHeight: 1.2,
- }}
- >
- <Translate id="hero.component.title.fragment2">
- Open-Source, Community-Driven, Future-Ready
- </Translate>
- </h2>
- <h3 className="hero-subtitle">
- <Translate id="hero.component.subtitle.content">
- APISIX API Gateway provides rich traffic management features like
load balancing, dynamic
- upstream, canary release, circuit breaking, auth, and observability.
- </Translate>
- </h3>
- <div className="hero-ctas">
- <Link target="_parent" to={useBaseUrl('docs/apisix/getting-started')}
className="btn btn-download">
- <Translate id="hero.component.download.btn">Getting
Started</Translate>
- </Link>
- <ArrowAnim />
- </div>
- </div>
- <div className="add-margin">
+const HeroSection: FC = () => {
+ useEffect(() => {
+ const handleScroll = () => {
+ const heroSection = document.querySelector('.hero-sec-wrap');
+ const navbar = document.querySelector('.navbar');
+
+ if (heroSection && navbar) {
+ const heroRect = heroSection.getBoundingClientRect();
+ const isInHeroSection = heroRect.top <= 100 && heroRect.bottom >= 0;
+
+ if (isInHeroSection) {
+ document.body.classList.add('hero-navbar');
+ } else {
+ document.body.classList.remove('hero-navbar');
+ }
+ }
+ };
Review Comment:
The handleScroll function runs on every scroll event without throttling or
debouncing, which can cause performance issues during rapid scrolling. The
function performs DOM queries (querySelector) and class manipulations on every
scroll event, which can be expensive. Consider throttling this function to run
at most once every 100-200ms to improve performance.
##########
website/src/css/landing-sections/hero.scss:
##########
@@ -23,98 +52,223 @@
.hero-subtitle {
z-index: 100;
- font-size: 1.1rem;
+ font-size: clamp(0.6rem, 2vw, 1.3rem);
font-family: MaisonNeue-Light, sans-serif;
position: relative;
- color: #615d5d;
- line-height: 30px;
- letter-spacing: 0.2px;
+ color: #f1f5f9;
+ line-height: 1.6;
+ letter-spacing: 0.3px;
margin: 25px 0;
- padding-right: 20px;
+ padding-right: 0;
animation-delay: 0.25s;
+ width: 100%;
+ max-width: 100%;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ hyphens: auto;
+ box-sizing: border-box;
+ text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6), 0 0 15px rgba(0, 0, 0, 0.4);
+ font-weight: 500;
+}
+
+.hero-subtitle[style*="color: #E8433E"] {
+ color: #ff4757 !important;
+ background: none !important;
+ -webkit-background-clip: unset !important;
+ -webkit-text-fill-color: unset !important;
+ background-clip: unset !important;
+ font-weight: 800;
+ font-size: clamp(0.8rem, 3vw, 2.2rem);
+ text-shadow: 2px 2px 6px rgba(0, 0, 0, 0.7), 0 0 20px rgba(0, 0, 0, 0.5);
+ margin: 20px 0 30px 0;
}
.hero-ctas {
display: flex;
align-items: center;
animation-delay: 0.5;
+ gap: 20px;
+ margin-top: 32px;
}
.hero-sec-wrap {
- display: flex;
- background: #f4f4f4ad;
- height: 100vh;
+ display: block !important;
+ background: transparent !important;
+ height: 100vh !important;
+ position: relative !important;
+ width: 100% !important;
+ margin-top: -60px !important;
+ padding-top: 60px !important;
}
+
.homeCanvas-overlay {
position: absolute;
- width: 50vw;
- height: 100vh;
- background: #fff;
- top: -1px;
- right: 0;
+ width: 100%;
+ height: 100%;
+ background: transparent;
+ top: 0;
+ left: 0;
+ z-index: 1;
+ pointer-events: none;
}
.homeCanvas {
- width: 50vw;
- height: 100vh;
+ width: 100% !important;
+ height: 100% !important;
+ position: absolute !important;
+ top: 0 !important;
+ left: 0 !important;
+ z-index: 1 !important;
+ opacity: 1 !important;
+ animation: float 6s ease-in-out infinite;
+ filter: contrast(1.1) brightness(1.05) saturate(1.1);
+}
+
+.hero-infograph {
+ position: absolute !important;
+ top: -60px !important;
+ left: 0 !important;
+ width: 100% !important;
+ height: calc(100% + 60px) !important;
+ z-index: 1 !important;
+ pointer-events: none !important;
}
+
.hero-text {
height: 100%;
display: flex;
flex-wrap: wrap;
align-content: center;
- width: 50%;
- padding: 0 0 0 6vw;
+ justify-content: center;
+ width: 80%;
+ max-width: 1200px;
+ padding: 60px 40px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ box-sizing: border-box;
+ z-index: 3;
+ text-align: center;
}
.hero-title {
font-family: MaisonNeue-Bold, sans-serif;
- color: #121212;
- width: 42vw;
- font-size: 4.2rem;
+ color: #ffffff !important;
+ width: 100% !important;
+ max-width: 100% !important;
+ font-size: clamp(1rem, 4vw, 4.5rem) !important;
letter-spacing: 0.2px;
- margin: 0;
+ margin: 0 0 30px 0;
+ position: relative;
+ line-height: 1.2;
+ word-wrap: break-word !important;
+ overflow-wrap: break-word !important;
+ hyphens: auto !important;
+ text-align: center;
+ text-shadow: 4px 4px 12px rgba(0, 0, 0, 1), 0 0 30px rgba(0, 0, 0, 0.9), 2px
2px 6px rgba(0, 0, 0, 1);
+ font-weight: 900;
+}
+
+.hero-title::after {
+ content: '';
+ position: absolute;
+ bottom: -8px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 60px;
+ height: 3px;
+ background: #E8433E;
+ border-radius: 2px;
+ opacity: 0;
+ animation: slideInUnderline 1.5s ease-out 1s forwards;
+}
+
+@keyframes slideInUnderline {
+ from {
+ width: 0;
+ opacity: 0;
+ }
+ to {
+ width: 60px;
+ opacity: 1;
+ }
}
.btn {
- background: #030c16;
- border-style: solid;
- border-width: 1px;
- border: none;
- color: white;
- padding: 5px 20px;
- border-radius: 20px;
- font-size: 1rem;
+ background: linear-gradient(135deg, #ff4757 0%, #ff3742 100%);
+ border: 2px solid rgba(255, 255, 255, 0.6);
+ color: #ffffff;
+ padding: 14px 28px;
+ border-radius: 30px;
+ font-size: 0.9rem;
+ font-weight: 800;
text-decoration: none;
- margin: 0 10px 0 0;
- transition: all 0.3s;
+ margin: 0 15px 0 0;
+ transition: all 0.3s ease;
+ box-shadow: 0 6px 20px rgba(255, 71, 87, 0.4);
+ position: relative;
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
+ width: 200px;
+ height: 50px;
+ text-align: center;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
}
Review Comment:
Fixed button dimensions (width: 200px, height: 50px) are applied alongside
padding (14px 28px), which can cause layout issues. The combination of explicit
width/height and padding may result in the button content overflowing or being
squeezed. Consider using either explicit dimensions OR padding with automatic
sizing, not both. Additionally, these fixed dimensions may not work well across
all screen sizes despite responsive breakpoints.
##########
website/src/css/landing-sections/hero.scss:
##########
@@ -23,98 +52,223 @@
.hero-subtitle {
z-index: 100;
- font-size: 1.1rem;
+ font-size: clamp(0.6rem, 2vw, 1.3rem);
font-family: MaisonNeue-Light, sans-serif;
position: relative;
- color: #615d5d;
- line-height: 30px;
- letter-spacing: 0.2px;
+ color: #f1f5f9;
+ line-height: 1.6;
+ letter-spacing: 0.3px;
margin: 25px 0;
- padding-right: 20px;
+ padding-right: 0;
animation-delay: 0.25s;
+ width: 100%;
+ max-width: 100%;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ hyphens: auto;
+ box-sizing: border-box;
+ text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6), 0 0 15px rgba(0, 0, 0, 0.4);
+ font-weight: 500;
+}
+
+.hero-subtitle[style*="color: #E8433E"] {
+ color: #ff4757 !important;
+ background: none !important;
+ -webkit-background-clip: unset !important;
+ -webkit-text-fill-color: unset !important;
+ background-clip: unset !important;
+ font-weight: 800;
+ font-size: clamp(0.8rem, 3vw, 2.2rem);
+ text-shadow: 2px 2px 6px rgba(0, 0, 0, 0.7), 0 0 20px rgba(0, 0, 0, 0.5);
+ margin: 20px 0 30px 0;
}
.hero-ctas {
display: flex;
align-items: center;
animation-delay: 0.5;
+ gap: 20px;
+ margin-top: 32px;
}
.hero-sec-wrap {
- display: flex;
- background: #f4f4f4ad;
- height: 100vh;
+ display: block !important;
+ background: transparent !important;
+ height: 100vh !important;
+ position: relative !important;
+ width: 100% !important;
+ margin-top: -60px !important;
+ padding-top: 60px !important;
}
+
.homeCanvas-overlay {
position: absolute;
- width: 50vw;
- height: 100vh;
- background: #fff;
- top: -1px;
- right: 0;
+ width: 100%;
+ height: 100%;
+ background: transparent;
+ top: 0;
+ left: 0;
+ z-index: 1;
+ pointer-events: none;
}
.homeCanvas {
- width: 50vw;
- height: 100vh;
+ width: 100% !important;
+ height: 100% !important;
+ position: absolute !important;
+ top: 0 !important;
+ left: 0 !important;
+ z-index: 1 !important;
+ opacity: 1 !important;
+ animation: float 6s ease-in-out infinite;
+ filter: contrast(1.1) brightness(1.05) saturate(1.1);
+}
+
Review Comment:
The float animation on .homeCanvas continuously animates translateY for 6
seconds on an infinite loop. Animating a full-screen positioned element with
transforms can be GPU-intensive and may cause performance issues, especially on
lower-end devices or mobile. The animation moves the entire canvas up and down
by 10px every 6 seconds, which is subtle but computationally expensive for such
a large element. Consider whether this animation is necessary, or use
will-change: transform to hint to the browser to optimize it, though this
should be done carefully as will-change has its own performance implications.
```suggestion
filter: contrast(1.1) brightness(1.05) saturate(1.1);
will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
.homeCanvas {
animation: none;
}
}
```
##########
website/src/css/landing-sections/hero.scss:
##########
@@ -158,3 +312,339 @@
width: 40vw;
}
}
+
+@media (max-width: 996px) {
+ .hero-sec-wrap {
+ display: block !important;
+ height: 100vh !important;
+ min-height: 100vh;
+ }
+
+ .hero-text {
+ width: 90%;
+ max-width: 800px;
+ padding: 40px 30px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ text-align: center;
+ }
+
+ .hero-title {
+ width: 100%;
+ max-width: 100%;
+ font-size: 3rem;
+ }
+
+ .hero-title::after {
+ width: 60px;
+ left: 50%;
+ transform: translateX(-50%);
+ }
+
+ .hero-subtitle {
+ width: 100%;
+ padding-right: 0;
+ }
+
+ .homeCanvas {
+ width: 100% !important;
+ height: 100% !important;
+ opacity: 0.85 !important;
+ }
+
+ .hero-ctas {
+ justify-content: center;
+ gap: 15px;
+ }
+}
+
+@media (max-width: 768px) {
+ .hero-text {
+ width: 95%;
+ max-width: 600px;
+ padding: 30px 25px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ }
+
+ .hero-title {
+ font-size: 2.5rem;
+ max-width: 100%;
+ }
+
+ .hero-subtitle {
+ font-size: 1rem;
+ }
+
+ .btn {
+ padding: 16px 32px;
+ font-size: 1.1rem;
+ }
+}
+
+@media (max-width: 768px) {
+ .hero-sec-wrap {
+ width: 100vw !important;
+ height: 100vh !important;
+ min-height: 100vh;
+ margin: 0 !important;
+ padding: 0 !important;
+ left: 50% !important;
+ right: 50% !important;
+ margin-left: -50vw !important;
+ margin-right: -50vw !important;
+ overflow: hidden;
+ position: relative;
+ }
+
+ .homeCanvas {
+ width: 100% !important;
+ height: 100% !important;
+ opacity: 0.9 !important;
+ filter: none !important;
+ backdrop-filter: none !important;
+ }
+
+ .hero-text {
+ width: 95%;
+ max-width: none;
+ padding: 20px 15px;
+ margin: 0;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ filter: none !important;
+ backdrop-filter: none !important;
+ text-align: center;
+ background: rgba(0, 0, 0, 0.4);
+ border-radius: 10px;
+ box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5);
+ max-height: 85vh;
+ overflow-y: auto;
+ }
+
+ .hero-title {
+ font-size: clamp(1.2rem, 4.5vw, 1.6rem);
+ max-width: 100%;
+ line-height: 1.3;
+ margin-bottom: 10px;
+ text-shadow: 2px 2px 6px rgba(0, 0, 0, 1), 0 0 15px rgba(0, 0, 0, 0.9),
1px 1px 2px rgba(0, 0, 0, 1);
+ font-weight: 900;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ hyphens: auto;
+ white-space: normal;
+ text-align: center;
+ padding: 0 10px;
+ }
+
+ .hero-title::after {
+ width: 30px;
+ height: 1px;
+ left: 50%;
+ transform: translateX(-50%);
+ }
+
+ .hero-subtitle {
+ font-size: clamp(0.75rem, 2.8vw, 0.9rem);
+ line-height: 1.4;
+ margin: 8px 0;
+ text-shadow: 1px 1px 4px rgba(0, 0, 0, 1), 0 0 10px rgba(0, 0, 0, 0.9),
1px 1px 1px rgba(0, 0, 0, 1);
+ font-weight: 600;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ hyphens: auto;
+ white-space: normal;
+ text-align: center;
+ padding: 0 10px;
+ max-width: 100%;
+ }
+
+ .hero-subtitle[style*="color: #E8433E"] {
+ font-size: clamp(1rem, 4vw, 1.2rem);
+ margin: 8px 0 12px 0;
+ text-shadow: 2px 2px 6px rgba(0, 0, 0, 1), 0 0 15px rgba(0, 0, 0, 0.9),
1px 1px 2px rgba(0, 0, 0, 1);
+ font-weight: 800;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ hyphens: auto;
+ white-space: normal;
+ text-align: center;
+ padding: 0 10px;
+ max-width: 100%;
+ line-height: 1.3;
+ }
+
+ .hero-ctas {
+ margin-top: 15px;
+ gap: 10px;
+ justify-content: center;
+ padding: 0 10px;
+ }
+
+ .btn {
+ padding: 9px 18px;
+ font-size: 0.8rem;
+ font-weight: 700;
+ text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7);
+ max-width: 200px;
+ border-radius: 20px;
+ }
Review Comment:
At the 768px breakpoint (lines 383-386), the button styling increases
padding to 16px 32px and font-size to 1.1rem, making the buttons larger.
However, the second 768px media query block (starting at line 389) overrides
this at line 490-497 with smaller padding (9px 18px) and smaller font-size
(0.8rem). This creates confusion - the first block makes buttons bigger for
tablets, but the second block immediately overrides it to make them smaller.
This is another consequence of the duplicate media query blocks.
##########
website/src/components/sections/HeroSection.tsx:
##########
@@ -24,39 +21,69 @@ const LazyLoadHeroCanvas = () => {
);
};
-const HeroSection: FC = () => (
- <div className="hero-sec-wrap" style={{ width: '100%' }}>
- <div className="hero-text">
- <h1 className="hero-title">
- <Translate id="hero.component.title.fragment1">API Gateway & AI
Gateway for APIs and AI Agents</Translate>
- </h1>
- <h2
- className="hero-subtitle"
- style={{
- color: '#E8433E', fontSize: 32, fontWeight: 700, lineHeight: 1.2,
- }}
- >
- <Translate id="hero.component.title.fragment2">
- Open-Source, Community-Driven, Future-Ready
- </Translate>
- </h2>
- <h3 className="hero-subtitle">
- <Translate id="hero.component.subtitle.content">
- APISIX API Gateway provides rich traffic management features like
load balancing, dynamic
- upstream, canary release, circuit breaking, auth, and observability.
- </Translate>
- </h3>
- <div className="hero-ctas">
- <Link target="_parent" to={useBaseUrl('docs/apisix/getting-started')}
className="btn btn-download">
- <Translate id="hero.component.download.btn">Getting
Started</Translate>
- </Link>
- <ArrowAnim />
- </div>
- </div>
- <div className="add-margin">
+const HeroSection: FC = () => {
+ useEffect(() => {
+ const handleScroll = () => {
+ const heroSection = document.querySelector('.hero-sec-wrap');
+ const navbar = document.querySelector('.navbar');
+
+ if (heroSection && navbar) {
+ const heroRect = heroSection.getBoundingClientRect();
+ const isInHeroSection = heroRect.top <= 100 && heroRect.bottom >= 0;
+
+ if (isInHeroSection) {
+ document.body.classList.add('hero-navbar');
+ } else {
+ document.body.classList.remove('hero-navbar');
+ }
+ }
+ };
+
+ // Set initial state
+ handleScroll();
+
+ // Add scroll listener
+ window.addEventListener('scroll', handleScroll);
+
+ // Cleanup
+ return () => {
+ window.removeEventListener('scroll', handleScroll);
+ document.body.classList.remove('hero-navbar');
Review Comment:
The hero-navbar styling approach applies global styles to the body element's
class rather than scoping styles to the hero section itself. When scrolling,
the body.hero-navbar class is toggled, which affects the entire page's navbar
styling. This creates a tight coupling between the hero section component and
global styles. A more maintainable approach would be to scope the navbar styles
to a container (e.g., .hero-navbar .navbar) or use a data attribute rather than
modifying body classes. This would make the component more portable and reduce
the risk of style conflicts.
```suggestion
if (heroSection && navbar instanceof HTMLElement) {
const heroRect = heroSection.getBoundingClientRect();
const isInHeroSection = heroRect.top <= 100 && heroRect.bottom >= 0;
if (isInHeroSection) {
navbar.classList.add('hero-navbar');
navbar.setAttribute('data-hero-navbar', 'true');
} else {
navbar.classList.remove('hero-navbar');
navbar.removeAttribute('data-hero-navbar');
}
}
};
// Set initial state
handleScroll();
// Add scroll listener
window.addEventListener('scroll', handleScroll);
// Cleanup
return () => {
window.removeEventListener('scroll', handleScroll);
const navbar = document.querySelector('.navbar');
if (navbar instanceof HTMLElement) {
navbar.classList.remove('hero-navbar');
navbar.removeAttribute('data-hero-navbar');
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]