Skip to content
Closed
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
16 changes: 13 additions & 3 deletions __tests__/components/common/DateAccordion.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jest.mock('@fortawesome/react-fontawesome', () => ({
import DateAccordion from '../../../components/common/DateAccordion';

describe('DateAccordion', () => {
it('shows collapsed content when not expanded and triggers toggle', () => {
it('shows collapsed content when not expanded, exposes aria attributes, and triggers toggle', () => {
const toggle = jest.fn();
render(
<DateAccordion title="Title" isExpanded={false} onToggle={toggle} collapsedContent={<span>info</span>}>
Expand All @@ -24,17 +24,27 @@ describe('DateAccordion', () => {
);
expect(screen.getByText('info')).toBeInTheDocument();
expect(screen.queryByTestId('child')).not.toBeInTheDocument();
fireEvent.click(screen.getByText('Title'));
const button = screen.getByRole('button', { name: /Title/ });
expect(button).toHaveAttribute('aria-expanded', 'false');
expect(button).toHaveAttribute('aria-controls');
fireEvent.click(button);
expect(toggle).toHaveBeenCalled();
});

it('renders children when expanded', () => {
it('renders children when expanded and links aria-controls to the content region', () => {
render(
<DateAccordion title="Title" isExpanded={true} onToggle={() => {}} collapsedContent={<span>info</span>}>
<div data-testid="child" />
</DateAccordion>
);
const button = screen.getByRole('button', { name: /Title/ });
expect(button).toHaveAttribute('aria-expanded', 'true');
const controls = button.getAttribute('aria-controls');
expect(controls).toBeTruthy();
expect(screen.getByTestId('child')).toBeInTheDocument();
expect(screen.queryByText('info')).not.toBeInTheDocument();
const region = controls ? document.getElementById(controls) : null;
expect(region).toBeInTheDocument();
expect(region).toContainElement(screen.getByTestId('child'));
});
});
13 changes: 10 additions & 3 deletions components/common/DateAccordion.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useId } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronDown } from "@fortawesome/free-solid-svg-icons";
import { motion, AnimatePresence } from "framer-motion";
Expand All @@ -19,16 +20,21 @@ export default function DateAccordion({
children,
showChevron = true,
}: DateAccordionProps) {
const contentId = useId();

return (
<motion.div
className="tw-bg-iron-900 tw-rounded-xl tw-ring-1 tw-ring-iron-700/50 tw-shadow-sm"
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.4 }}
>
<div
<button
type="button"
onClick={onToggle}
className="tw-px-5 tw-h-16 tw-cursor-pointer tw-flex tw-items-center tw-justify-between tw-w-full desktop-hover:hover:tw-bg-iron-800/50 tw-transition-colors tw-duration-200"
aria-expanded={isExpanded}
aria-controls={contentId}
className="tw-w-full tw-px-5 tw-h-16 tw-flex tw-items-center tw-justify-between tw-rounded-xl tw-bg-transparent tw-border-0 tw-text-left tw-cursor-pointer desktop-hover:hover:tw-bg-iron-800/50 tw-transition-colors tw-duration-200 focus-visible:tw-outline-none focus-visible:tw-ring-2 focus-visible:tw-ring-primary-400"
>
<div className="tw-flex tw-items-center tw-justify-between tw-w-full">
<div className="tw-flex tw-items-center tw-gap-x-3">
Expand All @@ -52,7 +58,7 @@ export default function DateAccordion({
</div>
)}
</div>
</div>
</button>

<AnimatePresence>
{isExpanded && (
Expand All @@ -61,6 +67,7 @@ export default function DateAccordion({
animate={{ height: "auto", opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: [0.04, 0.62, 0.23, 0.98] }}
id={contentId}
>
{children}
</motion.div>
Expand Down