63
loading...
This website collects cookies to deliver better user experience
---
import site from "../data/site.json";
const {nav} = site;
---
<header id="header">
<ul>
{nav.map((item) => (
<li>
<a href={item.link} target={item.target} rel="noopener noreferrer">{item.name}</a>
</li>
))}
</ul>
</header>
<script type="text/javascript">
const header = document.getElementById("header");
window.onscroll = function() {
if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) {
header.classList.add("active");
} else {
header.classList.remove("active");
}
};
</script>
.astro
file into a .jsx
file (React).Astro.config.mjs
file and make sure the renderers include the following element.renderers: ['@astrojs/renderer-react'],
import React, {useState, useEffect} from 'react';
import site from '../../data/site.json';
const {nav} = site;
import './header.scss'; // include global CSS
const Header = () => {
return (
<header id="header">
<ul>
{nav.map((item, i) => (
<li key={i}>
<a href={item.link} target={item.target} rel="noopener noreferrer">
{item.name}
</a>
</li>
))}
</ul>
</header>
);
};
export default Header;
const Header = () => {
const [colorChange, setColorchange] = useState(false);
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
function handleScroll() {
if (window.pageYOffset > 50) {
return setColorchange(true);
}
return setColorchange(false);
}
return (
<header id="header" className={colorChange ? 'active' : ''}>
<ul>
{nav.map((item, i) => (
<li key={i}>
<a href={item.link} target={item.target} rel="noopener noreferrer">
{item.name}
</a>
</li>
))}
</ul>
</header>
);
};
handleScroll
function.pages/index.astro
file.client:load
: Hydrates on page loadclient:idle
: Hydrate as soon as the main thread is freeclient:visible
: Hydrate as soon as this component hits the viewportclient:media={query}
: Hydrate when a specific media query is metimport Header from '../components/header/Header.jsx';
<Header client:load />;
import React, {useState, useEffect} from 'react';
import TestimonialItem from './TestimonialItem.jsx';
import site from '../../data/site.json';
const title = `Don't take my word for it`;
const {testimonials} = site;
import './testimonials.scss'; // include global CSS
const Testimonials = () => {
const [activeSlide, setActiveSlide] = useState(0);
useEffect(() => {
const timeout = setTimeout(() => {
const newIndex = activeSlide + 1 === testimonials.length ? 0 : activeSlide + 1;
setActiveSlide(newIndex);
}, 5000);
return () => {
clearTimeout(timeout);
};
}, [activeSlide]);
return (
<section id="testimonials">
<h2>{title}</h2>
<div className="testimonial-grid">
{testimonials.map((testimonial, i) => (
<TestimonialItem key={i} item={testimonial} active={activeSlide === i} />
))}
</div>
</section>
);
};
export default Testimonials;
import React from 'react';
import './testimonials.scss'; // include global CSS
const TestimonialItem = ({item, active}) => {
return (
<div className={active ? 'testimonial-item active' : 'testimonial-item'}>
<div className="testimonial-item--inner">
<img width="64" height="64" src={item.image} alt={item.name} />
<div className="testimonial-item--content">
<strong>
{item.name} <i>{item.title}</i>
</strong>
<br />
<p>{item.quote}</p>
</div>
</div>
</div>
);
};
export default TestimonialItem;
client:visible
option.import Testimonials from '../components/testimonials/Testimonials.jsx';
<Testimonials client:visible />;