Skip to content

Commit 4d6117f

Browse files
committed
Implement new Accordion component and refactor related sections for improved functionality
- Introduce a new generic Accordion component in the Core directory to enhance reusability across different sections. - Remove outdated Accordion implementations from KubernetesParetoPrinciple and MikrotikNetworking components. - Update ProductionChecklistSection, TabContent, DeviceConfiguration, FirewallLogic, Scenarios, and Summary components to utilize the new Accordion, improving code consistency and maintainability. - Ensure Accordion supports dynamic titles and content rendering for better user experience.
1 parent 6288d1c commit 4d6117f

File tree

9 files changed

+165
-175
lines changed

9 files changed

+165
-175
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { useState } from "react";
2+
3+
interface AccordionProps<T> {
4+
items: T[];
5+
getTitle: (item: T, idx: number) => React.ReactNode;
6+
renderContent: (item: T, idx: number) => React.ReactNode;
7+
initialActiveIndex?: number | null;
8+
stepPrefix?: (idx: number) => React.ReactNode; // Optional, for Mikrotik style
9+
}
10+
11+
function Accordion<T>({
12+
items,
13+
getTitle,
14+
renderContent,
15+
initialActiveIndex = null,
16+
stepPrefix,
17+
}: AccordionProps<T>) {
18+
const [openIndex, setOpenIndex] = useState<number | null>(initialActiveIndex);
19+
20+
const handleToggle = (index: number) => {
21+
setOpenIndex(openIndex === index ? null : index);
22+
};
23+
24+
return (
25+
<div className="space-y-3">
26+
{items.map((item, idx) => (
27+
<div
28+
key={idx}
29+
className="border border-slate-200 dark:border-slate-700 rounded-md bg-white/5 dark:bg-black/20"
30+
>
31+
<button
32+
onClick={() => handleToggle(idx)}
33+
className="w-full flex justify-between items-center p-4 text-left hover:bg-slate-100/30 dark:hover:bg-gray-800/20 transition-colors"
34+
>
35+
<span className="flex items-center gap-2 font-medium text-slate-700 dark:text-slate-200">
36+
{stepPrefix ? stepPrefix(idx) : null}
37+
{getTitle(item, idx)}
38+
</span>
39+
<span
40+
className={`transform transition-transform text-amber-500 ${
41+
openIndex === idx ? "rotate-45" : ""
42+
}`}
43+
>
44+
+
45+
</span>
46+
</button>
47+
<div
48+
className={`overflow-hidden transition-all duration-300 ease-in-out ${
49+
openIndex === idx ? "max-h-screen" : "max-h-0"
50+
}`}
51+
>
52+
{openIndex === idx && (
53+
<div className="p-4 pt-0 text-slate-600 dark:text-slate-300">
54+
{renderContent(item, idx)}
55+
</div>
56+
)}
57+
</div>
58+
</div>
59+
))}
60+
</div>
61+
);
62+
}
63+
64+
export default Accordion;

docusaurus/src/components/KubernetesParetoPrinciple/Accordion/index.tsx

Lines changed: 0 additions & 46 deletions
This file was deleted.
Lines changed: 31 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,36 @@
1-
import { useState } from "react";
1+
import Accordion from "../../Core/Accordion";
22
import ContentRenderer from "../ContentRenderer";
33
import { contentData } from "../content";
44

5-
const ProductionChecklistSection = () => {
6-
const [activeId, setActiveId] = useState(1);
7-
8-
const toggle = id => {
9-
setActiveId(activeId === id ? null : id);
10-
};
11-
12-
return (
13-
<section id="production" className="mb-16 md:mb-24 scroll-mt-20">
14-
<div className="text-center mb-12">
15-
<h2 className="font-bold tracking-tight text-slate-900 dark:text-slate-100">
16-
Production-Readiness Crucible
17-
</h2>
18-
<p className="mt-4 text-slate-600 dark:text-slate-300">
19-
A functional cluster is not a production cluster. Use this checklist
20-
to systematically harden, monitor, and back up your system for
21-
mission-critical workloads.
22-
</p>
23-
</div>
24-
<div>
25-
{contentData.production.map(item => (
26-
<div
27-
key={item.id}
28-
className="rounded-lg shadow-lg border border-slate-200 dark:border-slate-700 mb-4"
29-
>
30-
<button
31-
onClick={() => toggle(item.id)}
32-
className="w-full flex justify-between items-center px-4 py-4 text-left"
33-
>
34-
<div className="flex items-center">
35-
<span className="mr-4 text-2xl">{item.icon}</span>
36-
<div>
37-
<span className="font-semibold text-slate-800 dark:text-slate-200">
38-
{item.title}
39-
</span>
40-
<p className="text-slate-500 dark:text-slate-400 !mb-0 text-left">
41-
{item.description}
42-
</p>
43-
</div>
44-
</div>
45-
<span className="text-amber-500 font-light text-2xl">
46-
{activeId === item.id ? "−" : "+"}
47-
</span>
48-
</button>
49-
{activeId === item.id && (
50-
<div className="p-4 sm:p-6 pt-0 text-slate-600 dark:text-slate-300">
51-
<ContentRenderer content={item.content} />
52-
</div>
53-
)}
54-
</div>
55-
))}
56-
</div>
57-
</section>
58-
);
59-
};
5+
const ProductionChecklistSection = () => (
6+
<section id="production" className="mb-16 md:mb-24 scroll-mt-20">
7+
<div className="text-center mb-12">
8+
<h2 className="font-bold tracking-tight text-slate-900 dark:text-slate-100">
9+
Production-Readiness Crucible
10+
</h2>
11+
<p className="mt-4 text-slate-600 dark:text-slate-300">
12+
A functional cluster is not a production cluster. Use this checklist to
13+
systematically harden, monitor, and back up your system for
14+
mission-critical workloads.
15+
</p>
16+
</div>
17+
<Accordion
18+
items={contentData.production}
19+
getTitle={item => (
20+
<span className="flex items-center">
21+
<span className="mr-4 text-2xl">{item.icon}</span>
22+
<span className="font-semibold text-slate-800 dark:text-slate-200">
23+
{item.title}
24+
</span>
25+
<span className="ml-2 text-slate-500 dark:text-slate-400 text-sm font-normal">
26+
{item.description}
27+
</span>
28+
</span>
29+
)}
30+
renderContent={item => <ContentRenderer content={item.content} />}
31+
initialActiveIndex={0}
32+
/>
33+
</section>
34+
);
6035

6136
export default ProductionChecklistSection;

docusaurus/src/components/KubernetesParetoPrinciple/TroubleshootingSection/TabContent.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import Accordion from "../Accordion";
1+
import Accordion from "../../Core/Accordion";
2+
import ContentRenderer from "../ContentRenderer";
23

34
const TabContent = ({
45
title,
@@ -7,14 +8,19 @@ const TabContent = ({
78
}: {
89
title: string;
910
description: string;
10-
items: { id: number; title: string; content: string }[];
11+
items: { id: number; title: string; content: any }[];
1112
}) => (
1213
<div>
1314
<h3 className="font-semibold text-slate-800 dark:text-slate-200 mb-2">
1415
{title}
1516
</h3>
1617
<p className="text-slate-600 dark:text-slate-300 mb-4">{description}</p>
17-
<Accordion items={items} initialActiveId={1} />
18+
<Accordion
19+
items={items}
20+
getTitle={item => item.title}
21+
renderContent={item => <ContentRenderer content={item.content} />}
22+
initialActiveIndex={0}
23+
/>
1824
</div>
1925
);
2026

docusaurus/src/components/MikrotikNetworking/Accordion/index.tsx

Lines changed: 0 additions & 59 deletions
This file was deleted.

docusaurus/src/components/MikrotikNetworking/DeviceConfiguration/index.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useState } from "react";
2-
import Accordion from "../Accordion";
2+
import Accordion from "../../Core/Accordion";
3+
import CodeBlock from "../CodeBlock";
34
import { deviceConfigData } from "../data";
45
import Section from "../Section";
56
import { cx } from "../utils";
@@ -29,7 +30,19 @@ const DeviceConfiguration = () => {
2930
))}
3031
</nav>
3132
</div>
32-
<Accordion items={activeDevice.steps} />
33+
<Accordion
34+
items={activeDevice.steps}
35+
getTitle={item => item.title}
36+
renderContent={item => (
37+
<>
38+
<p className="text-sm mb-4">{item.description}</p>
39+
<CodeBlock code={item.code} />
40+
</>
41+
)}
42+
stepPrefix={idx => (
43+
<span className="font-semibold text-white">Step {idx + 1}:</span>
44+
)}
45+
/>
3346
</Section>
3447
);
3548
};

docusaurus/src/components/MikrotikNetworking/FirewallLogic/index.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import Accordion from "../Accordion";
1+
import Accordion from "../../Core/Accordion";
2+
import CodeBlock from "../CodeBlock";
23
import { firewallConfigData } from "../data";
34
import Section from "../Section";
45

@@ -7,7 +8,19 @@ const FirewallLogic = () => (
78
title="Deny by Default"
89
description="This is where the security policies are enforced on the RB3011 Router. These scripts create a 'deny by default' posture, which significantly enhances security."
910
>
10-
<Accordion items={firewallConfigData.steps} />
11+
<Accordion
12+
items={firewallConfigData.steps}
13+
getTitle={item => item.title}
14+
renderContent={item => (
15+
<>
16+
<p className="text-sm mb-4">{item.description}</p>
17+
<CodeBlock code={item.code} />
18+
</>
19+
)}
20+
stepPrefix={idx => (
21+
<span className="font-semibold text-white">Step {idx + 1}:</span>
22+
)}
23+
/>
1124
</Section>
1225
);
1326

docusaurus/src/components/MikrotikNetworking/Scenarios/index.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import Accordion from "../Accordion";
1+
import Accordion from "../../Core/Accordion";
2+
import CodeBlock from "../CodeBlock";
23
import { scenariosConfigData } from "../data";
34
import Section from "../Section";
45

@@ -7,7 +8,19 @@ const Scenarios = () => (
78
title="Common Scenarios & Firewall Exceptions"
89
description="A 'deny by default' firewall is secure but not very useful without exceptions. Here's how to poke controlled holes in the firewall for common, real-world needs."
910
>
10-
<Accordion items={scenariosConfigData.steps} />
11+
<Accordion
12+
items={scenariosConfigData.steps}
13+
getTitle={item => item.title}
14+
renderContent={item => (
15+
<>
16+
<p className="text-sm mb-4">{item.description}</p>
17+
<CodeBlock code={item.code} />
18+
</>
19+
)}
20+
stepPrefix={idx => (
21+
<span className="font-semibold text-white">Step {idx + 1}:</span>
22+
)}
23+
/>
1124
</Section>
1225
);
1326

0 commit comments

Comments
 (0)