refactor: turn sections into Astro components

This commit is contained in:
MAZE 2023-12-09 16:33:59 +03:30
parent a67083c0e9
commit 9398ae0edd
15 changed files with 345 additions and 340 deletions

View File

@ -86,7 +86,8 @@
"rules": { "rules": {
"prettier/prettier": "error", "prettier/prettier": "error",
"react/no-unknown-property": "off" "react/no-unknown-property": "off",
"react/jsx-key": "off"
}, },
"globals": { "globals": {

View File

@ -0,0 +1,62 @@
---
import { Container } from '@/components/container';
import { count as soundCount } from '@/lib/sounds';
const count = soundCount();
---
<div class="about">
<Container>
<div class="titleWrapper">
<h2 class="title">What is Moodist?</h2>
<div class="line"></div>
</div>
<p class="desc">
Welcome to Moodist your free, open-source ambient sound generator. With <span
>{count} curated sounds</span
>, effortlessly create your custom mix for focus or relaxation. No
accounts, no hassle just pure tranquility. Explore nature&apos;s calm
and urban rhythms. Elevate your ambiance with Moodist, where simplicity
meets serenity.
</p>
</Container>
</div>
<style>
.about {
padding: 80px 0;
& .titleWrapper {
display: flex;
align-items: center;
column-gap: 12px;
& .title {
margin-bottom: 12px;
font-family: var(--font-display);
font-size: var(--font-lg);
font-weight: 600;
}
& .line {
height: 1px;
flex-grow: 1;
background: linear-gradient(
90deg,
var(--color-neutral-300),
transparent
);
transform: translateY(-0.25rem);
}
}
& .desc {
color: var(--color-foreground-subtle);
line-height: 1.7;
& span {
color: var(--color-foreground);
}
}
}
</style>

View File

@ -1,32 +0,0 @@
.about {
padding: 80px 0;
& .titleWrapper {
display: flex;
align-items: center;
column-gap: 12px;
& .title {
margin-bottom: 12px;
font-family: var(--font-display);
font-size: var(--font-lg);
font-weight: 600;
}
& .line {
height: 1px;
flex-grow: 1;
background: linear-gradient(90deg, var(--color-neutral-300), transparent);
transform: translateY(-0.25rem);
}
}
& .desc {
color: var(--color-foreground-subtle);
line-height: 1.7;
& span {
color: var(--color-foreground);
}
}
}

View File

@ -1,28 +0,0 @@
import { useMemo } from 'react';
import { Container } from '@/components/container';
import { count as soundCount } from '@/lib/sounds';
import styles from './about.module.css';
export function About() {
const count = useMemo(soundCount, []);
return (
<div className={styles.about}>
<Container>
<div className={styles.titleWrapper}>
<h2 className={styles.title}>What is Moodist?</h2>
<div className={styles.line} />
</div>
<p className={styles.desc}>
Welcome to Moodist your free, open-source ambient sound generator.
With <span>{count} curated sounds</span>, effortlessly create your
custom mix for focus or relaxation. No accounts, no hassle just pure
tranquility. Explore nature&apos;s calm and urban rhythms. Elevate
your ambiance with Moodist, where simplicity meets serenity.
</p>
</Container>
</div>
);
}

View File

@ -1 +0,0 @@
export { About } from './about';

View File

@ -1,3 +0,0 @@
export { About as AboutSection } from './about';
export { Why as WhySection } from './why';
export { Ready as ReadySection } from './ready';

View File

@ -0,0 +1,119 @@
---
import { RiSparkling2Line } from 'react-icons/ri/index';
import { Container } from '@/components/container';
---
<div class="ready">
<Container>
<div class="wrapper">
<div class="iconContainer">
<div class="tail"></div>
<div class="icon">
<RiSparkling2Line />
</div>
</div>
<h2 class="title">Are you ready?</h2>
<p class="desc">Create your calm oasis in seconds!</p>
<button class="button" id="button"> Use Moodist</button>
</div>
</Container>
</div>
<script>
const button = document.getElementById('button');
button?.addEventListener('click', () => {
const app = document.getElementById('app');
app?.scrollIntoView(true);
});
</script>
<style>
.ready {
& .wrapper {
position: relative;
padding: 0 20px 40px;
border-radius: 0 0 20px 20px;
background: linear-gradient(transparent, var(--color-neutral-100));
&::after {
position: absolute;
bottom: 0;
left: 50%;
width: 70%;
height: 1px;
background: linear-gradient(
90deg,
transparent,
var(--color-neutral-300),
transparent
);
content: '';
transform: translateX(-50%);
}
}
& .iconContainer {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 15px;
& .tail {
width: 1px;
height: 75px;
background: linear-gradient(transparent, var(--color-neutral-300));
}
& .icon {
display: flex;
width: 45px;
height: 45px;
align-items: center;
justify-content: center;
border: 1px solid var(--color-neutral-300);
border-radius: 50%;
background-color: var(--color-neutral-100);
color: #fbbf24;
font-size: var(--font-md);
}
}
& .title {
margin-bottom: 12px;
font-family: var(--font-display);
font-size: var(--font-lg);
font-weight: 600;
text-align: center;
}
& .desc {
color: var(--color-foreground-subtle);
text-align: center;
}
& .button {
display: flex;
width: 120px;
height: 40px;
align-items: center;
justify-content: center;
border: none;
border-radius: 100px;
border-top: 2px solid var(--color-neutral-950);
border-bottom: 3px solid var(--color-neutral-600);
margin: 24px auto 0;
background-color: var(--color-neutral-700);
color: var(--color-neutral-200);
cursor: pointer;
font-family: var(--font-heading);
font-size: var(--font-sm);
line-height: 0;
outline: none;
text-decoration: none;
}
}
</style>

View File

@ -1 +0,0 @@
export { Ready } from './ready';

View File

@ -1,84 +0,0 @@
.ready {
& .wrapper {
position: relative;
padding: 0 20px 40px;
border-radius: 0 0 20px 20px;
background: linear-gradient(transparent, var(--color-neutral-100));
&::after {
position: absolute;
bottom: 0;
left: 50%;
width: 70%;
height: 1px;
background: linear-gradient(
90deg,
transparent,
var(--color-neutral-300),
transparent
);
content: '';
transform: translateX(-50%);
}
}
& .iconContainer {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 15px;
& .tail {
width: 1px;
height: 75px;
background: linear-gradient(transparent, var(--color-neutral-300));
}
& .icon {
display: flex;
width: 45px;
height: 45px;
align-items: center;
justify-content: center;
border: 1px solid var(--color-neutral-300);
border-radius: 50%;
background-color: var(--color-neutral-100);
color: #fbbf24;
font-size: var(--font-md);
}
}
& .title {
margin-bottom: 12px;
font-family: var(--font-display);
font-size: var(--font-lg);
font-weight: 600;
text-align: center;
}
& .desc {
color: var(--color-foreground-subtle);
text-align: center;
}
& .button {
display: flex;
width: 120px;
height: 40px;
align-items: center;
justify-content: center;
border: none;
border-radius: 100px;
border-top: 2px solid var(--color-neutral-950);
border-bottom: 3px solid var(--color-neutral-600);
margin: 24px auto 0;
background-color: var(--color-neutral-700);
color: var(--color-neutral-200);
cursor: pointer;
font-family: var(--font-heading);
font-size: var(--font-sm);
line-height: 0;
outline: none;
text-decoration: none;
}
}

View File

@ -1,34 +0,0 @@
import { RiSparkling2Line } from 'react-icons/ri/index';
import { Container } from '@/components/container';
import styles from './ready.module.css';
export function Ready() {
const handleClick = () => {
const app = document.getElementById('app');
app?.scrollIntoView(true);
};
return (
<div className={styles.ready}>
<Container>
<div className={styles.wrapper}>
<div className={styles.iconContainer}>
<div className={styles.tail} />
<div className={styles.icon}>
<RiSparkling2Line />
</div>
</div>
<h2 className={styles.title}>Are you ready?</h2>
<p className={styles.desc}>Create your calm oasis in seconds!</p>
<button className={styles.button} onClick={handleClick}>
Use Moodist
</button>
</div>
</Container>
</div>
);
}

View File

@ -0,0 +1,157 @@
---
import { BiMoney, BiUserCircle, BiLogoGithub } from 'react-icons/bi/index';
import { BsSoundwave, BsStars } from 'react-icons/bs/index';
import { RxMixerHorizontal } from 'react-icons/rx/index';
import { Balancer } from 'react-wrap-balancer';
import { Container } from '@/components/container';
import { count as soundCount } from '@/lib/sounds';
const count = soundCount();
const reasons = [
{
Icon: BiMoney,
body: "Immerse yourself in Moodist's ambient world without spending a dime. All features are accessible to everyone, ensuring a cost-free auditory journey.",
id: 'free-access',
label: 'Free Access',
},
{
Icon: BiUserCircle,
body: 'Embrace simplicity Moodist skips the registration process. No accounts, no hassle; just click, play, and enjoy the serenity.',
id: 'no-registration',
label: 'No Registration',
},
{
Icon: BsSoundwave,
body: `With a curated collection of ${count} sounds, Moodist offers a spectrum of auditory experiences. From the tranquility of nature to the beat of urban life, find the perfect backdrop for your mood.`,
id: 'diverse-sounds',
label: 'Diverse Sounds',
},
{
Icon: RxMixerHorizontal,
body: 'Tailor your ambiance effortlessly. Moodist allows you to create personalized mixes, adjusting the blend of sounds to suit your focus or relaxation needs.',
id: 'customizable-mixes',
label: 'Customizable Mixes',
},
{
Icon: BiLogoGithub,
body: 'Trust in transparency. Moodist is open-source, fostering collaboration and providing users with a platform they can explore and understand.',
id: 'open-source',
label: 'Open-Source',
link: {
label: 'Source Code',
url: 'https://github.com/remvze/moodist',
},
},
{
Icon: BsStars,
body: 'Navigate with ease. Moodist provides a user-friendly interface, ensuring a smooth and hassle-free experience as you explore the diverse soundscape of calm and rhythm.',
id: 'seamless-experience',
label: 'Seamless Experience',
},
];
---
<div class="why">
<Container>
<div class="titleWrapper">
<h2 class="title">Why use Moodist?</h2>
<div class="line"></div>
</div>
<div class="reasons">
{
reasons.map(reason => (
<div class="reason">
<div class="icon">
<reason.Icon />
</div>
<h3 class="label">{reason.label}</h3>
<p class="body">
<Balancer>{reason.body}</Balancer>
</p>
{reason.link && (
<a class="link" href={reason.link.url}>
{reason.link.label} →
</a>
)}
</div>
))
}
</div>
</Container>
</div>
<style>
.why {
padding-bottom: 80px;
& .titleWrapper {
display: flex;
align-items: center;
column-gap: 12px;
& .title {
margin-bottom: 12px;
font-family: var(--font-display);
font-size: var(--font-lg);
font-weight: 600;
}
& .line {
height: 1px;
flex-grow: 1;
background: linear-gradient(
90deg,
var(--color-neutral-300),
transparent
);
transform: translateY(-0.25rem);
}
}
& .reasons {
display: grid;
margin-top: 24px;
column-gap: 20px;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
row-gap: 28px;
& .icon {
display: flex;
width: 40px;
height: 40px;
align-items: center;
justify-content: center;
border: 1px solid var(--color-neutral-200);
border-radius: 12px;
margin-bottom: 12px;
background: linear-gradient(var(--color-neutral-100), transparent);
color: #34d399;
font-size: var(--font-md);
}
& .label {
margin-bottom: 8px;
font-family: var(--font-heading);
font-weight: 600;
}
& .body {
color: var(--color-foreground-subtle);
line-height: 1.6;
}
& .link {
display: block;
margin-top: 8px;
color: var(--color-foreground);
font-size: var(--font-sm);
font-weight: 500;
text-decoration: none;
}
}
}
</style>

View File

@ -1 +0,0 @@
export { Why } from './why';

View File

@ -1,65 +0,0 @@
.why {
padding-bottom: 80px;
& .titleWrapper {
display: flex;
align-items: center;
column-gap: 12px;
& .title {
margin-bottom: 12px;
font-family: var(--font-display);
font-size: var(--font-lg);
font-weight: 600;
}
& .line {
height: 1px;
flex-grow: 1;
background: linear-gradient(90deg, var(--color-neutral-300), transparent);
transform: translateY(-0.25rem);
}
}
& .reasons {
display: grid;
margin-top: 24px;
column-gap: 20px;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
row-gap: 28px;
& .icon {
display: flex;
width: 40px;
height: 40px;
align-items: center;
justify-content: center;
border: 1px solid var(--color-neutral-200);
border-radius: 12px;
margin-bottom: 12px;
background: linear-gradient(var(--color-neutral-100), transparent);
color: #34d399;
font-size: var(--font-md);
}
& .label {
margin-bottom: 8px;
font-family: var(--font-heading);
font-weight: 600;
}
& .body {
color: var(--color-foreground-subtle);
line-height: 1.6;
}
& .link {
display: block;
margin-top: 8px;
color: var(--color-foreground);
font-size: var(--font-sm);
font-weight: 500;
text-decoration: none;
}
}
}

View File

@ -1,86 +0,0 @@
import { useMemo } from 'react';
import { BiMoney, BiUserCircle, BiLogoGithub } from 'react-icons/bi/index';
import { BsSoundwave, BsStars } from 'react-icons/bs/index';
import { RxMixerHorizontal } from 'react-icons/rx/index';
import { Balancer } from 'react-wrap-balancer';
import { Container } from '@/components/container';
import { count as soundCount } from '@/lib/sounds';
import styles from './why.module.css';
export function Why() {
const count = useMemo(soundCount, []);
const reasons = [
{
body: "Immerse yourself in Moodist's ambient world without spending a dime. All features are accessible to everyone, ensuring a cost-free auditory journey.",
icon: <BiMoney />,
id: 'free-access',
label: 'Free Access',
},
{
body: 'Embrace simplicity Moodist skips the registration process. No accounts, no hassle; just click, play, and enjoy the serenity.',
icon: <BiUserCircle />,
id: 'no-registration',
label: 'No Registration',
},
{
body: `With a curated collection of ${count} sounds, Moodist offers a spectrum of auditory experiences. From the tranquility of nature to the beat of urban life, find the perfect backdrop for your mood.`,
icon: <BsSoundwave />,
id: 'diverse-sounds',
label: 'Diverse Sounds',
},
{
body: 'Tailor your ambiance effortlessly. Moodist allows you to create personalized mixes, adjusting the blend of sounds to suit your focus or relaxation needs.',
icon: <RxMixerHorizontal />,
id: 'customizable-mixes',
label: 'Customizable Mixes',
},
{
body: 'Trust in transparency. Moodist is open-source, fostering collaboration and providing users with a platform they can explore and understand.',
icon: <BiLogoGithub />,
id: 'open-source',
label: 'Open-Source',
link: {
label: 'Source Code',
url: 'https://github.com/remvze/moodist',
},
},
{
body: 'Navigate with ease. Moodist provides a user-friendly interface, ensuring a smooth and hassle-free experience as you explore the diverse soundscape of calm and rhythm.',
icon: <BsStars />,
id: 'seamless-experience',
label: 'Seamless Experience',
},
];
return (
<div className={styles.why}>
<Container>
<div className={styles.titleWrapper}>
<h2 className={styles.title}>Why use Moodist?</h2>
<div className={styles.line} />
</div>
<div className={styles.reasons}>
{reasons.map(reason => (
<div className={styles.reason} key={reason.id}>
<div className={styles.icon}>{reason.icon}</div>
<h3 className={styles.label}>{reason.label}</h3>
<p className={styles.body}>
<Balancer>{reason.body}</Balancer>
</p>
{reason.link && (
<a className={styles.link} href={reason.link.url}>
{reason.link.label}
</a>
)}
</div>
))}
</div>
</Container>
</div>
);
}

View File

@ -1,11 +1,12 @@
--- ---
import Layout from '@/layouts/layout.astro'; import Layout from '@/layouts/layout.astro';
import Footer from '@/components/footer.astro';
import AboutSection from '@/components/sections/about.astro';
import WhySection from '@/components/sections/why.astro';
import ReadySection from '@/components/sections/ready.astro';
import { Hero } from '@/components/hero'; import { Hero } from '@/components/hero';
import { App } from '@/components/app'; import { App } from '@/components/app';
import { AboutSection, WhySection, ReadySection } from '@/components/sections';
import Footer from '@/components/footer.astro';
--- ---
<Layout title="Moodist: Ambient Sounds for Focus and Calm"> <Layout title="Moodist: Ambient Sounds for Focus and Calm">
@ -13,6 +14,6 @@ import Footer from '@/components/footer.astro';
<App client:load /> <App client:load />
<AboutSection /> <AboutSection />
<WhySection /> <WhySection />
<ReadySection client:load /> <ReadySection />
<Footer /> <Footer />
</Layout> </Layout>