Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions src/components/Faq/Faq.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Meta, StoryObj } from "@storybook/react"

import { Faq as FaqComponent, FaqContent, FaqItem, FaqTrigger } from "."

const meta = {
title: "Molecules / Display Content / Faq",
component: FaqComponent,
decorators: [
(Story) => (
<div className="mx-auto w-[calc(100vw-2rem)] max-w-[min(52rem,100%)] p-4">
<Story />
</div>
),
],
} satisfies Meta<typeof FaqComponent>

export default meta

export const Faq: StoryObj = {
render: () => (
<FaqComponent type="single" collapsible>
<FaqItem value="item-1">
<FaqTrigger>
<h2 className="text-start text-base md:text-xl">
Why is there no &apos;official&apos; Ethereum L2?
</h2>
</FaqTrigger>

<FaqContent>
Just as there is no &apos;official&apos; Ethereum client, there is no
&apos;official&apos; Ethereum layer 2. Ethereum is permissionless -
technically anyone can create a layer 2! Multiple teams will implement
their version of a layer 2, and the ecosystem as a whole will benefit
from a diversity of design approaches that are optimized for different
use cases. Much like we have multiple Ethereum clients developed by
multiple teams in order to have diversity in the network, this too
will be how layer 2s develop in the future.
</FaqContent>
</FaqItem>
<FaqItem value="item-2">
<FaqTrigger>
<h2 className="text-start text-base md:text-xl">
Why is there no &apos;official&apos; Ethereum L2?
</h2>
</FaqTrigger>
<FaqContent>
Just as there is no &apos;official&apos; Ethereum client, there is no
&apos;official&apos; Ethereum layer 2. Ethereum is permissionless -
technically anyone can create a layer 2! Multiple teams will implement
their version of a layer 2, and the ecosystem as a whole will benefit
from a diversity of design approaches that are optimized for different
use cases. Much like we have multiple Ethereum clients developed by
multiple teams in order to have diversity in the network, this too
will be how layer 2s develop in the future.
</FaqContent>
</FaqItem>
</FaqComponent>
),
}
91 changes: 91 additions & 0 deletions src/components/Faq/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React from "react"
import * as AccordionPrimitive from "@radix-ui/react-accordion"

import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"

import { cn } from "@/lib/utils/cn"

const FaqTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<AccordionTrigger
ref={ref}
className={cn(
"w-full p-4 md:px-8 md:py-6",
"text-start font-medium",
"hover:text-body [&[data-state=open]_h2]:text-current [&[data-state=open]_svg]:-rotate-90 hover:[&_h2]:!text-body [&_svg]:rotate-90",
"[&_[data-label='icon-container']]:ms-8 [&_[data-label='icon-container']]:rounded-full [&_[data-label='icon-container']]:border [&_[data-label='icon-container']]:border-body [&_[data-label='icon-container']]:p-2 [&_svg]:text-lg",
"[&_[data-label='icon-container']:hover_svg]:text-primary-hover hover:[&_[data-label='icon-container']]:!border-primary-hover hover:[&_[data-label='icon-container']]:shadow-[4px_4px_0_hsla(var(--primary-low-contrast),1)]",
"[&[data-state=open]]:text-current",
className
)}
{...props}
>
{children}
</AccordionTrigger>
))
FaqTrigger.displayName = AccordionPrimitive.Trigger.displayName

const Faq = ({
children,
type,
...props
}: AccordionPrimitive.AccordionSingleProps) => {
return (
<Accordion
type={type}
collapsible
className={cn(
"overflow-hidden rounded border",
"w-full bg-background",
props?.className
)}
{...props}
>
{children}
</Accordion>
)
}

const FaqItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => (
<AccordionItem
ref={ref}
className={cn(
"w-full border-b last:border-b-0 hover:bg-background-highlight [&[data-state=open]]:bg-background-highlight",
className
)}
{...props}
/>
))
FaqItem.displayName = "AccordionItem"

const FaqContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<AccordionContent
ref={ref}
className={cn(
"w-full overflow-hidden px-4 text-sm md:px-8",
"transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
)}
{...props}
>
<div className={cn("border-t border-body-light py-3 md:py-6", className)}>
{children}
</div>
</AccordionContent>
))

FaqContent.displayName = AccordionPrimitive.Content.displayName

export { Faq, FaqContent, FaqItem, FaqTrigger }
4 changes: 3 additions & 1 deletion src/components/ui/accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ const AccordionTrigger = React.forwardRef<
<>
{children}
{!hideIcon && (
<ChevronNext className="size-[1em] shrink-0 text-2xl transition-transform duration-200" />
<div data-label="icon-container">
<ChevronNext className="size-[1em] shrink-0 text-2xl transition-transform duration-200" />
</div>
)}
</>
</AccordionPrimitive.Trigger>
Expand Down