Skip to content

Commit

Permalink
Merge pull request #66 from complexdatacollective/feature/node-panel-…
Browse files Browse the repository at this point in the history
…accordion

WIP implementation of panels using radix accordion for a11y
  • Loading branch information
jthrilly authored Oct 4, 2024
2 parents 08e41f3 + 014c19d commit 3f157a4
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function NameGenerator(_props: InterviewStage) {
<div className={cn(interfaceWrapperClasses, 'flex grow flex-col gap-4')}>
<Prompts prompts={demoPrompts} currentPromptId="1" />
<div className="relative flex h-full min-h-0 flex-1 items-start justify-center gap-4">
<NodePanels panels={demoPanels} />
<NodePanels panels={demoPanels} id="data-wizard-task-step-2" />
<div className="flex-basis-auto flex h-full flex-shrink flex-grow">
<NodeList items={demoNodes} />
</div>
Expand Down
52 changes: 44 additions & 8 deletions components/interview/interfaces/name-generator/NodePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,52 @@
import Panel from './Panel';
import NodeList, { type Node } from '../../NodeList';
import * as Accordion from '@radix-ui/react-accordion';
import { motion } from 'framer-motion';
import { MotionSurface } from '~/components/layout/Surface';
import Heading from '~/components/typography/Heading';
import { cn } from '~/lib/utils';

export default function NodePanel({
nodes,
// incompatibility between framer-motion 12.x and new react types
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const MotionTrigger = motion(Accordion.Trigger);

export default function Panel({
id,
title,
expanded,
children,
noHighlight,
}: {
nodes: Node[];
id: string;
title: string;
expanded: boolean;
children: React.ReactNode;
noHighlight?: boolean;
}) {
const panelClasses = cn(
'flex flex-1 flex-col rounded-small border-b border-b-4 border-panel-1 shadow-xl',
{
'border-b-0': noHighlight,
},
);

const contentClasses = cn(
'h-auto flex-grow border-t border-background flex flex-col overflow-hidden items-center',
);

return (
<Panel title={title}>
<NodeList items={nodes} nodeSize="sm" />
</Panel>
<Accordion.Item value={id} asChild>
<MotionSurface layout level={1} spacing="none" className={panelClasses}>
<MotionTrigger
layout
className="flex cursor-pointer items-center justify-center p-4"
>
<Heading variant="h3" className="mb-0">
{title}
</Heading>
</MotionTrigger>
<Accordion.Content className={contentClasses}>
{expanded ? children : null}
</Accordion.Content>
</MotionSurface>
</Accordion.Item>
);
}
49 changes: 34 additions & 15 deletions components/interview/interfaces/name-generator/NodePanels.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,46 @@
'use client';

import type { Node } from '~/components/interview/NodeList';
import * as Accordion from '@radix-ui/react-accordion';
import { useState } from 'react';
import NodeList from '~/components/interview/NodeList';
import NodePanel from './NodePanel';
import { forwardRef, type ForwardedRef } from 'react';
import { useTranslations } from 'next-intl';

// TODO: Remove once connected to state
type Panel = {
id: string;
title: string;
nodes: Node[];
};

export default forwardRef(function NodePanels(
{ panels }: { panels: Panel[] },
ref: ForwardedRef<HTMLDivElement>,
) {
const t = useTranslations(`Protocol.Panels`);
type NodePanels = {
panels: Panel[];
} & React.ComponentProps<'div'>;

export default function NodePanels({ panels, ...rest }: NodePanels) {
const [values, setValues] = useState<string[]>(
panels.map((panel) => panel.id),
);

return (
<div id="data-wizard-task-step-2" ref={ref} className="flex flex-col gap-4">
{panels.map((panel) => {
return (
<NodePanel key={panel.id} {...panel} title={t(`${panel.id}.Title`)} />
);
})}
</div>
<Accordion.Root
value={values}
onValueChange={setValues}
asChild
type="multiple"
>
<div className="flex flex-col gap-4" {...rest}>
{panels.map((panel) => (
<NodePanel
key={panel.id}
id={panel.id}
title={panel.title}
expanded={values.includes(panel.id)}
>
<NodeList items={panel.nodes} nodeSize="sm" />
</NodePanel>
))}
</div>
</Accordion.Root>
);
});
}
55 changes: 0 additions & 55 deletions components/interview/interfaces/name-generator/Panel.tsx

This file was deleted.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@formatjs/intl-localematcher": "^0.5.4",
"@lucia-auth/adapter-prisma": "^4.0.1",
"@node-rs/argon2": "^1.8.3",
"@radix-ui/react-accordion": "^1.2.1",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-direction": "^1.1.0",
"@radix-ui/react-label": "^2.1.0",
Expand Down
106 changes: 103 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3f157a4

Please sign in to comment.