forked from ShelterTechSF/askdarcel-web
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
make git acknowledge SearchAndBrowse case change
- Loading branch information
1 parent
d7112a0
commit 1a4d5b6
Showing
28 changed files
with
2,343 additions
and
0 deletions.
There are no files selected for viewing
20 changes: 20 additions & 0 deletions
20
app/components/SearchAndBrowse/Header/BrowseHeaderSection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
44
app/components/SearchAndBrowse/Header/BrowseSubheader.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
49
app/components/SearchAndBrowse/Header/CustomDropdown.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
155
app/components/SearchAndBrowse/Header/CustomDropdown.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
); | ||
}; |
36 changes: 36 additions & 0 deletions
36
app/components/SearchAndBrowse/Header/SearchHeaderSection.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.