Skip to content

Commit

Permalink
Allow filtering of icons and components (#553)
Browse files Browse the repository at this point in the history
  • Loading branch information
victortrinh2 authored Dec 18, 2024
2 parents ebfd043 + f92b4aa commit 193c2a6
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 40 deletions.
19 changes: 14 additions & 5 deletions apps/docs/app/ui/icons/iconTable/IconTable.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
"use client";

import IconItem from "./IconItem";
import * as IconLibrary from "@hopper-ui/icons";
import { HopperProvider } from "@hopper-ui/components";
import * as IconLibrary from "@hopper-ui/icons";
import IconItem from "./IconItem";

import { ThemeContext } from "@/context/theme/ThemeProvider";
import { useContext } from "react";
import "./iconTable.css";

interface IconTableProps {
size: "sm" | "md" | "lg" | "xl";
type: "svg" | "react";
items: typeof IconLibrary.iconNames | typeof IconLibrary.richIconNames;
filter?: string;
}

function toKebabCase(str: string) {
return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
}

function getIconNumericSize(iconSize : "sm" | "md" | "lg" | "xl") {
switch (iconSize) {
case "sm":
Expand All @@ -28,8 +32,13 @@ function getIconNumericSize(iconSize : "sm" | "md" | "lg" | "xl") {
}
}

export const IconTable = ({ size, type, items }: IconTableProps) => {
const listItems = items.map(name => {
export const IconTable = ({ size, type, items, filter }: IconTableProps) => {
const { colorMode } = useContext(ThemeContext);
const listItems = items.filter(name => {
const formattedName = name.replace("RichIcon", "").replace("Icon", "");

return !filter || formattedName.toLowerCase().includes(filter.trim().toLowerCase());
}).map(name => {
const formattedName = name.replace("RichIcon", "").replace("Icon", "");
const copyString = type === "react"
? `${name}`
Expand All @@ -45,7 +54,7 @@ export const IconTable = ({ size, type, items }: IconTableProps) => {
});

return (
<HopperProvider colorScheme="light">
<HopperProvider colorScheme={colorMode}>
<div className="hd-icon-table">
{listItems}
</div>
Expand Down
21 changes: 16 additions & 5 deletions apps/docs/app/ui/icons/switcher/Switcher.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"use client";

import { memo, useState, type ReactNode } from "react";
import { RadioGroup, Radio, type RadioProps } from "react-aria-components";
import { IconTable } from "@/app/ui/icons/iconTable/IconTable.tsx";
import { SparklesIcon, SparklesRichIcon, iconNames, richIconNames } from "@hopper-ui/icons";
import { memo, useContext, useState, type ReactNode } from "react";
import { Radio, RadioGroup, type RadioProps } from "react-aria-components";

import { ThemeContext } from "@/context/theme/ThemeProvider";
import { HopperProvider, TextField } from "@hopper-ui/components";
import "./switcher.css";

interface SwitcherProps {
Expand All @@ -15,21 +17,30 @@ interface SwitcherProps {
type AvailableSizes = "sm"| "md" | "lg" | "xl";

const Switcher = memo(({ type, iconType = "icon" }: SwitcherProps) => {
const { colorMode } = useContext(ThemeContext);
const [filter, setFilter] = useState("");
const [selectedSize, setSelectedSize] = useState<AvailableSizes>(iconType === "icon" ? "md" : "lg");

const Icon = iconType === "icon" ? SparklesIcon : SparklesRichIcon;
const iconList = iconType === "icon" ? iconNames : richIconNames;

const onTextFieldChange = (value: string) => {
setFilter(value);
};

return (
<>
<div className="hd-switcher__wrapper">
<RadioGroup className="hd-switcher-picker" defaultValue={selectedSize} onChange={value => setSelectedSize(value as AvailableSizes)}>
{iconType === "icon" && <SwitcherChoice value="sm" preview={<SparklesIcon size="sm" />} />}
<SwitcherChoice value="md" preview={<Icon size="md" />} />
<SwitcherChoice value="lg" preview={<Icon size="lg" />} />
{iconType === "richIcon" && <SwitcherChoice value="xl" preview={<SparklesRichIcon size="xl" />} />}
</RadioGroup>
<IconTable type={type} size={selectedSize} items={iconList} />
</>
<HopperProvider colorScheme={colorMode}>
<TextField placeholder="Search" value={filter} onChange={onTextFieldChange} />
</HopperProvider>
<IconTable type={type} size={selectedSize} filter={filter} items={iconList} />
</div>
);
});

Expand Down
7 changes: 6 additions & 1 deletion apps/docs/app/ui/icons/switcher/switcher.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.hd-switcher-picker {
margin-bottom: var(--hd-space-3);
display: flex;
gap: var(--hd-space-2);
}
Expand Down Expand Up @@ -57,3 +56,9 @@
.hd-switcher-choice:has(input:focus-visible) {
outline: -webkit-focus-ring-color auto var(--hd-border-size);
}

.hd-switcher__wrapper {
display: flex;
gap: var(--hd-space-3);
flex-direction: column;
}
75 changes: 47 additions & 28 deletions apps/docs/app/ui/layout/sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,25 @@ import { FeatureFlagContext } from "@/context/feature/FeatureFlagProvider.tsx";
import clsx from "clsx";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useContext, useEffect, useRef } from "react";
import { useContext, useEffect, useRef, useState } from "react";

import { useSidebar } from "@/context/sidebar/SidebarProvider";

import Overlay from "@/components/overlay/Overlay";

import type { Section } from "@/app/lib/getPageLinks";

import { ThemeContext } from "@/context/theme/ThemeProvider";
import { HopperProvider, TextField } from "@hopper-ui/components";
import "./sidebar.css";

export interface SidebarProps {
links: Section[];
}

const Sidebar = ({ links }: SidebarProps) => {
const { colorMode } = useContext(ThemeContext);
const [filter, setFilter] = useState("");
const sidebarRef = useRef<HTMLDivElement>(null);
const pathName = usePathname();
const sidebarContext = useSidebar()!;
Expand Down Expand Up @@ -68,33 +72,45 @@ const Sidebar = ({ links }: SidebarProps) => {
}
};

const linkItems = links.map(link => {
return (
<ul className="hd-sidebar__list" key={link.id}>
<li className="hd-sidebar__item hd-sidebar-section">
<span className="hd-sidebar__title">{link.title}</span>
<ul className="hd-sidebar__nested-list">
{link.linkItems
.filter(item => item.status === "ready" || item.status === undefined || (item.status === "alpha" && featureFlags.alpha)).map(item => {
const linkPath = `/${item.path}`;
const isActive = pathName === linkPath;

return (
<li className={clsx("hd-sidebar__item", isActive && "hd-sidebar__item--active")}
key={item.id}
>
<Link href={linkPath}
className="hd-sidebar__link"
onClick={handleLinkClick}
>{item.title}</Link>
</li>
);
})}
</ul>
</li>
</ul>
);
});
const onTextFieldChange = (value: string) => {
setFilter(value);
};

const linkItems = links
.filter(link => {
const trimmedFilter = filter.trim().toLowerCase();

const hasMatch = (value: string) => value.toLowerCase().includes(trimmedFilter);

return hasMatch(link.title) || link.linkItems.find(item => hasMatch(item.title));
})
.map(link => {
return (
<ul className="hd-sidebar__list" key={link.id}>
<li className="hd-sidebar__item hd-sidebar-section">
<span className="hd-sidebar__title">{link.title}</span>
<ul className="hd-sidebar__nested-list">
{link.linkItems
.filter(item => item.status === "ready" || item.status === undefined || (item.status === "alpha" && featureFlags.alpha)).map(item => {
const linkPath = `/${item.path}`;
const isActive = pathName === linkPath;

return (
<li className={clsx("hd-sidebar__item", isActive && "hd-sidebar__item--active")}
key={item.id}
>
<Link href={linkPath}
className="hd-sidebar__link"
onClick={handleLinkClick}
>{item.title}</Link>
</li>
);
})}
</ul>
</li>
</ul>
);
});

return (
<>
Expand All @@ -105,6 +121,9 @@ const Sidebar = ({ links }: SidebarProps) => {
>
<div className="hd-sidebar__wrapper">
<div className="hd-sidebar__container">
<HopperProvider colorScheme={colorMode}>
<TextField placeholder="Search" value={filter} onChange={onTextFieldChange} />
</HopperProvider>
{linkItems}
</div>
</div>
Expand Down
1 change: 0 additions & 1 deletion apps/docs/app/ui/layout/sidebar/sidebar.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
opacity: 0;
}


@media screen and (width >= 48rem) {
.hd-sidebar {
position: sticky;
Expand Down

0 comments on commit 193c2a6

Please sign in to comment.