Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create FAQ Accordion Component #13840

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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/FaqAccordian/FaqAccordian.stories.tsx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screen.Recording.2024-10-22.at.11.14.51.mov

Functioning pretty well, just noting we should handle the width. In the DS we have max-width: 52rem; Ultimately though, the width shouldn't change when open vs closed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can implement max-width: 52rem; or near valuemax-w-4xl ==> 56rem. One thing I notice is, its taking parent width if mentioned and fits it to full width (trigger & content both)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screen.Recording.2024-10-23.at.12.38.55.AM.mov

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Meta, StoryObj } from "@storybook/react"

import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "."

const meta = {
title: "FaqAccordion",
component: Accordion,
decorators: [
(Story) => (
<div className="">
<Story />
</div>
),
],
} satisfies Meta<typeof Accordion>

export default meta

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

<AccordionContent>
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.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-2">
<AccordionTrigger>
<h2 className="text-start text-base md:text-xl">
Why is there no &apos;official&apos; Ethereum L2?
</h2>
</AccordionTrigger>
<AccordionContent>
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.
</AccordionContent>
</AccordionItem>
</Accordion>
),
}
92 changes: 92 additions & 0 deletions src/components/FaqAccordian/index.tsx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accordiOn not accordiAn

Need to fix the file paths here: FaqAccordion/index.tsx
(Same with the story: FaqAccordion/FaqAccordion.stories.tsx)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But, this also makes me wonder if we should even be calling this "FaqAccordion", since in the DS it's just called FAQ... @pettinarip Any thoughts here? Simply calling this component/FAQ/index.tsx would work for me, and could just swap "FAQ" for "Accordion" in the exported sub-components in this file.

Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React from "react"
import { MdChevronRight } from "react-icons/md"
import * as AccordionPrimitive from "@radix-ui/react-accordion"

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

import * as RootAccordion from "../../../tailwind/ui/accordion"

const AccordionTrigger = React.forwardRef<
saurabhburade marked this conversation as resolved.
Show resolved Hide resolved
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
// p-4 hover:bg-background-highlight
saurabhburade marked this conversation as resolved.
Show resolved Hide resolved
<AccordionPrimitive.Header className="flex w-full">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we didn't go with the existing AccordionTrigger from tailwind/ui/accordion.tsx, instead of rebuilding from the Radix-UI primitive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used for grouping styles with MdChevronRight ==> "group-hover:border-primary group-hover:text-primary group-hover:shadow-md group-hover:shadow-primary-low-contrast"

<AccordionPrimitive.Trigger
ref={ref}
className={cn(
"px-4 py-3 md:px-8 md:py-6",
"flex flex-1 items-center justify-between gap-2",
"border-t border-body-light",
"focus-visible:outline-1 focus-visible:-outline-offset-1 focus-visible:outline-primary-hover",
"group cursor-pointer text-start font-medium",
"transition-all [&[data-state=open]>svg]:-rotate-90",
className
)}
{...props}
>
{children}

<MdChevronRight
className={cn(
"size-[1em] shrink-0 p-1 text-2xl md:size-[1.25em]",
"rounded-full border",
"group-hover:border-primary group-hover:text-primary group-hover:shadow-md group-hover:shadow-primary-low-contrast",
"transition-transform duration-200"
)}
/>
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
))
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName

// TODO: Prop types
saurabhburade marked this conversation as resolved.
Show resolved Hide resolved
const Accordion = ({ children, ...props }) => {
return (
<RootAccordion.Accordion
type="single"
collapsible
className={cn(
"rounded border border-body-light first:border-t-0",
"overflow-hidden bg-background",
props?.className
)}
{...props}
>
{children}
</RootAccordion.Accordion>
)
}
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => (
<AccordionPrimitive.Item
ref={ref}
className={cn("hover:bg-background-highlight", className)}
{...props}
/>
))
AccordionItem.displayName = "AccordionItem"

const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content
ref={ref}
className={cn(
"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>
</AccordionPrimitive.Content>
))

AccordionContent.displayName = AccordionPrimitive.Content.displayName

export { Accordion, AccordionContent, AccordionItem, AccordionTrigger }
Loading