feat: implement the AccordionItem component

This commit is contained in:
Hossein Mehrabi
2023-12-14 05:29:35 +03:30
parent fa830767b9
commit ab6a5a8048
8 changed files with 171 additions and 10 deletions
@@ -1,18 +1,22 @@
import { useColorMode } from '@docusaurus/theme-common'
import { clsx } from 'clsx'
import React, { CSSProperties } from 'react'
import React from 'react'
import styles from './style.module.scss'
import AddSvg from '../../static/icons/add.svg'
import ArrowLCircleSvg from '../../static/icons/arrow-left-circle.svg'
import ArrowL from '../../static/icons/arrow-left.svg'
import ArrowRCircleSvg from '../../static/icons/arrow-right-circle.svg'
import ArrowR from '../../static/icons/arrow-right.svg'
import Avatar from '../../static/icons/avatar.svg'
import CloseSvg from '../../static/icons/close.svg'
import CopySvg from '../../static/icons/copy.svg'
import DiscordWhiteSvg from '../../static/icons/discord-white.svg'
import DiscordSvg from '../../static/icons/discord.svg'
import DiscourseSvg from '../../static/icons/discourse.svg'
import DotSvg from '../../static/icons/dot.svg'
import DownloadSvg from '../../static/icons/download.svg'
import DropdownSvg from '../../static/icons/dropdown.svg'
import EditSvg from '../../static/icons/edit.svg'
import ExternalLinkSvg from '../../static/icons/external-link.svg'
@@ -23,15 +27,13 @@ import GithubWhiteSvg from '../../static/icons/github-white.svg'
import GScholarSvg from '../../static/icons/gscholar.svg'
import HistorySvg from '../../static/icons/history.svg'
import LinkedinSvg from '../../static/icons/linkedin.svg'
import RemoveSvg from '../../static/icons/remove.svg'
import SearchSvg from '../../static/icons/search.svg'
import StatusSvg from '../../static/icons/status.svg'
import TelegramWhiteSvg from '../../static/icons/telegram-white.svg'
import TelegramSvg from '../../static/icons/telegram.svg'
import TwitterSvg from '../../static/icons/twitter.svg'
import DiscordWhiteSvg from '../../static/icons/discord-white.svg'
import TelegramWhiteSvg from '../../static/icons/telegram-white.svg'
import XWhiteSvg from '../../static/icons/x-white.svg'
import Avatar from '../../static/icons/avatar.svg'
import DownloadSvg from '../../static/icons/download.svg'
type TIconProps = {
size?: 's' | 'm' | 'l'
@@ -40,7 +42,8 @@ type TIconProps = {
type TProps = {
children?: JSX.Element
fill?: string
fill?: boolean
stroke?: boolean
} & TIconProps
export const Icon = (props: TProps): JSX.Element => {
@@ -53,6 +56,8 @@ export const Icon = (props: TProps): JSX.Element => {
styles.icon,
colorMode === 'dark' ? styles.dark : styles.light,
styles[size],
props.stroke && styles.stroke,
props.fill && styles.fill,
props.className && props.className,
)}
>
@@ -234,3 +239,15 @@ export const IconDownload = (props: TIconProps): JSX.Element => (
<DownloadSvg />
</Icon>
)
export const IconAdd = (props: TIconProps): JSX.Element => (
<Icon {...props} stroke>
<AddSvg />
</Icon>
)
export const IconRemove = (props: TIconProps): JSX.Element => (
<Icon {...props} stroke>
<RemoveSvg />
</Icon>
)
@@ -17,13 +17,31 @@
}
&.dark {
.fill {
fill: var(--ifm-color-black);
&.fill {
&,
* {
fill: var(--ifm-color-white);
}
}
.stroke {
stroke: var(--ifm-color-white);
&.stroke {
svg,
svg * {
stroke: var(--ifm-color-white);
}
}
}
&.light {
&.fill {
&,
* {
fill: var(--ifm-color-black);
}
}
&.stroke {
svg,
svg * {
stroke: var(--ifm-color-black);
}
}
}
}
@@ -0,0 +1,45 @@
@use '../../../css/utils';
@use '../../../css/lsd';
.mdx-accordion-item {
border-bottom: 1px solid rgb(var(--lsd-border-primary));
> input {
display: none;
}
}
.mdx-accordion-item__header {
min-height: 88px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 16px 0;
gap: 0 16px;
&,
* {
cursor: pointer;
}
}
.mdx-accordion-item__content-wrapper {
overflow: hidden;
height: auto;
}
.mdx-accordion-item__content {
height: 0;
transition: 0.3s ease;
}
.mdx-accordion-item--open {
.mdx-accordion-item__content {
height: auto;
padding-bottom: 1.875rem;
}
}
@include utils.responsive('lg', 'down') {
}
@@ -0,0 +1,72 @@
import clsx from 'clsx'
import React, { useEffect, useState } from 'react'
import './AccordionItem.scss'
import { Typography } from '@acid-info/lsd-react'
import { IconAdd, IconRemove } from '../../Icon'
import uniqueId from 'lodash/uniqueId'
export type AccordionItemProps = Omit<
React.HTMLProps<HTMLDivElement>,
'title'
> & {
open?: boolean
title: React.ReactNode
onToggle?: (open: boolean) => void
}
export const AccordionItem: React.FC<AccordionItemProps> = ({
open: openProp,
onToggle,
title,
className,
children,
...props
}) => {
const id = uniqueId('accordion-item-')
const [open, setOpen] = useState(openProp ?? false)
if (typeof openProp !== 'undefined' && openProp !== open) {
setOpen(openProp)
}
const handleToggle = () => {
if (typeof openProp !== 'undefined') {
onToggle && onToggle(!open)
} else {
setOpen((val) => !val)
}
}
return (
<div
className={clsx(
className,
'mdx-accordion-item',
open && 'mdx-accordion-item--open',
)}
{...props}
>
<input type="checkbox" id={id} checked={open} />
<div
role="button"
className="mdx-accordion-item__header"
onClick={() => handleToggle()}
>
<Typography
className="mdx-accordion-item__title"
variant="h5"
component="label"
htmlFor={id}
>
{title}
</Typography>
<div className="mdx-accordion-item__icon">
{open ? <IconRemove /> : <IconAdd />}
</div>
</div>
<div className="mdx-accordion-item__content-wrapper">
<div className="mdx-accordion-item__content">{children}</div>
</div>
</div>
)
}
@@ -0,0 +1 @@
export * from './AccordionItem'
@@ -1,3 +1,4 @@
export * from './AccordionItem'
export * from './AppCard'
export * from './AssetCard'
export * from './Box'
@@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="9" y1="17.5" x2="9" y2="0.5" stroke="white"/>
<line x1="0.5" y1="9" x2="17.5" y2="9" stroke="white"/>
</svg>

After

Width:  |  Height:  |  Size: 215 B

@@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="0.5" y1="9" x2="17.5" y2="9" stroke="white"/>
</svg>

After

Width:  |  Height:  |  Size: 159 B