feat(landing): slicing faq section
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import { Button } from '@imphnen-frontend-service/ui/atoms'
|
||||
import { Accordion, AccordionOptions } from '@imphnen-frontend-service/ui/molecules'
|
||||
import { FC, useRef } from 'react'
|
||||
import { motion, useInView, Variants } from 'framer-motion'
|
||||
import { cn, For } from '@imphnen-frontend-service/utils'
|
||||
|
||||
const FAQ_DATA: AccordionOptions[] = [
|
||||
{ title: 'Apakah saya bisa memilih mentor sendiri?', description: 'Tentu! Kamu bisa memilih mentor yang sesuai dengan kebutuhan dan level skill kamu.' },
|
||||
{ title: 'Apakah mentoring ini cocok untuk pemula?', description: 'Yap! Baik newbie maupun seasoned dev bisa menemukan mentor yang pas untuk mempercepat progres belajarnya.' },
|
||||
{ title: 'Apakah ini seperti sekolah coding biasa?', description: 'Nope! Ini lebih dari sekadar kursus-kursus AI guide dan mentor berpengalaman, kamu mendapatkan pengalaman belajar yang jauh lebih personal dan efektif.' },
|
||||
]
|
||||
|
||||
export const FAQSection: FC = () => {
|
||||
const ref = useRef(null)
|
||||
const isInView = useInView(ref, { once: true, amount: 0.2 })
|
||||
|
||||
const containerVariants: Variants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.1,
|
||||
delayChildren: 0.2,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const childVariants: Variants = {
|
||||
hidden: { opacity: 0, y: 20 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
duration: 0.4,
|
||||
ease: [0.25, 0.46, 0.45, 0.94],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return (
|
||||
<section ref={ref} className="mx-auto py-4 px-8 md:py-8 md:px-[60px] lg:px-20 md:pb-8">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
viewport={{ once: true }}
|
||||
className="mb-6 flex justify-center md:mb-10"
|
||||
>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="bordered"
|
||||
className="h-auto px-3 py-2 font-semibold bg-primary-100 md:text-base md:px-5 md:py-2.5 lg:text-2xl lg:px-6 lg:py-3"
|
||||
>
|
||||
Frequently Ask Question
|
||||
</Button>
|
||||
</motion.div>
|
||||
|
||||
<div
|
||||
className={cn(
|
||||
"grid max-w-7xl mx-auto gap-y-7 divide-y-2 divide-primary-200",
|
||||
"md:grid-cols-11 md:gap-x-10 md:divide-y-0 md:divide-x-2 lg:grid-cols-7 lg:gap-x-[72px]"
|
||||
)}
|
||||
>
|
||||
<motion.h1
|
||||
className={cn(
|
||||
"pb-7 text-2xl font-semibold text-primary-500 text-center leading-none",
|
||||
"md:pe-10 md:pb-0 md:text-start md:col-span-5 lg:text-4xl lg:col-span-3 lg:pe-[72px]"
|
||||
)}
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
viewport={{ once: true }}
|
||||
>
|
||||
Console log for new developers
|
||||
</motion.h1>
|
||||
|
||||
<motion.div
|
||||
className="flex flex-col gap-4 md:col-span-6 lg:col-span-4"
|
||||
variants={containerVariants}
|
||||
animate={isInView ? "visible" : "hidden"}
|
||||
>
|
||||
<For data={FAQ_DATA}>
|
||||
{(props) => (
|
||||
<motion.div key={props.title} variants={childVariants}>
|
||||
<Accordion {...props} />
|
||||
</motion.div>
|
||||
)}
|
||||
</For>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { FC, ReactElement } from 'react';
|
||||
import { HeroSection } from './_components/hero-section';
|
||||
import { WhatWeOfferSection } from './_components/what-we-offer-section';
|
||||
import { TestimonialSection } from './_components/testimonial-section';
|
||||
import { FAQSection } from './_components/faq-section';
|
||||
|
||||
export const Components: FC = (): ReactElement => {
|
||||
return (
|
||||
@@ -9,6 +10,7 @@ export const Components: FC = (): ReactElement => {
|
||||
<HeroSection />
|
||||
<WhatWeOfferSection />
|
||||
<TestimonialSection />
|
||||
<FAQSection />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import { cn, Show } from "@imphnen-frontend-service/utils"
|
||||
import { DetailedHTMLProps, FC, HTMLAttributes, useState } from "react"
|
||||
import { AnimatePresence, motion, Variants } from "framer-motion"
|
||||
import { MinusOutlined, PlusOutlined } from "@ant-design/icons"
|
||||
|
||||
export type AccordionOptions = {
|
||||
title: string
|
||||
description: string
|
||||
}
|
||||
|
||||
export type AccordionProps = DetailedHTMLProps<
|
||||
HTMLAttributes<HTMLDivElement>,
|
||||
HTMLDivElement
|
||||
> & AccordionOptions & {
|
||||
titleClassName?: string
|
||||
contentClassName?: string
|
||||
}
|
||||
|
||||
export const Accordion: FC<AccordionProps> = ({ title, description, className, titleClassName, contentClassName, ...rest }) => {
|
||||
const [expand, setExpand] = useState(false)
|
||||
|
||||
const variants: Variants = {
|
||||
expand: { opacity: 1, y: 0, marginBottom: 16, height: 'auto' },
|
||||
collapse: { opacity: 0, y: -10, marginBottom: 0, height: 0 },
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn("bg-white rounded-lg shadow cursor-pointer", className)} {...rest}>
|
||||
<div className="px-5 py-4 select-none flex justify-between items-center gap-x-2" onClick={() => setExpand(prev => !prev)}>
|
||||
<h4 className={cn("text-primary-500 font-semibold text-lg leading-tight md:text-xl", titleClassName)}>{title}</h4>
|
||||
<div className={cn("text-primary-500 transition-all duration-300", expand && "rotate-90")}>
|
||||
<Show condition={expand} fallback={<PlusOutlined />}>
|
||||
<MinusOutlined className="rotate-90" />
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
<AnimatePresence>
|
||||
{expand && (
|
||||
<motion.p
|
||||
className={cn("px-5 text-neutral-500 text-sm font-medium cursor-text md:text-base", contentClassName)}
|
||||
variants={variants}
|
||||
initial="collapse"
|
||||
animate="expand"
|
||||
exit="collapse"
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
{description}
|
||||
</motion.p>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './accordion';
|
||||
@@ -4,3 +4,4 @@ export * from './input-field';
|
||||
export * from './pagination';
|
||||
export * from './modal/modal';
|
||||
export * from './stepper';
|
||||
export * from './accordion';
|
||||
Reference in New Issue
Block a user