Skip to content

Commit

Permalink
@thunderstore/cyberstorm: replace FilterItemList with CategoryMenu
Browse files Browse the repository at this point in the history
- Simplify the implementation
- Will disconnect the menu from the tag cloud showing the selected
  categories, and the package list filtering the packages based on the
  selection. These will be fixed in the next commits
- Didn't clean up the old Filters implementation, will do that when the
  tag cloud and package listing is refactored

Refs TS-1860
  • Loading branch information
anttimaki committed Oct 24, 2023
1 parent b92a8a9 commit c29daa7
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 68 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
.root {
display: flex;
flex-direction: column;
font-size: var(--font-size--m);
}

.header {
padding: var(--space--8) var(--space--12);
font-size: var(--font-size--m);
}

.list {
list-style: none;
}

.label {
display: flex;
gap: var(--gap--12);
align-items: center;
padding: var(--space--8) var(--space--12);
border-radius: var(--border-radius--8);
color: var(--color-text--secondary);
font-weight: 700;
cursor: pointer;
transition: 60ms;
user-select: none;

--mark-color: var(--color-purple--6);
}

.label:hover {
background-color: var(--color-surface--4);

--mark-color: var(--color-purple--2);
}

.checkbox {
width: var(--space--18);
height: var(--space--18);
border-radius: var(--border-radius--2);
background-color: var(--mark-color);
transition: ease-out 60ms;
}

.label:hover .checkbox { --mark-color: #4343a3; }

.label.include,
.label.include .checkbox {
color: var(--color-highlight);

--mark-color: var(--color-highlight);
}

.label.exclude,
.label.exclude .checkbox {
color: var(--color-danger);

--mark-color: var(--color-danger);
}

.icon {
height: var(--space--16);
color: var(--color-surface--0);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { faCheck, faXmark } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import * as Checkbox from "@radix-ui/react-checkbox";
import { Dispatch, SetStateAction } from "react";

import styles from "./CategoryMenu.module.css";
import { CategorySelection, CATEGORY_STATES as STATES } from "../types";
import { Icon } from "../../Icon/Icon";

interface Props {
categories: CategorySelection[];
setCategories: Dispatch<SetStateAction<CategorySelection[]>>;
}

/**
* Allow filtering packages by categories on PackageSearch.
*
* TODO TS-1715: show number of packages on each category.
*/
export const CategoryMenu = (props: Props) => {
const { categories, setCategories } = props;

const toggleCategory = (slug: string) =>
setCategories(toggle(categories, slug));

return (
<div className={styles.root}>
<h2 className={styles.header}>Categories</h2>

{categories.length ? (
<ol className={styles.list}>
{categories.map((c) => (
<li key={c.slug}>
<label className={`${styles.label} ${styles[c.selection]}`}>
<Checkbox.Root
checked={c.selection !== "off"}
onCheckedChange={() => toggleCategory(c.slug)}
className={styles.checkbox}
>
<Checkbox.Indicator>
<Icon>
<FontAwesomeIcon
icon={c.selection === "include" ? faCheck : faXmark}
className={styles.icon}
/>
</Icon>
</Checkbox.Indicator>
</Checkbox.Root>
{c.name}
</label>
</li>
))}
</ol>
) : (
<p>No categories</p>
)}
</div>
);
};

CategoryMenu.displayName = "CategoryMenu";

/**
* Three-way toggle a category and return a copy of the category list.
*
* Toggling "off" -> "include" -> "exclude" -> "off"
*/
const toggle = (categories: CategorySelection[], targetSlug: string) =>
categories.map((c) => {
if (c.slug === targetSlug) {
const nextIndex = (STATES.indexOf(c.selection) + 1) % STATES.length;
return { ...c, selection: STATES[nextIndex] };
}
return c;
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
gap: var(--gap--24);
}

.filterItemList {
.sidebar {
display: flex;
flex-basis: 20%;
flex-direction: column;
Expand Down
26 changes: 17 additions & 9 deletions packages/cyberstorm/src/components/PackageSearch/PackageSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import { PackageCategory } from "@thunderstore/dapper/types";
import { Suspense, useState, createContext } from "react";
import { useDebounce } from "use-debounce";

import { CategoryMenu } from "./CategoryMenu/CategoryMenu";
import styles from "./PackageSearch.module.css";
import { CategorySelection } from "./types";
import * as Button from "../Button/";
import { FilterItemList } from "../FilterItemList/FilterItemList";
import { Icon } from "../Icon/Icon";
import { Pagination } from "../Pagination/Pagination";
import { PackageList } from "../PackageList/PackageList";
Expand Down Expand Up @@ -95,22 +96,32 @@ function CurrentFilters(props: TagListProps) {

interface Props {
communityId?: string;
userId?: string;
teamId?: string;
packageCategories: PackageCategory[];
teamId?: string;
userId?: string;
}

/**
* Component for filtering and rendering a PackageList
*/
export function PackageSearch(props: Props) {
const { communityId, userId, teamId } = props;
const {
communityId,
packageCategories: allCategories,
teamId,
userId,
} = props;

const filters = new Filters();
const [order, setOrder] = useState("1");
const [page, setPage] = useState(1);
const [searchValue, setSearchValue] = useState("");
const [debouncedSearchValue] = useDebounce(searchValue, 300);
const [categories, setCategories] = useState<CategorySelection[]>(
allCategories
.sort((a, b) => a.slug.localeCompare(b.slug))
.map((c) => ({ ...c, selection: "off" }))
);

const clearFilters = () => {
setSearchValue("");
Expand All @@ -133,11 +144,8 @@ export function PackageSearch(props: Props) {
}
/>
<div className={styles.contentWrapper}>
<div className={styles.filterItemList}>
<FilterItemList
filterItems={filters.availableCategories}
filterItemsSetter={filters.setAvailableCategories}
/>
<div className={styles.sidebar}>
<CategoryMenu categories={categories} setCategories={setCategories} />
</div>
<div className={styles.content}>
<div className={styles.listTopNavigation}>
Expand Down
9 changes: 9 additions & 0 deletions packages/cyberstorm/src/components/PackageSearch/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { PackageCategory } from "@thunderstore/dapper/types";

export const CATEGORY_STATES = ["off", "include", "exclude"] as const;

export interface CategorySelection extends PackageCategory {
// TODO: IDE disagrees with what precommit prettier wants, fix config.
// eslint-disable-next-line prettier/prettier
selection: typeof CATEGORY_STATES[number];
}

0 comments on commit c29daa7

Please sign in to comment.