Skip to content

Commit

Permalink
feat: make filter options collapsible (#815)
Browse files Browse the repository at this point in the history
<!-- 👋 Hi, thanks for sending a PR to tidelift-me-up-site! 💖.
Please fill out all fields below and make sure each item is true and [x]
checked.
Otherwise we may not be able to review your PR. -->

## PR Checklist

- [x] Addresses an existing open issue: fixes #5 
- [x] That issue was marked as [`status: accepting
prs`](https://github.com/JoshuaKGoldberg/tidelift-me-up-site/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+accepting+prs%22)
- [x] Steps in
[CONTRIBUTING.md](https://github.com/JoshuaKGoldberg/tidelift-me-up-site/blob/main/.github/CONTRIBUTING.md)
were taken

## Overview

<!-- Description of what is changed and how the code change does that.
-->
Previously, the filter options were always visible and could not be
collapsed.

Now, the filter options can be collapsed, and the behavior is as
follows:
- By default, the filter options are visible when the site loads:
<img width="411" alt="filter-options-visible"
src="https://github.com/user-attachments/assets/a545f2e9-990a-4720-8e87-00c90d9e69e8">

- Users can toggle the filter options open and closed by clicking on the
"Filter options by v" button:
<img width="391" alt="filter-options-hidden"
src="https://github.com/user-attachments/assets/67f7f7b0-f247-4e08-ab7b-350331402ea3">

- The filter options automatically close when a search is submitted:
<img width="385" alt="search-results"
src="https://github.com/user-attachments/assets/dfc2060c-5f10-4870-85e2-46141378b263">

Lastly, another fav emoji of mine: 🌱!
  • Loading branch information
maggienegm authored Dec 1, 2024
1 parent ecedbfc commit ed4cac4
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 37 deletions.
15 changes: 15 additions & 0 deletions src/components/OptionsForm.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
.secondaryOptions {
flex-direction: column;
gap: 3rem;
margin-top: 1.25rem;
}

@media screen and (width >= 700px) {
Expand Down Expand Up @@ -138,3 +139,17 @@
height: 2rem;
padding: 0.5rem;
}

.optionsSummary {
align-items: center;
cursor: pointer;
display: flex;
font-style: italic;
gap: 4px;
justify-content: center;
list-style: none;
}

.optionsDetails[open] .chevronIcon {
transform: rotate(180deg);
}
96 changes: 59 additions & 37 deletions src/components/OptionsForm.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import { PackageOwnership } from "tidelift-me-up";

import { CallToAction } from "./CallToAction";
Expand All @@ -16,6 +18,8 @@ export interface OptionsFormProps {
export function OptionsForm({ options }: OptionsFormProps) {
const ownerships = new Set(options.ownership);

const optionsExpanded = !options.username;

return (
<form className={styles.optionsForm}>
<div className={styles.primaryOptions}>
Expand All @@ -39,44 +43,62 @@ export function OptionsForm({ options }: OptionsFormProps) {
</div>

<div className={styles.secondaryOptionsArea}>
<h2 className={styles.h2}>optionally, filter by:</h2>
<div className={styles.secondaryOptions}>
<div className={styles.secondaryOptionArea}>
<label className={styles.labelSecondary} htmlFor="since">
Updated Since
</label>
<input
className={styles.inputSecondary}
defaultValue={options.since && options.since.toString()}
id="since"
name="since"
type="date"
></input>
</div>

<fieldset className={styles.secondaryOptionArea} name="ownership">
<legend className={styles.legendSecondary}>
Relationship to Project
</legend>
<div className={styles.fieldsetOptions}>
{(["author", "maintainer", "publisher"] as const).map(
(ownershipForm) => (
<div className={styles.secondaryOption} key={ownershipForm}>
<input
defaultChecked={ownerships.has(ownershipForm)}
id={ownershipForm}
name={ownershipForm}
type="checkbox"
/>
<label htmlFor={ownershipForm}>
{upperFirst(ownershipForm)}
</label>
</div>
),
)}
<details className={styles.optionsDetails} open={optionsExpanded}>
<summary className={styles.optionsSummary}>
optionally, filter by{" "}
<svg
className={styles.chevronIcon}
fill="none"
height="24"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M6 9l6 6 6-6" />
</svg>
</summary>
<div className={styles.secondaryOptions}>
<div className={styles.secondaryOptionArea}>
<label className={styles.labelSecondary} htmlFor="since">
Updated Since
</label>
<input
className={styles.inputSecondary}
defaultValue={options.since && options.since.toString()}
id="since"
name="since"
type="date"
></input>
</div>
</fieldset>
</div>

<fieldset className={styles.secondaryOptionArea} name="ownership">
<legend className={styles.legendSecondary}>
Relationship to Project
</legend>
<div className={styles.fieldsetOptions}>
{(["author", "maintainer", "publisher"] as const).map(
(ownershipForm) => (
<div className={styles.secondaryOption} key={ownershipForm}>
<input
defaultChecked={ownerships.has(ownershipForm)}
id={ownershipForm}
name={ownershipForm}
type="checkbox"
/>
<label htmlFor={ownershipForm}>
{upperFirst(ownershipForm)}
</label>
</div>
),
)}
</div>
</fieldset>
</div>
</details>
</div>
</form>
);
Expand Down

0 comments on commit ed4cac4

Please sign in to comment.