Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add dropdown for topics in Explore (#877)
Fixes #533
- Loading branch information
Showing
10 changed files
with
192 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import Radio from "components/atoms/Radio/radio"; | ||
import humanizeNumber from "lib/utils/humanizeNumber"; | ||
|
||
interface SelectorProps { | ||
filterOptions: string[]; | ||
handleFilterClick: (filter: string) => void; | ||
selected?: string; | ||
} | ||
|
||
const Selector = ({ | ||
filterOptions, | ||
handleFilterClick, | ||
selected | ||
}: SelectorProps) => { | ||
return ( | ||
<div className="mt-2 absolute transform md:translate-x-0 space-y-1 mt-1 shadow-superlative z-10 w-72 bg-white rounded-lg px-1.5 py-2"> | ||
{filterOptions.length > 0 && | ||
filterOptions.map((option, index) => { | ||
return ( | ||
<Radio | ||
key={index} | ||
onClick={() => { | ||
handleFilterClick(option); | ||
}} | ||
css="!w-full" | ||
checked={selected === option ? true : false} | ||
> | ||
{option} | ||
</Radio> | ||
); | ||
})} | ||
</div> | ||
); | ||
}; | ||
|
||
export default Selector; |
86 changes: 86 additions & 0 deletions
86
components/molecules/FilterCardSelect/filter-card-select.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import React, { useEffect, useRef, useState } from "react"; | ||
import Image from "next/image"; | ||
import Text from "../../atoms/Typography/text"; | ||
import hashIcon from "../../../img/icons/hash.svg"; | ||
import orgIcon from "../../../img/icons/org.svg"; | ||
import personIcon from "../../../img/icons/person.svg"; | ||
import repoIcon from "../../../img/icons/repo.svg"; | ||
import Selector from "../../atoms/Selector/selector"; | ||
|
||
interface FilterCardSelectProps { | ||
selected: string; | ||
icon?: "topic" | "repo" | "org" | "contributor"; | ||
options: string[]; | ||
handleFilterClick: (filter: string) => void; | ||
} | ||
|
||
const icons = { | ||
topic: { | ||
src: hashIcon.src, | ||
alt: "Topic" | ||
}, | ||
org: { | ||
src: orgIcon.src, | ||
alt: "Organization" | ||
}, | ||
contributor: { | ||
src: personIcon.src, | ||
alt: "Contributor" | ||
}, | ||
repo: { | ||
src: repoIcon.src, | ||
alt: "Repository" | ||
} | ||
}; | ||
|
||
const FilterCardSelect: React.FC<FilterCardSelectProps> = ({ selected: filterName, icon = "topic", options, handleFilterClick }) => { | ||
|
||
const ref = useRef<HTMLDivElement>(null); | ||
const [isOpen, setIsOpen] = useState(false); | ||
const toggleFilter = () => { | ||
setIsOpen(!isOpen); | ||
}; | ||
|
||
useEffect(() => { | ||
const checkIfClickedOutside = (e: MouseEvent) => { | ||
// If the menu is open and the clicked target is not within the menu, | ||
// then close the menu | ||
if (isOpen && ref.current && !ref.current.contains(e.target as Node)) { | ||
setIsOpen(false); | ||
} | ||
}; | ||
document.addEventListener("mousedown", checkIfClickedOutside); | ||
|
||
return () => { | ||
// Cleanup the event listener | ||
document.removeEventListener("mousedown", checkIfClickedOutside); | ||
}; | ||
}, [isOpen]); | ||
|
||
return ( | ||
<> | ||
<div | ||
onClick={toggleFilter} | ||
ref={ref} | ||
className={"inline-block py-1 border border-slate-300 outline-none hover:bg-slate-50 focus:ring-2 bg-slate-100 focus:ring-slate-300 rounded-lg cursor-pointer"}> | ||
<button className="flex items-center gap-1 mx-2"> | ||
<Image | ||
width={14} height={14} | ||
alt={icon === "topic" ? icons.topic.alt : icon === "org" ? icons.org.alt : icon === "contributor" ? icons.contributor.alt : icon === "repo" ? icons.repo.alt : "Icon"} | ||
src={icon === "topic" ? icons.topic.src : icon === "org" ? icons.org.src : icon === "contributor" ? icons.contributor.src : icon === "repo" ? icons.repo.src : icons.topic.src} /> | ||
<Text className="!text-sm font-semibold tracking-tight !text-slate-900"> | ||
{filterName} | ||
</Text> | ||
</button> | ||
{ isOpen && <Selector | ||
filterOptions={options} | ||
handleFilterClick={handleFilterClick} | ||
selected={filterName} | ||
/> | ||
} | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
export default FilterCardSelect; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
const getTopicOptions = () => { | ||
const topics = ["javascript", "rust", "python", "ml", "ai", "react"]; | ||
|
||
return topics; | ||
}; | ||
|
||
export default getTopicOptions; |
6 changes: 4 additions & 2 deletions
6
lib/utils/check-camelcase-naming.ts → lib/utils/topic-name-formatting.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,13 @@ | ||
import uppercaseFirst from "./uppercase-first"; | ||
|
||
/** Checks the input and if it should be camelcased, it will camelcase it. Uppercases the output. */ | ||
const checkCamelCaseNaming = (name: string) => { | ||
const topicNameFormatting = (name: string) => { | ||
if (!name) return ""; | ||
|
||
if(name.toLowerCase() == "javascript") return "JavaScript"; | ||
if(name.toLowerCase() == "ai") return "AI"; | ||
if(name.toLowerCase() == "ml") return "Machine Learning"; | ||
else return uppercaseFirst(name); | ||
}; | ||
|
||
export default checkCamelCaseNaming; | ||
export default topicNameFormatting; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import React from "react"; | ||
import { ComponentStory } from "@storybook/react"; | ||
import Selector from "components/atoms/Selector/selector"; | ||
|
||
const storyConfig = { | ||
title: "Design System/Atoms/Selector", | ||
component: "Select" | ||
}; | ||
|
||
export default storyConfig; | ||
|
||
//Select Template | ||
const SelectTemplate: ComponentStory<typeof Selector> = (args) => <Selector {...args} />; | ||
|
||
export const Default = SelectTemplate.bind({}); | ||
|
||
Default.args = { | ||
filterOptions: ["option1", "option2", "option3"], | ||
selected: "option1" | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import React from "react"; | ||
import { ComponentStory } from "@storybook/react"; | ||
import Selector from "components/atoms/Selector/selector"; | ||
import FilterCardSelect from "components/molecules/FilterCardSelect/filter-card-select"; | ||
|
||
const storyConfig = { | ||
title: "Design System/Molecules/FilterCardSelect", | ||
component: "FilterCardSelect" | ||
}; | ||
|
||
export default storyConfig; | ||
|
||
//Select Template | ||
const SelectTemplate: ComponentStory<typeof FilterCardSelect> = (args) => <FilterCardSelect {...args} />; | ||
|
||
export const Default = SelectTemplate.bind({}); | ||
|
||
Default.args = { | ||
options: ["option1", "option2", "option3"], | ||
selected: "option1" | ||
}; |
6 changes: 3 additions & 3 deletions
6
.../lib/utils/check-camelcase-naming.test.ts → ...s/lib/utils/topic-name-formatting.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,15 @@ | ||
import checkCamelCaseNaming from "lib/utils/check-camelcase-naming"; | ||
import topicNameFormatting from "lib/utils/topic-name-formatting"; | ||
|
||
describe("[lib] checkCamelCaseNaming()", () => { | ||
it("should make javascript camelCase and uppercase first letter", () => { | ||
const testString = "javascript"; | ||
const result = checkCamelCaseNaming(testString); | ||
const result = topicNameFormatting(testString); | ||
expect(result).toBe("JavaScript"); | ||
}); | ||
|
||
it("should uppercase python without camelCase", () => { | ||
const testString = "python"; | ||
const result = checkCamelCaseNaming(testString); | ||
const result = topicNameFormatting(testString); | ||
expect(result).toBe("Python"); | ||
}); | ||
}); |