Skip to content

Commit

Permalink
Make all options in filter sidebar collapsible
Browse files Browse the repository at this point in the history
  • Loading branch information
Oksamies committed Jun 20, 2024
1 parent 9ad3cfb commit 460a309
Show file tree
Hide file tree
Showing 6 changed files with 256 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,44 +23,40 @@ export const CategoryMenu = (props: Props) => {

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

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={classnames(
styles.label,
c.selection !== "off" ? styles[c.selection] : undefined
)}
if (categories.length) {
return (
<ol className={styles.list}>
{categories.map((c) => (
<li key={c.slug}>
<label
className={classnames(
styles.label,
c.selection !== "off" ? styles[c.selection] : undefined
)}
>
<Checkbox.Root
checked={c.selection !== "off"}
onCheckedChange={() => toggleCategory(c.id)}
className={styles.checkbox}
>
<Checkbox.Root
checked={c.selection !== "off"}
onCheckedChange={() => toggleCategory(c.id)}
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 className={styles.empty}>No categories</p>
)}
</div>
);
<Checkbox.Indicator>
<Icon>
<FontAwesomeIcon
icon={c.selection === "include" ? faCheck : faXmark}
className={styles.icon}
/>
</Icon>
</Checkbox.Indicator>
</Checkbox.Root>
{c.name}
</label>
</li>
))}
</ol>
);
} else {
return <p className={styles.empty}>No categories</p>;
}
};

CategoryMenu.displayName = "CategoryMenu";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
.root {
display: flex;
flex-direction: column;
font-size: var(--font-size--m);
}

.header,
.empty {
padding: var(--space--8) var(--space--12);
font-weight: var(--font-weight-boldest);
font-size: var(--font-size--l);
}

.header {
display: flex;
justify-content: space-between;
}

.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: var(--font-weight-bold);
cursor: pointer;
transition: var(--animation-length-xs);
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 var(--animation-length-xs);
}

.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);
}

.radio {
display: flex;
align-items: center;
justify-content: center;
width: var(--space--16);
height: var(--space--16);
border: var(--space--2) solid var(--color-surface--7);
border-radius: var(--border-radius--8);
background-color: transparent;
transition: ease-out var(--animation-length-xs);
}

.radio.radioSelected {
border-color: var(--mark-color);
}

.radioIndicator {
display: block;
width: var(--space--6);
height: var(--space--6);
border-radius: 50%;
background-color: var(--mark-color);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { PropsWithChildren } from "react";
import { faCaretDown } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import styles from "./CollapsibleMenu.module.css";
import { Icon } from "@thunderstore/cyberstorm";

interface Props extends PropsWithChildren {
headerTitle: string;
defaultOpen?: boolean;
}

/**
* Wrapper for making a menu collapsible
*/
export const CollapsibleMenu = (props: Props) => {
const { headerTitle, defaultOpen, children } = props;

return (
<details className={styles.root} open={defaultOpen}>
<summary className={styles.header}>
{headerTitle}
<Icon inline>
<FontAwesomeIcon icon={faCaretDown} />
</Icon>
</summary>
{children}
</details>
);
};

CollapsibleMenu.displayName = "CollapsibleMenu";
Original file line number Diff line number Diff line change
Expand Up @@ -24,35 +24,31 @@ export const OthersMenu = (props: Props) => {
];

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

<ol className={styles.list}>
{filters.map(([checked, setChecked, label]) => (
<li key={label}>
<label
className={classnames(
styles.label,
checked ? styles.include : null
)}
<ol className={styles.list}>
{filters.map(([checked, setChecked, label]) => (
<li key={label}>
<label
className={classnames(
styles.label,
checked ? styles.include : null
)}
>
<Checkbox.Root
checked={checked}
onCheckedChange={() => setChecked(!checked)}
className={styles.checkbox}
>
<Checkbox.Root
checked={checked}
onCheckedChange={() => setChecked(!checked)}
className={styles.checkbox}
>
<Checkbox.Indicator>
<Icon>
<FontAwesomeIcon icon={faCheck} className={styles.icon} />
</Icon>
</Checkbox.Indicator>
</Checkbox.Root>
{label}
</label>
</li>
))}
</ol>
</div>
<Checkbox.Indicator>
<Icon>
<FontAwesomeIcon icon={faCheck} className={styles.icon} />
</Icon>
</Checkbox.Indicator>
</Checkbox.Root>
{label}
</label>
</li>
))}
</ol>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,29 @@ interface Props {
export const SectionMenu = (props: Props) => {
const { allSections, selected, setSelected } = props;

if (!allSections.length) {
return null;
}

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

<RadioGroup.Root value={selected} onValueChange={setSelected}>
{allSections.map((s) => (
<label
key={s.slug}
<RadioGroup.Root value={selected} onValueChange={setSelected}>
{allSections.map((s) => (
<label
key={s.slug}
className={classnames(
styles.label,
s.uuid === selected ? styles.include : null
)}
>
<RadioGroup.Item
value={s.uuid}
className={classnames(
styles.label,
s.uuid === selected ? styles.include : null
styles.radio,
s.uuid === selected ? styles.radioSelected : null
)}
>
<RadioGroup.Item
value={s.uuid}
className={classnames(
styles.radio,
s.uuid === selected ? styles.radioSelected : null
)}
>
<RadioGroup.Indicator className={styles.radioIndicator} />
</RadioGroup.Item>
{s.name}
</label>
))}
</RadioGroup.Root>
</div>
<RadioGroup.Indicator className={styles.radioIndicator} />
</RadioGroup.Item>
{s.name}
</label>
))}
</RadioGroup.Root>
);
};

Expand Down
Loading

0 comments on commit 460a309

Please sign in to comment.