@@ -15,7 +15,7 @@ const meta: Meta
= {
export default meta;
-type Story = StoryObj;
+type Story = StoryObj;
export const Active: Story = {
args: {
diff --git a/src/entities/Section/ui/SectionAccordion/SectionAccordion.test.tsx b/src/entities/Section/ui/SectionPanel/SectionPanel.test.tsx
similarity index 73%
rename from src/entities/Section/ui/SectionAccordion/SectionAccordion.test.tsx
rename to src/entities/Section/ui/SectionPanel/SectionPanel.test.tsx
index 6c5d182..2de2a63 100644
--- a/src/entities/Section/ui/SectionAccordion/SectionAccordion.test.tsx
+++ b/src/entities/Section/ui/SectionPanel/SectionPanel.test.tsx
@@ -1,5 +1,5 @@
import { render, screen } from '@testing-library/react';
-import { SectionAccordion } from './SectionAccordion';
+import { SectionPanel } from './SectionPanel';
const defaultProps = {
number: '01',
@@ -10,30 +10,30 @@ const defaultProps = {
children: Content here
,
};
-describe('SectionAccordion', () => {
+describe('SectionPanel', () => {
describe('collapsed state (isActive=false)', () => {
it('renders a section element with the given id', () => {
- const { container } = render();
+ const { container } = render();
expect(container.querySelector('section#about')).toBeInTheDocument();
});
it('renders a link with number and title', () => {
- render();
+ render();
expect(screen.getByRole('link', { name: /01.*About/i })).toBeInTheDocument();
});
it('link points to the correct href', () => {
- render();
+ render();
expect(screen.getByRole('link', { name: /01.*About/i })).toHaveAttribute('href', '/about');
});
it('does not render children', () => {
- render();
+ render();
expect(screen.queryByText('Content here')).not.toBeInTheDocument();
});
it('does not render a button', () => {
- render();
+ render();
expect(screen.queryByRole('button')).not.toBeInTheDocument();
});
});
@@ -42,17 +42,17 @@ describe('SectionAccordion', () => {
const activeProps = { ...defaultProps, isActive: true };
it('renders an h1 with number and title', () => {
- render();
+ render();
expect(screen.getByRole('heading', { level: 1, name: /01.*About/i })).toBeInTheDocument();
});
it('renders children', () => {
- render();
+ render();
expect(screen.getByText('Content here')).toBeInTheDocument();
});
it('does not render a link', () => {
- render();
+ render();
expect(screen.queryByRole('link')).not.toBeInTheDocument();
});
});
diff --git a/src/entities/Section/ui/SectionAccordion/SectionAccordion.tsx b/src/entities/Section/ui/SectionPanel/SectionPanel.tsx
similarity index 92%
rename from src/entities/Section/ui/SectionAccordion/SectionAccordion.tsx
rename to src/entities/Section/ui/SectionPanel/SectionPanel.tsx
index d02d582..31c6495 100644
--- a/src/entities/Section/ui/SectionAccordion/SectionAccordion.tsx
+++ b/src/entities/Section/ui/SectionPanel/SectionPanel.tsx
@@ -2,7 +2,7 @@ import Link from 'next/link';
import type { ReactNode } from 'react';
import { ViewTransitionWrapper } from '$shared/ui';
-interface SectionAccordionProps {
+interface SectionPanelProps {
/**
* Display number prefix (e.g. "01")
*/
@@ -32,7 +32,7 @@ interface SectionAccordionProps {
/**
* Accordion-style section that collapses to a navigation link when inactive.
*/
-export function SectionAccordion({ number, title, id, isActive, href, children }: SectionAccordionProps) {
+export function SectionPanel({ number, title, id, isActive, href, children }: SectionPanelProps) {
const heading = `${number}. ${title}`;
return (
diff --git a/src/entities/Section/ui/SectionPanel/index.ts b/src/entities/Section/ui/SectionPanel/index.ts
new file mode 100644
index 0000000..6281730
--- /dev/null
+++ b/src/entities/Section/ui/SectionPanel/index.ts
@@ -0,0 +1 @@
+export * from './SectionPanel';
diff --git a/src/entities/Section/ui/index.ts b/src/entities/Section/ui/index.ts
index 25000d2..6281730 100644
--- a/src/entities/Section/ui/index.ts
+++ b/src/entities/Section/ui/index.ts
@@ -1 +1 @@
-export * from './SectionAccordion';
+export * from './SectionPanel';
diff --git a/src/widgets/SectionAccordion/index.ts b/src/widgets/SectionAccordion/index.ts
new file mode 100644
index 0000000..e999d50
--- /dev/null
+++ b/src/widgets/SectionAccordion/index.ts
@@ -0,0 +1 @@
+export { SectionAccordion } from './ui/SectionAccordion/SectionAccordion';
diff --git a/src/widgets/SectionsAccordion/ui/SectionsAccordion/SectionsAccordion.test.tsx b/src/widgets/SectionAccordion/ui/SectionAccordion/SectionAccordion.test.tsx
similarity index 77%
rename from src/widgets/SectionsAccordion/ui/SectionsAccordion/SectionsAccordion.test.tsx
rename to src/widgets/SectionAccordion/ui/SectionAccordion/SectionAccordion.test.tsx
index 918c46b..0a52144 100644
--- a/src/widgets/SectionsAccordion/ui/SectionsAccordion/SectionsAccordion.test.tsx
+++ b/src/widgets/SectionAccordion/ui/SectionAccordion/SectionAccordion.test.tsx
@@ -1,6 +1,6 @@
import { render, screen } from '@testing-library/react';
import type { SectionRecord } from '$entities/Section';
-import { SectionsAccordion } from './SectionsAccordion';
+import { SectionAccordion } from './SectionAccordion';
const baseRecord = { collectionId: 'c1', collectionName: 'sections', created: '', updated: '' };
@@ -10,26 +10,26 @@ const sections: SectionRecord[] = [
{ ...baseRecord, id: '3', slug: 'skills', title: 'Skills', order: 3 },
];
-describe('SectionsAccordion', () => {
+describe('SectionAccordion', () => {
describe('active section rendering', () => {
it('renders the active section as an h1', () => {
render(
-
+
Intro content
Bio content
Skills content
- ,
+ ,
);
expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent('01. Intro');
});
it('renders inactive sections as links', () => {
render(
-
+
Intro content
Bio content
Skills content
- ,
+ ,
);
const links = screen.getAllByRole('link');
expect(links).toHaveLength(2);
@@ -37,11 +37,11 @@ describe('SectionsAccordion', () => {
it('inactive section links point to correct hrefs', () => {
render(
-
+
Intro content
Bio content
Skills content
- ,
+ ,
);
expect(screen.getByRole('link', { name: /02.*Bio/i })).toHaveAttribute('href', '/bio');
expect(screen.getByRole('link', { name: /03.*Skills/i })).toHaveAttribute('href', '/skills');
@@ -49,22 +49,22 @@ describe('SectionsAccordion', () => {
it('renders the correct active section for a given activeSlug', () => {
render(
-
+
Intro content
Bio content
Skills content
- ,
+ ,
);
expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent('02. Bio');
});
it('only one section is active at a time', () => {
render(
-
+
Intro content
Bio content
Skills content
- ,
+ ,
);
expect(screen.getAllByRole('heading', { level: 1 })).toHaveLength(1);
});
@@ -73,22 +73,22 @@ describe('SectionsAccordion', () => {
describe('content slots', () => {
it('shows active section content', () => {
render(
-
+
Intro content
Bio content
Skills content
- ,
+ ,
);
expect(screen.getByText('Intro content')).toBeInTheDocument();
});
it('does not show inactive section content', () => {
render(
-
+
Intro content
Bio content
Skills content
- ,
+ ,
);
expect(screen.queryByText('Bio content')).not.toBeInTheDocument();
expect(screen.queryByText('Skills content')).not.toBeInTheDocument();
diff --git a/src/widgets/SectionsAccordion/ui/SectionsAccordion/SectionsAccordion.tsx b/src/widgets/SectionAccordion/ui/SectionAccordion/SectionAccordion.tsx
similarity index 85%
rename from src/widgets/SectionsAccordion/ui/SectionsAccordion/SectionsAccordion.tsx
rename to src/widgets/SectionAccordion/ui/SectionAccordion/SectionAccordion.tsx
index 73cffcd..56df0eb 100644
--- a/src/widgets/SectionsAccordion/ui/SectionsAccordion/SectionsAccordion.tsx
+++ b/src/widgets/SectionAccordion/ui/SectionAccordion/SectionAccordion.tsx
@@ -1,7 +1,7 @@
import type { ReactNode } from 'react';
import { Children } from 'react';
import type { SectionRecord } from '$entities/Section';
-import { SectionAccordion } from '$entities/Section';
+import { SectionPanel } from '$entities/Section';
export interface Props {
/**
@@ -24,13 +24,13 @@ export interface Props {
* Active section is determined by the URL (activeSlug prop); inactive sections
* render as navigation links so the browser handles routing.
*/
-export function SectionsAccordion({ sections, activeSlug, children }: Props) {
+export function SectionAccordion({ sections, activeSlug, children }: Props) {
const slots = Children.toArray(children);
return (
{sections.map((section, i) => (
-
{slots[i]}
-
+
))}
);
diff --git a/src/widgets/SectionsAccordion/index.ts b/src/widgets/SectionsAccordion/index.ts
deleted file mode 100644
index 4a468c4..0000000
--- a/src/widgets/SectionsAccordion/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { SectionsAccordion } from './ui/SectionsAccordion/SectionsAccordion';