Skip to content

Commit 7201b5b

Browse files
aarabiinehagup
andauthored
feat: added the card layout to glossary page (#543)
Co-authored-by: Neha Gupta <[email protected]>
1 parent e99249a commit 7201b5b

File tree

4 files changed

+295
-191
lines changed

4 files changed

+295
-191
lines changed

src/components/GlossaryCard.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from "react";
2+
import ArrowUpRight from "../../static/img/ArrowUpRight.svg";
3+
4+
const GlossaryCard = ({name, description, link}) => {
5+
return (
6+
<a
7+
href={link}
8+
className="group flex h-full flex-col rounded-xl border border-transparent bg-[var(--ifm-card-background-color)] p-6 shadow-[0_4px_12px_var(--ifm-card-shadow-color)] transition-all duration-300 hover:border-[var(--ifm-color-primary)] hover:shadow-[0_8px_20px_var(--ifm-card-shadow-color)] focus:outline-none focus:ring-2 focus:ring-[var(--ifm-color-primary)] focus:ring-offset-2
9+
"
10+
>
11+
<div className="mb-3 flex items-start justify-between">
12+
<h3 className="pr-4 text-xl font-bold text-[var(--ifm-color-primary)]">
13+
{name}
14+
</h3>
15+
<ArrowUpRight
16+
className=" flex-shrink-0 text-[var(--ifm-color-emphasis-500)] transition-all duration-300 ease-in-out group-hover:rotate-45 group-hover:text-[var(--ifm-color-primary)]"
17+
size={22}
18+
/>
19+
</div>
20+
<p className="text-sm leading-relaxed text-[var(--ifm-color-emphasis-700)]">
21+
{description}
22+
</p>
23+
</a>
24+
);
25+
};
26+
27+
export default GlossaryCard;

src/pages/concepts/reference/glossary.js

Lines changed: 114 additions & 191 deletions
Original file line numberDiff line numberDiff line change
@@ -1,208 +1,131 @@
1-
import React, {useState} from "react";
1+
import React, {useState, useMemo} from "react";
22
import Layout from "@theme/Layout";
3-
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
3+
4+
import {glossaryEntries} from "../../../../static/data/glossaryEntries";
5+
import GlossaryCard from "../../../components/GlossaryCard";
46

57
function Glossary() {
6-
const [state, setState] = useState(() => {
7-
const alphabet = "ABCEFGIMRSTUW";
8-
const initialState = {};
9-
for (let i = 0; i < alphabet.length; i++) {
10-
initialState[alphabet[i]] = true;
11-
}
12-
return initialState;
13-
});
14-
const entries = {
15-
A: [
16-
{
17-
name: "Acceptance Testing",
18-
link: "/docs/concepts/reference/glossary/acceptance-testing",
19-
},
20-
{
21-
name: "Agile Unit Testing",
22-
link: "/docs/concepts/reference/glossary/agile-unit-testing",
23-
},
24-
{
25-
name: "AI Test Completion",
26-
link: "/docs/concepts/reference/glossary/ai-test-completion",
27-
},
28-
],
29-
B: [
30-
{
31-
name: "BDD",
32-
link: "/docs/concepts/reference/glossary/behaviour-driven-development",
33-
},
34-
{
35-
name: "Beta Testing",
36-
link: "/docs/concepts/reference/glossary/beta-testing",
37-
},
38-
{
39-
name: "Black Box Testing",
40-
link: "/docs/concepts/reference/glossary/black-box-testing",
41-
},
42-
],
43-
C: [
44-
{
45-
name: "Code Coverage",
46-
link: "/docs/concepts/reference/glossary/code-coverage",
47-
},
48-
{
49-
name: "Cucumber Testing",
50-
link: "/docs/concepts/reference/glossary/cucumber-testing",
51-
},
52-
],
53-
E: [
54-
{
55-
name: "End To End Testing",
56-
link: "/docs/concepts/reference/glossary/end-to-end-testing",
57-
},
58-
{
59-
name: "Error Guessing",
60-
link: "/docs/concepts/reference/glossary/error-guessing",
61-
},
62-
],
63-
F: [
64-
{
65-
name: "Functional Testing",
66-
link: "/docs/concepts/reference/glossary/functional-testing",
67-
},
68-
],
69-
G: [
70-
{
71-
name: "Gray Box Testing",
72-
link: "/docs/concepts/reference/glossary/gray-box-testing",
73-
},
74-
],
75-
I: [
76-
{
77-
name: "Integration Testing",
78-
link: "/docs/concepts/reference/glossary/integration-testing",
79-
},
80-
{
81-
name: "Idempotency",
82-
link: "/docs/concepts/reference/glossary/idempotency",
83-
},
84-
],
85-
M: [
86-
{
87-
name: "Manual Testing",
88-
link: "/docs/concepts/reference/glossary/manual-testing",
89-
},
90-
{
91-
name: "Mocks",
92-
link: "/docs/concepts/reference/glossary/mocks",
93-
},
94-
{
95-
name: "Microservice Testing",
96-
link: "/docs/concepts/reference/glossary/microservice-testing",
97-
},
98-
],
99-
R: [
100-
{
101-
name: "Regression Testing",
102-
link: "/docs/concepts/reference/glossary/regression-testing",
103-
},
104-
],
105-
S: [
106-
{
107-
name: "Stubs",
108-
ink: "/docs/concepts/reference/glossary/stubs",
109-
},
110-
{
111-
name: "Software Testing Life Cycle",
112-
link: "/docs/concepts/reference/glossary/software-testing-life-cycle",
113-
},
114-
],
115-
T: [
116-
{
117-
name: "Test Driven TDD",
118-
link: "/docs/concepts/reference/glossary/test-driven-development",
119-
},
120-
{
121-
name: "Test Data Generation",
122-
link: "/docs/concepts/reference/glossary/test-data-generation",
123-
},
124-
],
125-
U: [
126-
{
127-
name: "Unit Test Automation",
128-
link: "/docs/concepts/reference/glossary/unit-test-automation",
129-
},
130-
{
131-
name: "Unit Testing",
132-
link: "/docs/concepts/reference/glossary/unit-testing",
133-
},
134-
],
135-
W: [
136-
{
137-
name: "White Box Testing",
138-
link: "/docs/concepts/reference/glossary/white-box-testing",
139-
},
140-
],
8+
const [selectedletter, setselectedletter] = useState([]);
9+
10+
const allLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
11+
const availableLetters = Object.keys(glossaryEntries);
12+
13+
const handleLetterClick = (letter) => {
14+
setselectedletter((prev) =>
15+
prev.includes(letter)
16+
? prev.filter((l) => l !== letter)
17+
: [...prev, letter]
18+
);
14119
};
142-
const {siteConfig, siteMetadata} = useDocusaurusContext;
143-
const handleClick = (index) => {
144-
setState((state) => {
145-
var obj = {
146-
...state,
147-
[index]: !state[index],
148-
};
149-
return obj;
150-
});
20+
21+
// Reset filter
22+
const handleResetFilter = () => {
23+
setselectedletter([]);
15124
};
25+
26+
// Memoize the filtered entries to avoid re calculating on every render
27+
const filteredEntrie = useMemo(() => {
28+
if (selectedletter.length === 0) {
29+
return Object.values(glossaryEntries).flat();
30+
}
31+
return selectedletter
32+
.map((letter) => glossaryEntries[letter] || [])
33+
.flat()
34+
.sort((a, b) => a.name.localeCompare(b.name));
35+
}, [selectedletter]);
36+
15237
return (
15338
<Layout
154-
title="About the docs"
39+
title="Glossary"
15540
permalink="/reference/glossary"
156-
description="User General Information about Keploy's Documentation"
41+
description="A glossary of terms related to software testing and development."
15742
>
158-
<main className="margin-vert--lg container flex flex-col justify-evenly">
159-
<div className="pb-5 text-center text-4xl font-bold">Glossary</div>
160-
<div className="flex flex-row justify-evenly">
161-
{new Array(26).fill(0).map((x, i) => (
43+
<main className="container mx-auto my-12 px-4 sm:px-6 lg:px-8">
44+
<div className="mb-12 text-center">
45+
<h1 className="text-4xl font-extrabold tracking-tight sm:text-5xl">
46+
Glossary
47+
</h1>
48+
<p className="mt-4 text-lg text-[var(--ifm-color-emphasis-700)]">
49+
Your guide to modern software testing and development terminology.
50+
</p>
51+
</div>
52+
53+
<div
54+
className="mb-8 flex flex-wrap justify-center gap-2"
55+
role="navigation"
56+
aria-label="Alphabetical Glossary Navigation"
57+
>
58+
{allLetters.map((letter) => {
59+
const isAvailable = availableLetters.includes(letter);
60+
const isSelected = selectedletter.includes(letter);
61+
62+
return (
63+
<button
64+
key={letter}
65+
onClick={() => handleLetterClick(letter)}
66+
disabled={!isAvailable}
67+
className={`flex h-10 w-10 items-center justify-center rounded-full text-lg font-bold transition-all duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-[var(--ifm-color-primary)] focus:ring-offset-2 sm:h-12 sm:w-12
68+
${
69+
isAvailable
70+
? isSelected
71+
? "scale-110 bg-[var(--ifm-color-primary)] text-white shadow-lg"
72+
: "bg-[var(--ifm-card-background-color)] text-[var(--ifm-color-primary)] shadow-md hover:bg-[var(--ifm-color-primary-lightest)] hover:text-[var(--ifm-color-primary-darker)]"
73+
: "cursor-not-allowed bg-transparent text-[var(--ifm-color-emphasis-300)]"
74+
}
75+
`}
76+
aria-pressed={isSelected}
77+
>
78+
{letter}
79+
</button>
80+
);
81+
})}
82+
</div>
83+
84+
{selectedletter.length > 0 && (
85+
<div className="mb-10 text-center">
16286
<button
163-
className={`col-span-1 gap-2 rounded-sm p-3
164-
${
165-
state[String.fromCharCode(65 + i)]
166-
? "text-black-200 rounded-3xl bg-orange-200 font-bold shadow-md hover:text-orange-950 dark:text-orange-900"
167-
: entries[String.fromCharCode(65 + i)] === undefined
168-
? "bg-transparent text-gray-400" // Modified color class
169-
: "bg-grey-200 rounded-3xl shadow-md"
170-
} `}
171-
key={i}
172-
disabled={
173-
entries[String.fromCharCode(65 + i)] === undefined
174-
? true
175-
: false
176-
}
177-
onClick={() => handleClick(String.fromCharCode(65 + i))}
87+
onClick={handleResetFilter}
88+
className="rounded-full border-2 border-[var(--ifm-color-primary)] bg-transparent px-6 py-2 font-semibold text-[var(--ifm-color-primary)] transition-colors hover:bg-[var(--ifm-color-primary)] hover:text-white"
17889
>
179-
{String.fromCharCode(65 + i)}
90+
Reset Filter
18091
</button>
181-
))}
182-
</div>
183-
<div className="-mb-3 mt-10 flex flex-wrap justify-center gap-4 text-xl font-semibold">
184-
{Object.entries(state).map(([key, value]) => {
185-
return (
186-
<div key={key} className="mb-4 w-1/4">
187-
<div key={key}>{value ? key : ""}</div>
188-
{value ? (
189-
<div className="ml-4 flex flex-col justify-around text-xl">
190-
{entries[key]?.map(({name, link}, i) => (
191-
<a
192-
className="text-orange-600 hover:text-orange-800 hover:underline"
193-
key={i}
194-
href={link}
195-
>
196-
{name}
197-
</a>
92+
</div>
93+
)}
94+
95+
<div className="mt-12">
96+
{selectedletter.length > 0 ? (
97+
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
98+
{filteredEntrie.map((entry, index) => (
99+
<GlossaryCard key={`${entry.name}-${index}`} {...entry} />
100+
))}
101+
</div>
102+
) : (
103+
<div className="space-y-16">
104+
{Object.entries(glossaryEntries).map(([letter, entries]) => (
105+
<section key={letter} id={`letter-${letter}`}>
106+
<h2 className="mb-6 border-b-2 border-[var(--ifm-color-emphasis-300)] pb-3 text-4xl font-bold text-[var(--ifm-color-primary)]">
107+
{letter}
108+
</h2>
109+
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
110+
{entries.map((entry, index) => (
111+
<GlossaryCard key={`${entry.name}-${index}`} {...entry} />
198112
))}
199113
</div>
200-
) : (
201-
""
202-
)}
203-
</div>
204-
);
205-
})}
114+
</section>
115+
))}
116+
</div>
117+
)}
118+
119+
{filteredEntrie.length === 0 && selectedletter.length > 0 && (
120+
<div className="py-16 text-center">
121+
<p className="text-2xl font-semibold text-[var(--ifm-color-emphasis-800)]">
122+
No terms found.
123+
</p>
124+
<p className="mt-2 text-[var(--ifm-color-emphasis-600)]">
125+
Try selecting a different letter or resetting the filter.
126+
</p>
127+
</div>
128+
)}
206129
</div>
207130
</main>
208131
</Layout>

0 commit comments

Comments
 (0)