Skip to content

Commit

Permalink
Merge pull request #292 from blz-it/262-add-icons
Browse files Browse the repository at this point in the history
Improve Dropdowns
  • Loading branch information
Benjamin-Frost authored Oct 19, 2024
2 parents 73b75eb + 235a8ee commit 21d5f1b
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 41 deletions.
57 changes: 29 additions & 28 deletions src/components/dropdowns/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
Label,
Listbox,
ListboxButton,
ListboxOption,
Expand All @@ -10,35 +9,37 @@ import { CheckIcon } from "@heroicons/react/20/solid/index";
import { clsx } from "clsx";
import { Fragment } from "react";

interface Props {
item: string;
options: readonly string[];
onChange: (option: string) => void;
label?: string;
icon: JSX.Element;
type Item<T> = { label: string; value: T };

interface Props<T> {
item: Item<T>;
options: Item<T>[];
onChange: (option: T) => void;
leftIcon?: JSX.Element;
rightIcon?: JSX.Element;
}

export const Dropdown = ({ item, options, icon, onChange, label }: Props) => {
export function Dropdown<T>({
item,
options,
onChange,
leftIcon,
rightIcon,
}: Props<T>) {
return (
<Listbox
value={item}
onChange={(option) => option !== item && onChange(option)}
onChange={(option) =>
option.value !== item.value && onChange(option.value)
}
>
{({ open }) => (
<div className="min-w-[6rem]">
{label && (
<Label className="mb-1 block text-sm font-medium text-gray-700">
{label}
</Label>
)}
<div className="relative">
<ListboxButton className="peer relative w-full cursor-default rounded-md py-2 pl-3 pr-10 text-left text-white hover:bg-wsg-orange-400 hover:bg-opacity-50 focus:ring-1 focus:ring-wsi-blue-300 sm:text-sm">
<span className="block truncate text-base font-medium">
{item}
</span>
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
{icon}
</span>
<ListboxButton className="peer flex w-full items-center gap-2 rounded-md px-4 py-2 text-left text-white hover:bg-wsg-orange-400 hover:bg-opacity-50 focus:ring-1 focus:ring-wsi-blue-300 sm:text-sm">
{leftIcon && <span>{leftIcon}</span>}
<span className="flex-1 text-base font-medium">{item.label}</span>
{rightIcon && <span>{rightIcon}</span>}
</ListboxButton>

<Transition
Expand All @@ -49,11 +50,11 @@ export const Dropdown = ({ item, options, icon, onChange, label }: Props) => {
leaveTo="opacity-0"
>
<ListboxOptions className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
{options.map((option) => (
{options.map((option, index) => (
<ListboxOption
key={option}
key={index}
className={
"relative cursor-default select-none py-2 pl-3 pr-9 text-gray-900 hover:bg-wsg-orange-700"
"relative cursor-pointer select-none py-2 pl-3 pr-9 text-gray-900 hover:bg-wsg-orange-700"
}
value={option}
>
Expand All @@ -65,14 +66,14 @@ export const Dropdown = ({ item, options, icon, onChange, label }: Props) => {
"block truncate",
)}
>
{option}
{option.label}
</span>

{selected ? (
{selected && (
<span className="absolute inset-y-0 right-0 flex items-center pr-4 text-wsi-blue-300">
<CheckIcon className="h-5 w-5" aria-hidden="true" />
</span>
) : null}
)}
</>
)}
</ListboxOption>
Expand All @@ -84,4 +85,4 @@ export const Dropdown = ({ item, options, icon, onChange, label }: Props) => {
)}
</Listbox>
);
};
}
20 changes: 10 additions & 10 deletions src/components/dropdowns/LanguageDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { ChevronUpDownIcon } from "@heroicons/react/20/solid";
import type { LocalePath } from "~/i18n";
import { LanguageIcon } from "@heroicons/react/20/solid";
import { languages, type Language, type LocalePath } from "~/i18n";
import { Dropdown } from "./Dropdown";

interface Props {
lang: string;
lang: Language;
paths: LocalePath[];
}

export const LanguageDropdown = ({ lang, paths }: Props) => (
<Dropdown
item={lang.toUpperCase()}
icon={<ChevronUpDownIcon className="h-5 w-5" aria-hidden="true" />}
options={paths.map(({ lang }) => lang.toUpperCase())}
onChange={(option) =>
item={{ label: languages[lang], value: lang }}
leftIcon={<LanguageIcon className="h-5 w-5" aria-hidden="true" />}
options={paths.map(({ lang }) => ({ label: languages[lang], value: lang }))}
onChange={(option) => {
window.location.assign(
paths.find(({ lang }) => lang.toUpperCase() === option)?.path || "",
)
}
paths.find(({ lang }) => lang === option)?.path || "",
);
}}
/>
);
6 changes: 3 additions & 3 deletions src/components/dropdowns/SkillsDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ interface Props {

export const SkillsDropdown = ({ title, skills }: Props) => (
<Dropdown
item={title}
icon={<ChevronDownIcon className="h-5 w-5" aria-hidden="true" />}
options={skills.map(({ name }) => name)}
item={{ label: title, value: "" }}
rightIcon={<ChevronDownIcon className="h-5 w-5" aria-hidden="true" />}
options={skills.map(({ name }) => ({ label: name, value: name }))}
onChange={(option) =>
window.location.assign(
skills.find(({ name }) => name === option)?.href || "",
Expand Down

0 comments on commit 21d5f1b

Please sign in to comment.