Skip to content

Commit

Permalink
Added Accordion Component (#23)
Browse files Browse the repository at this point in the history
Co-authored-by: Ashwathi23 <[email protected]>
  • Loading branch information
Ashwathi23 and Ashwathi23 authored Oct 1, 2024
1 parent 78a8488 commit d9b5aee
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 0 deletions.
23 changes: 23 additions & 0 deletions src/components/Accordion/Accordion.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Meta, StoryObj } from '@storybook/react';
import { Accordion } from './Accordion';

const meta: Meta<typeof Accordion> = {
title: 'Components/Accordion',
component: Accordion,
};

export default meta;
type Story = StoryObj<typeof Accordion>;

const defaultProps = {
items: [
{ title: 'Section 1', content: 'Content for section 1' },
{ title: 'Section 2', content: 'Content for section 2' },
],
};

export const Default: Story = {
args: {
...defaultProps,
},
};
25 changes: 25 additions & 0 deletions src/components/Accordion/Accordion.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import styled from 'styled-components';

export const AccordionContainer = styled.div`
width: 100%;
`;

export const AccordionItem = styled.div`
border: 1px solid ${({ theme }) => theme.colors.border || '#ccc'};
margin-bottom: ${({ theme }) => theme.spacing.xs || '5px'};
`;

export const AccordionTitle = styled.div`
background-color: ${({ theme }) => theme.colors.backgroundAlt || '#f1f1f1'};
padding: ${({ theme }) => theme.spacing.sm || '10px'};
cursor: pointer;
`;

export const AccordionContent = styled.div`
padding: ${({ theme }) => theme.spacing.sm || '10px'};
display: none;
&.open {
display: block;
}
`;
36 changes: 36 additions & 0 deletions src/components/Accordion/Accordion.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { screen, fireEvent } from '@testing-library/react';
import { renderWithDeps } from '../../../jest.utils';
import { Accordion } from './Accordion';
import { axe } from 'jest-axe';

describe('<Accordion />', () => {
it('renders', () => {
renderWithDeps(<Accordion items={[{ title: 'Title', content: 'Content' }]} />);

const titleElement = screen.getByText('Title');

expect(titleElement).toBeInTheDocument();
});

it('toggles content on click', () => {
renderWithDeps(<Accordion items={[{ title: 'Title', content: 'Content' }]} />);

const titleElement = screen.getByText('Title');
fireEvent.click(titleElement);

const contentElement = screen.getByText('Content');
expect(contentElement).toBeVisible();

fireEvent.click(titleElement);
expect(contentElement).not.toBeVisible();
});

it('has no accessibility violations', async () => {
const { container } = renderWithDeps(<Accordion items={[{ title: 'Title', content: 'Content' }]} />);
const results = await axe(container);

expect(results).toHaveNoViolations();
});
});


34 changes: 34 additions & 0 deletions src/components/Accordion/Accordion.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { useState, ReactNode } from 'react';
import {
AccordionContainer,
AccordionItem,
AccordionTitle,
AccordionContent,
} from './Accordion.style';

type AccordionProps = {
items: { title: string; content: ReactNode }[]; // Change content to ReactNode
};

export const Accordion: React.FC<AccordionProps> = ({ items }) => {
const [openIndex, setOpenIndex] = useState<number | null>(null);

const handleToggle = (index: number) => {
setOpenIndex(index === openIndex ? null : index);
};

return (
<AccordionContainer>
{items.map((item, index) => (
<AccordionItem key={index}>
<AccordionTitle onClick={() => handleToggle(index)}>
{item.title}
</AccordionTitle>
<AccordionContent className={openIndex === index ? 'open' : ''}>
{item.content}
</AccordionContent>
</AccordionItem>
))}
</AccordionContainer>
);
};

0 comments on commit d9b5aee

Please sign in to comment.