Skip to content

Commit

Permalink
Merge pull request #66 from DenizUgur/ui-fixes
Browse files Browse the repository at this point in the history
UI Fixes
  • Loading branch information
podborski authored Sep 1, 2023
2 parents 1f5e497 + 0f79690 commit 45c772f
Show file tree
Hide file tree
Showing 15 changed files with 133 additions and 85 deletions.
2 changes: 1 addition & 1 deletion conformance-search/src/components/BoxComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export default function BoxComponent({ box }: { box: SearchResultRefined<Box> })
return (
<div
className={clsx(
"relative flex w-full flex-col divide-y-1 rounded-md bg-white shadow-md",
"relative flex w-full flex-col divide-y-1 overflow-hidden rounded-md bg-white shadow-md",
box.score === 0 && "border-l-4 border-green-400",
box.score > 0 && "border-l-4 border-yellow-400",
box.count === 0 && "border-l-4 !border-red-400 opacity-40"
Expand Down
2 changes: 1 addition & 1 deletion conformance-search/src/components/Drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default function Drawer({

if (hidden) return null;
return (
<div ref={ref} className="sticky last:border-b-1">
<div ref={ref} className="sticky">
<div
className={clsx("sticky top-0 border-t-1 bg-white px-3 py-1", open && "border-b-1")}
>
Expand Down
2 changes: 1 addition & 1 deletion conformance-search/src/components/FeatureComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function FeatureComponent({ feature }: { feature: SearchResultRef
return (
<div
className={clsx(
"relative flex w-full flex-col divide-y-1 rounded-md bg-white shadow-md",
"relative flex w-full flex-col divide-y-1 overflow-hidden rounded-md bg-white shadow-md",
feature.score === 0 && "border-l-4 border-green-400",
feature.score > 0 && "border-l-4 border-yellow-400",
feature.count === 0 && "border-l-4 border-red-400 opacity-40"
Expand Down
6 changes: 3 additions & 3 deletions conformance-search/src/components/FileComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ export default function FileComponent({ file }: { file: FileSearchResult }) {
>
{file.item.published ? "Published" : "Under Consideration"}
</span>
{file.matches.slice(0, 8).map((match) => {
{file.matches.slice(0, 4).map((match) => {
return (
<span
key={match.value}
Expand All @@ -290,9 +290,9 @@ export default function FileComponent({ file }: { file: FileSearchResult }) {
</span>
);
})}
{file.matches.length > 8 && (
{file.matches.length > 4 && (
<span className="flex h-4 items-center justify-center whitespace-nowrap rounded-full bg-gray-500 px-2 text-xs font-bold text-white opacity-40">
+{file.matches.length - 6} more
+{file.matches.length - 4} more
</span>
)}
</div>
Expand Down
44 changes: 20 additions & 24 deletions conformance-search/src/components/Input/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import clsx from "clsx";
import Fuse from "fuse.js";
import { useEffect, useRef, useState } from "react";
import React, { forwardRef, useEffect, useState } from "react";
import { useEvent, useIntersection } from "react-use";
import { normalizeResultScores } from "@/utils";
import { Chip } from "@/components";
import { FuseSearchWithScore } from "@/types";

export default function Dropdown({
query,
fuse,
parseValue,
hidden
}: {
query: string;
fuse: {
fourccs: Fuse<string>;
types: Fuse<string>;
};
parseValue: (value: string) => Promise<void>;
hidden: boolean;
}) {
function Dropdown(
{
query,
fuse,
parseValue
}: {
query: string;
fuse: {
fourccs: Fuse<string>;
types: Fuse<string>;
};
parseValue: (value: string) => Promise<void>;
},
ref: React.ForwardedRef<HTMLDivElement>
) {
const [activeIndex, setActiveIndex] = useState(-1);
const [results, setResults] = useState<{
fourccs: FuseSearchWithScore<string>[];
Expand All @@ -30,8 +30,7 @@ export default function Dropdown({
});

// Check if the dropdown is visible
const ref = useRef(null);
const intersection = useIntersection(ref, {
const intersection = useIntersection(ref as React.MutableRefObject<HTMLDivElement>, {
root: null,
rootMargin: "0px",
threshold: 0.1
Expand Down Expand Up @@ -142,12 +141,7 @@ export default function Dropdown({
return (
<div
ref={ref}
className={clsx(
"absolute bottom-[-1px] z-10 translate-y-full flex-col gap-3 bg-white p-3 shadow-lg outline outline-1 outline-gray-200 max-md:right-0 sm:left-[-3]",
hidden || (results.fourccs.length === 0 && results.types.length === 0)
? "hidden"
: "flex"
)}
className="mt-[1.5px] flex flex-col gap-3 bg-white p-3 shadow-lg outline outline-1 outline-gray-200"
data-testid="dropdown"
>
{dropdownSection({
Expand All @@ -162,3 +156,5 @@ export default function Dropdown({
</div>
);
}

export default forwardRef(Dropdown);
2 changes: 1 addition & 1 deletion conformance-search/src/components/Input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default function Input({
updateFilter(index, (e.target as HTMLInputElement).value)
}
placeholder={placeholder}
type="text"
type="search"
value={filter.value}
/>
);
Expand Down
59 changes: 42 additions & 17 deletions conformance-search/src/components/Input/variants/ContainerInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useClickAway } from "react-use";
import Search from "@/lib/search";
import { Chip } from "@/components";
import { Filter } from "@/types";
import { Popper } from "@mui/material";
import Dropdown from "../Dropdown";
import stripSpecialChars from "../helpers";

Expand Down Expand Up @@ -95,14 +96,17 @@ export default function ContainerInput({
updateFuse(search);
}, [parsed, search]);

// Focus the input when the parsed value changes
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
inputRef.current?.focus();
}, [parsed]);

// Dropdown menu
const dropdownContainerRef = useRef<HTMLDivElement>(null);
const dropdownRef = useRef<HTMLDivElement>(null);
const [open, setOpen] = useState(false);

const handleClickOutside = () => {
setOpen(false);
};

// Capture delete key
const onKeyDown = async (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Backspace") {
Expand All @@ -119,7 +123,15 @@ export default function ContainerInput({
}
};

useClickAway(dropdownRef, handleClickOutside);
useClickAway(
dropdownContainerRef,
(e: MouseEvent) => {
const target = e.target as HTMLElement;
if (dropdownRef.current?.contains(target)) return;
setOpen(false);
},
["mouseup"]
);

return (
<div className="relative flex grow flex-row items-center pl-3 text-sm">
Expand Down Expand Up @@ -159,25 +171,38 @@ export default function ContainerInput({
</Chip>
))}
</div>
<div ref={dropdownRef} className="relative flex h-full grow flex-row">
<div ref={dropdownContainerRef} className="relative flex h-full grow flex-row">
<input
className="w-full focus:outline-none"
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setQuery((e.target as HTMLInputElement).value)
}
ref={inputRef}
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="w-fit focus:outline-none xs:w-full"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setQuery((e.target as HTMLInputElement).value);
setOpen(true);
}}
onClick={() => setOpen(true)}
onKeyDown={onKeyDown}
placeholder={placeholder}
type="text"
spellCheck="false"
type="search"
value={query}
/>
{fuse && (
<Dropdown
fuse={fuse}
hidden={!open || query === ""}
parseValue={parseValue}
query={query}
/>
<Popper
anchorEl={inputRef.current}
className="z-20"
open={open && query !== ""}
placement="bottom-start"
>
<Dropdown
ref={dropdownRef}
fuse={fuse}
parseValue={parseValue}
query={query}
/>
</Popper>
)}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default function SearchComponent({
onResult
}: {
className?: string;
onResult: (boxes: SearchResult<Box>[], features: SearchResult<Feature>[]) => Promise<void>;
onResult: (boxes: SearchResult<Box>[], features: SearchResult<Feature>[]) => void;
}) {
const [loading, setLoading] = useState(false);
const [open, setOpen] = useState(false);
Expand Down Expand Up @@ -52,7 +52,7 @@ export default function SearchComponent({
// Update URL
setQueryParams(query, filters);
const { boxes, features } = await search.search(query, filters);
await onResult(boxes, features);
onResult(boxes, features);
setLoading(false);
},
250,
Expand All @@ -63,6 +63,10 @@ export default function SearchComponent({
useEffect(() => {
const newState = filters.length > 0 && open;
setOpen(newState);

// If open, disable scroll
if (newState) document.body.style.overflow = "hidden";
else document.body.style.overflow = "auto";
}, [open, filters]);

return (
Expand Down Expand Up @@ -122,7 +126,7 @@ export default function SearchComponent({
filters.map((filter: Filter, index: number) => (
<div
key={filter.value}
className="flex flex-row items-stretch divide-x-1 px-3"
className="flex flex-row items-stretch divide-x-1 overflow-x-scroll px-3"
>
<button
className="my-3 mr-3 cursor-pointer"
Expand Down
34 changes: 23 additions & 11 deletions conformance-search/src/components/Select.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Popper } from "@mui/material";
import clsx from "clsx";
import { useRef, useState } from "react";
import { IoChevronDown } from "react-icons/io5";
Expand All @@ -16,14 +17,19 @@ export default function Select({
value: string;
onChange: (newValue: string) => void;
}) {
const ref = useRef(null);
const ref = useRef<HTMLUListElement>(null);
const refContainer = useRef<HTMLDivElement>(null);
const [open, setOpen] = useState(false);

const handleClickOutside = () => {
setOpen(false);
};

useClickAway(ref, handleClickOutside);
useClickAway(
refContainer,
(e: MouseEvent) => {
const target = e.target as HTMLElement;
if (ref.current?.contains(target)) return;
setOpen(false);
},
["mouseup"]
);

// Get the longest option
const longestOption = Math.max(
Expand All @@ -34,8 +40,9 @@ export default function Select({
);

return (
<div ref={ref} className="relative" style={{ width: `${longestOption * 0.7}rem` }}>
<div className="relative" style={{ minWidth: `${longestOption * 0.7}rem` }}>
<div
ref={refContainer}
className={clsx(
"flex h-full cursor-pointer flex-row items-center justify-evenly whitespace-nowrap pl-4 pr-12 text-sm",
className
Expand All @@ -52,9 +59,14 @@ export default function Select({
<span>{value === "" ? "Select one..." : items[value].name}</span>
<IoChevronDown className="absolute right-4" />
</div>
{open && (
<div className="absolute bottom-[-1px] z-10 w-full translate-y-full bg-white shadow-lg outline outline-1 outline-gray-200">
<ul>
<Popper anchorEl={refContainer.current} className="z-20" open={open} placement="bottom">
<div
className="mt-[1.5px] bg-white shadow-lg outline outline-1 outline-gray-200"
style={{
minWidth: `calc(${longestOption * 0.7}rem - 1px)`
}}
>
<ul ref={ref}>
{value === "" && (
<li className="cursor-pointer px-4 py-2 text-sm transition-all duration-75 hover:bg-neutral-200">
Select one...
Expand Down Expand Up @@ -82,7 +94,7 @@ export default function Select({
))}
</ul>
</div>
)}
</Popper>
</div>
);
}
Expand Down
31 changes: 18 additions & 13 deletions conformance-search/src/components/SpecsCovered.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,30 @@ export default function SpecsCovered({
<a
key={info.ISO}
className={clsx(
"group flex items-center justify-between gap-2 truncate px-3 py-2 font-light hover:bg-gray-100",
"group flex items-center justify-between gap-2 px-3 py-2 font-light hover:bg-gray-100",
compact && "text-sm font-normal"
)}
href={info.link}
rel="noreferrer"
target="_blank"
>
<span>
ISO/IEC {info.ISO}:{info.date} (
<span className="font-bold">{info.name}</span>):{" "}
{addOrdinalSuffix(info.version)} Edition{" "}
{info.amendmends &&
info.amendmends.length > 0 &&
`, ${info.amendmends.join(", ")}`}
{info.corrigenda &&
info.corrigenda.length > 0 &&
`, ${info.corrigenda.join(", ")}`}
</span>
<FaExternalLinkAlt className="text-xs opacity-0 transition-opacity duration-200 group-hover:opacity-100" />
<div className="flex flex-wrap gap-1">
<span>
ISO/IEC {info.ISO}:{info.date}
</span>
<span>
(<b>{info.name}</b>): {addOrdinalSuffix(info.version)} Edition
</span>
<span>
{info.amendmends &&
info.amendmends.length > 0 &&
`, ${info.amendmends.join(", ")}`}
{info.corrigenda &&
info.corrigenda.length > 0 &&
`, ${info.corrigenda.join(", ")}`}
</span>
</div>
<FaExternalLinkAlt className="opacity-0 transition-opacity duration-200 group-hover:opacity-100 md:text-xs" />
</a>
))}
</div>
Expand Down
4 changes: 4 additions & 0 deletions conformance-search/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ body {
@apply bg-paper;
}

b {
@apply font-bold;
}

#root {
@apply h-screen w-screen flex flex-col;
}
Expand Down
4 changes: 2 additions & 2 deletions conformance-search/src/lib/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,8 +428,8 @@ class Search {
boxes = boxes.filter((box) => box.item.fourcc !== "file");

// Normalize scores
boxes = normalizeResultScores(boxes, query === "" ? 1.0 : 0.2);
features = normalizeResultScores(features, query === "" ? 1.0 : 0.2);
boxes = normalizeResultScores(boxes, query === "");
features = normalizeResultScores(features, query === "");

// Filter out results with low scores
boxes = boxes.filter((result) => result.score <= 0.2);
Expand Down
Loading

0 comments on commit 45c772f

Please sign in to comment.