Skip to content

Commit

Permalink
make git acknowledge SearchAndBrowse case change
Browse files Browse the repository at this point in the history
  • Loading branch information
adriencyberspace committed Nov 15, 2024
1 parent d7112a0 commit 1a4d5b6
Show file tree
Hide file tree
Showing 28 changed files with 2,343 additions and 0 deletions.
20 changes: 20 additions & 0 deletions app/components/SearchAndBrowse/Header/BrowseHeaderSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";
import styles from "./SearchHeaderSection.module.scss";

/**
* Renders mobile and desktop views for Listings navigation
*/
export const BrowseHeaderSection = ({
descriptionText,
}: {
descriptionText: string;
}) => {
return (
<div className={styles.searchHeaderContainer}>
<div className={styles.searchHeaderContainerLeft}>
<h1>Services</h1>
</div>
<span>{descriptionText}</span>
</div>
);
};
44 changes: 44 additions & 0 deletions app/components/SearchAndBrowse/Header/BrowseSubheader.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
@import "~styles/utils/_helpers.scss";

.headerInner {
display: flex;
margin: 0 auto;
padding: $general-spacing-md $general-spacing-lg;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid $color-grey3;

@media screen and (max-width: $break-tablet-s) {
padding: $general-spacing-s $general-spacing-xxs;
}
}

.title {
text-align: left;
font-weight: bold;
font-size: 26px;

@media screen and (max-width: $break-tablet-s) {
font-size: 21px;
line-height: 20px;
}
}

.printAllBtn,
.qrCodeBtn {
display: none;

&.showBtn {
display: block;

@media screen and (max-width: $break-tablet-s) {
display: none;
}
}
}

.btnText {
font-weight: 600;
font-size: 16px;
margin-left: 10px;
}
57 changes: 57 additions & 0 deletions app/components/SearchAndBrowse/Header/BrowseSubheader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from "react";

import { Button } from "components/ui/inline/Button/Button";
import websiteConfig from "utils/websiteConfig";
import { CATEGORIES } from "pages/constants";
import DropdownMenu from "components/ui/Navigation/DropdownMenu";

import styles from "./BrowseSubheader.module.scss";

const { showPrintResultsBtn } = websiteConfig;

interface Props {
currentCategory: string;
}

// TODO: This should be the same as the dropdown links in the Navigation dropdown (which comes from Strapi)
const DROPDOWN_LINKS = CATEGORIES.map((category) => ({
id: category.slug,
url: `/${category.slug}/results`,
text: category.name,
}));

export const BrowseSubheader = ({ currentCategory }: Props) => {
const title = currentCategory;

const uuid = crypto.randomUUID();

return (
<div className={styles.header}>
<div className={styles.headerInner}>
<div>
<h1 className="sr-only">{title}</h1>
<DropdownMenu
id={uuid}
title={title}
links={DROPDOWN_LINKS}
variant="category"
/>
</div>
<Button
iconName="fas fa-print"
iconVariant="before"
variant="secondary"
size="lg"
onClick={() => {
window.print();
}}
addClass={`${styles.printAllBtn} ${
showPrintResultsBtn ? styles.showBtn : ""
}`}
>
Print this page
</Button>
</div>
</div>
);
};
49 changes: 49 additions & 0 deletions app/components/SearchAndBrowse/Header/CustomDropdown.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
@import "~styles/utils/_helpers.scss";

.dropdown {
position: relative;
display: inline-block;
}

.title {
font-size: 26px;
font-weight: bold;
cursor: pointer;
font-family: Montserrat;
padding: 0;

@include r_max($break-tablet-s) {
font-size: 20px;
}
}

.arrowDown i,
.arrowUp i {
margin-left: 5px;
}

.dropdownMenu {
display: block;
position: absolute;
background-color: white;
border-radius: $rounded-md;
top: 50px;
min-width: 160px;
box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.2);
z-index: $z-index-top;
list-style: none;
padding: 0;
margin: 0;
}

.dropdownMenu li {
font-family: Montserrat;
font-weight: 500;
padding: $general-spacing-s $general-spacing-md;
cursor: pointer;
}

.dropdownMenu li:hover,
.dropdownMenu li:focus {
background-color: $gray-100;
}
155 changes: 155 additions & 0 deletions app/components/SearchAndBrowse/Header/CustomDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import React, { useState, useRef, useEffect } from "react";
import { ServiceCategory } from "pages/constants";
import styles from "./CustomDropdown.module.scss";

interface DropdownProps {
categories: Readonly<ServiceCategory[]>;
currentCategory: string;
onCategoryChange: (slug: string) => void;
resultsTitle: string;
}

// NOTE: built quickly for demo

export const CustomDropdown: React.FC<DropdownProps> = ({
categories,
currentCategory,
onCategoryChange,
resultsTitle,
}) => {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
const menuRef = useRef<HTMLUListElement>(null);

const handleToggle = () => {
setIsOpen(!isOpen);
};

const handleCategoryChange = (slug: string) => {
onCategoryChange(slug);
setIsOpen(false);
buttonRef.current?.focus();
};

const handleKeyDown = (event: React.KeyboardEvent) => {
if (event.key === "Escape" && isOpen) {
setIsOpen(false);
buttonRef.current?.focus();
}

if (event.key === "ArrowDown" && !isOpen) {
setIsOpen(true);
event.preventDefault();
}

if (event.key === "ArrowDown" && isOpen) {
const firstMenuItem = menuRef.current?.querySelector("li");
(firstMenuItem as HTMLElement)?.focus();
event.preventDefault();
}

if (event.key === "ArrowUp" && isOpen) {
const lastMenuItem = menuRef.current?.querySelector("li:last-child");
(lastMenuItem as HTMLElement)?.focus();
event.preventDefault();
}
};

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
) {
setIsOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [dropdownRef]);

const handleItemKeyDown = (
event: React.KeyboardEvent,
slug: string,
index: number
) => {
const menuItems = Array.from(menuRef.current?.querySelectorAll("li") || []);

switch (event.key) {
case "ArrowDown":
event.preventDefault();
{
const nextItem = menuItems[index + 1] || menuItems[0];
(nextItem as HTMLElement)?.focus();
}
break;
case "ArrowUp":
event.preventDefault();
{
const prevItem =
menuItems[index - 1] || menuItems[menuItems.length - 1];
(prevItem as HTMLElement)?.focus();
}
break;
case "Enter":
case " ":
event.preventDefault();
handleCategoryChange(slug);
break;
case "Tab":
setIsOpen(false);
break;
default:
break;
}
};

return (
<div className={styles.dropdown} ref={dropdownRef}>
<button
ref={buttonRef}
type="button"
className={styles.title}
onClick={handleToggle}
onKeyDown={handleKeyDown}
aria-haspopup="listbox"
aria-expanded={isOpen}
style={{ cursor: "pointer" }}
>
{resultsTitle}{" "}
<span className={isOpen ? styles.arrowUp : styles.arrowDown}>
<i className={`fas fa-chevron-${isOpen ? "up" : "down"}`} />
</span>
</button>
{isOpen && (
<ul
ref={menuRef}
className={styles.dropdownMenu}
role="listbox"
aria-activedescendant={currentCategory}
tabIndex={-1}
>
{categories.map((category, index) => (
<li
key={category.slug}
onClick={() => handleCategoryChange(`/${category.slug}/results`)}
className={currentCategory === category.slug ? styles.active : ""}
role="option"
id={category.slug}
tabIndex={0}
aria-selected={currentCategory === category.slug}
onKeyDown={(event) =>
handleItemKeyDown(event, `/${category.slug}/results`, index + 1)
}
>
{category.name}
</li>
))}
</ul>
)}
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@import "~styles/utils/_helpers.scss";

.searchHeaderContainer {
display: flex;
justify-content: space-between;
align-items: center;
gap: $spacing-6;

@include r_max($break-tablet-s) {
display: block;
gap: $spacing-3;
}

.searchHeaderContainerLeft {
display: flex;
align-items: center;
gap: $spacing-6;

h1 {
font-size: 26px;
min-height: 100%;
line-height: 100%;
}

@include r_max($break-tablet-s) {
display: block;
width: 100%;
margin-bottom: $general-spacing-md;

h1 {
margin-bottom: $general-spacing-md;
font-size: 20px;
}
}
}
}
Loading

0 comments on commit 1a4d5b6

Please sign in to comment.