Skip to content

Commit

Permalink
Merge pull request #34 from zyx7eam/development
Browse files Browse the repository at this point in the history
Multiple boolean prop added to accordion to enable multi expandable &…
  • Loading branch information
hamudeshahin committed Jun 18, 2024
2 parents 2be9984 + 81d4321 commit 9572dfd
Show file tree
Hide file tree
Showing 8 changed files with 5,150 additions and 3,979 deletions.
4 changes: 2 additions & 2 deletions apps/web/src/app/examples/accordion/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

import React from 'react';
import Accordion, { AccordionItem } from '@zyxui/accordion/src';
import Accordion, { AccordionItem } from '@zyxui/accordion';

let items = [
{ key: 'one', title: 'one title', children: 'one children' },
Expand All @@ -16,7 +16,7 @@ let items = [

const AccordionExample = () => {
return (
<Accordion defaultExpandedKeys={['one']} variant='bordered'>
<Accordion defaultExpandedKeys={['one']} multiple={true} iconPosition='end'>
<AccordionItem key={'one'} title={'Test Text'} hasChildItems={false}>
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Veniam
adipisci ut cumque assumenda blanditiis corrupti illo iste quis delectus
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"turbo": "latest",
"prettier-plugin-tailwindcss": "^0.4.1"
},
"packageManager": "pnpm@8.6.10",
"packageManager": "pnpm@9.1.4",
"dependencies": {
"tailwindcss": "^3.3.5"
}
Expand Down
2 changes: 0 additions & 2 deletions packages/components/accordion/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"homepage": "https://ui.geeksteam.org",
"license": "MIT",
"main": "./src/index.ts",
"types": "./src/index.d.ts",
"sideEffects": false,
"files": [
"src"
Expand Down Expand Up @@ -48,7 +47,6 @@
"@react-types/shared": "^3.22.1",
"@zyxui/lib": "workspace:*",
"@zyxui/tsconfig": "workspace:*",
"class-variance-authority": "^0.7.0",
"framer-motion": "^10.16.5",
"lucide-react": "^0.292.0",
"tailwind-variants": "^0.2.1",
Expand Down
120 changes: 110 additions & 10 deletions packages/components/accordion/src/accordion-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,138 @@ import { useRef } from 'react';
import { useAccordionItem } from './use-accordion';
import { FocusRing } from '@react-aria/focus';
import { useHover, useFocus } from '@react-aria/interactions';
import { ChevronDownIcon } from 'lucide-react';

import { mergeProps } from '@react-aria/utils';
import { VariantProps, tv } from 'tailwind-variants';
import { AnimationConfig, BodyTransitionType, iconSizes } from './accordion';

interface AccordionItemProps<T> {
import {
LazyMotion,
m,
domAnimation,
AnimatePresence,
MotionConfig,
Transition,
} from 'framer-motion';

const accordionItemVariants = tv({
slots: {
button: 'flex w-full bg-red-300 justify-between items-center',
body: 'bg-yellow-100 h-full',
icon: '',
text: 'text-inherit',
},
variants: {
size: {
sm: {},
md: {},
lg: {},
},
iconPosition: {
start: {
text: 'order-2',
icon: 'order-1',
button: 'justify-start',
},
end: {
text: 'order-1',
icon: 'order-2',
},
},
},
compoundSlots: [
{
size: 'sm',
slots: ['button', 'body'],
class: ['p-2 text-[14px]'],
},
{
size: 'md',
slots: ['button', 'body'],
class: ['p-4 text-[18px]'],
},
{
size: 'lg',
slots: ['button', 'body'],
class: ['p-6 text-[24px]'],
},
],
});

type AccordionItemVariants = VariantProps<typeof accordionItemVariants>;

type AccordionItemProps<T> = {
item: Node<T>;
state: TreeState<T>;
}
multiple?: boolean;
size?: keyof typeof iconSizes;
// animationConfig?: AnimationConfig;
animationConfig?: Transition;
} & AccordionItemVariants;

function AccordionItem<T>({ item, state }: AccordionItemProps<T>) {
function AccordionItem<T>({
item,
state,
multiple,
size,
iconPosition,
animationConfig,
}: AccordionItemProps<T>) {
let ref = useRef<HTMLButtonElement>(null);
let { buttonProps, regionProps, toggle } = useAccordionItem(
{ item },
let { buttonProps, regionProps } = useAccordionItem(
{ item, multiple },
state,
ref,
);

let isExpanded = state.expandedKeys.has(item.key);
let isDisabled = state.disabledKeys.has(item.key);

// extract slot from variants
const { button, body, icon, text } = accordionItemVariants({});

// button focus props
const { focusProps } = useFocus({ isDisabled });

return (
<div>
<LazyMotion features={domAnimation} strict>
<h3>
<button {...mergeProps(buttonProps, focusProps)} ref={ref}>
{item.rendered}
<button
{...mergeProps(buttonProps, focusProps)}
className={button({ size, iconPosition })}
ref={ref}
>
<span className={text({ iconPosition })}>{item.rendered}</span>
<m.span
className={icon({ iconPosition })}
style={{ overflow: 'hidden' }}
initial={{ rotate: isExpanded ? 180 : 0 }}
animate={{ rotate: isExpanded ? 180 : 0 }}
exit={{ rotate: 0 }}
>
<ChevronDownIcon size={iconSizes[size || 'md']} />
</m.span>
</button>
</h3>

{isExpanded && <div {...regionProps}>{item.props.children}</div>}
</div>
<AnimatePresence initial={isExpanded} presenceAffectsLayout>
<MotionConfig transition={animationConfig}>
<m.div
style={{ overflow: 'hidden', background: 'transparent' }}
initial={{ height: 'auto' }}
animate={{
height: isExpanded ? 'auto' : 0,
}}
exit={{ height: 0 }}
>
<div {...regionProps} className={body({ size })}>
{item.props.children}
</div>
</m.div>
</MotionConfig>
</AnimatePresence>
</LazyMotion>
);
}

Expand Down
72 changes: 56 additions & 16 deletions packages/components/accordion/src/accordion.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,39 @@
// 'use client';

import { useTreeState } from '@react-stately/tree';

import { useAccordion } from './use-accordion';
import React, { RefObject, useImperativeHandle, useMemo, useRef } from 'react';
import React, { RefObject, useMemo } from 'react';
import { filterDOMProps, useObjectRef } from '@react-aria/utils';
import AccordionItem from './accordion-item';
import { AriaAccordionProps } from '@react-types/accordion';
import { tv } from 'tailwind-variants';
import { VariantProps } from 'class-variance-authority';
import type { VariantProps } from 'tailwind-variants';
import { Item } from '@react-stately/collections';
import { CollectionChildren } from '@react-types/shared';
// export { Item } from '@react-stately/collections';
import { Transition } from 'framer-motion';

export const iconSizes = {
sm: 14,
md: 18,
lg: 24,
};

export type IconSizeType = keyof typeof iconSizes;

export type BodyTransitionType =
| 'inertia'
| 'spring'
| 'just'
| 'keyframes'
| 'tween';

export type AnimationConfig = {
enabled?: boolean;
duration?: number;
easing?: string;
delay?: number;
bodyTransitionType?: BodyTransitionType;
};

const accordionVariants = tv({
base: 'w-full bg-red-200',
base: 'w-full bg-black',
variants: {
variant: {
default: 'border-0',
Expand All @@ -28,21 +47,34 @@ const accordionVariants = tv({

type AccordionVariants = VariantProps<typeof accordionVariants>;

export type Item<T> = {
key: string;
title: string;
children: React.ReactNode;
hasChildItems?: boolean;
};
// export type Item<T> = {
// key: string;
// title: string;
// children: React.ReactNode;
// hasChildItems?: boolean;
// };

export type AccordionProps<T extends object> = AriaAccordionProps<T> &
AccordionVariants & {
ref?: RefObject<HTMLDivElement>;
twClassName?: string;
multiple?: boolean;
size?: IconSizeType;
iconPosition?: 'start' | 'end';
// animationConfig?: AnimationConfig;
animationConfig?: Transition;
};

function Accordion<T extends object>(props: AccordionProps<T>) {
const { variant, twClassName, ...__restProps } = props;
const {
variant,
twClassName,
multiple,
size = 'md',
iconPosition = 'end',
animationConfig = {},
...__restProps
} = props;

const ref = useObjectRef(__restProps?.ref);

Expand All @@ -61,7 +93,15 @@ function Accordion<T extends object>(props: AccordionProps<T>) {
const __items = useMemo(
() =>
[...state.collection].map((item) => (
<AccordionItem key={item.key} item={item} state={state} />
<AccordionItem
key={item.key}
item={item}
state={state}
multiple={multiple}
size={size}
iconPosition={iconPosition}
animationConfig={animationConfig}
/>
)),
[state.collection],
);
Expand Down
13 changes: 0 additions & 13 deletions packages/components/accordion/src/index.d.ts

This file was deleted.

Loading

0 comments on commit 9572dfd

Please sign in to comment.