mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-12 02:38:15 +00:00
Replace all @untitledui/icons imports across 55 files with equivalent
@fortawesome/pro-duotone-svg-icons icons, using FontAwesomeIcon wrappers
(FC<{ className?: string }>) for prop-based usage and inline replacements
for direct JSX usage. Drops unsupported Untitled UI-specific props
(strokeWidth, numeric size). TypeScript compiles clean with no errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
209 lines
10 KiB
TypeScript
209 lines
10 KiB
TypeScript
import type { FC, ReactNode } from "react";
|
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
import { faBell, faLifeRing, faMagnifyingGlass, faGear } from "@fortawesome/pro-duotone-svg-icons";
|
|
|
|
const Bell01: FC<{ className?: string }> = ({ className }) => <FontAwesomeIcon icon={faBell} className={className} />;
|
|
const LifeBuoy01: FC<{ className?: string }> = ({ className }) => <FontAwesomeIcon icon={faLifeRing} className={className} />;
|
|
const SearchLg: FC<{ className?: string }> = ({ className }) => <FontAwesomeIcon icon={faMagnifyingGlass} className={className} />;
|
|
const Settings01: FC<{ className?: string }> = ({ className }) => <FontAwesomeIcon icon={faGear} className={className} />;
|
|
import { Button as AriaButton, DialogTrigger, Popover } from "react-aria-components";
|
|
import { Avatar } from "@/components/base/avatar/avatar";
|
|
import { BadgeWithDot } from "@/components/base/badges/badges";
|
|
import { Input } from "@/components/base/input/input";
|
|
import { UntitledLogo } from "@/components/foundations/logo/untitledui-logo";
|
|
import { cx } from "@/utils/cx";
|
|
import { MobileNavigationHeader } from "./base-components/mobile-header";
|
|
import { NavAccountCard, NavAccountMenu } from "./base-components/nav-account-card";
|
|
import { NavItemBase } from "./base-components/nav-item";
|
|
import { NavItemButton } from "./base-components/nav-item-button";
|
|
import { NavList } from "./base-components/nav-list";
|
|
|
|
type NavItem = {
|
|
/** Label text for the nav item. */
|
|
label: string;
|
|
/** URL to navigate to when the nav item is clicked. */
|
|
href: string;
|
|
/** Whether the nav item is currently active. */
|
|
current?: boolean;
|
|
/** Icon component to display. */
|
|
icon?: FC<{ className?: string }>;
|
|
/** Badge to display. */
|
|
badge?: ReactNode;
|
|
/** List of sub-items to display. */
|
|
items?: NavItem[];
|
|
};
|
|
|
|
interface HeaderNavigationBaseProps {
|
|
/** URL of the currently active item. */
|
|
activeUrl?: string;
|
|
/** List of items to display. */
|
|
items: NavItem[];
|
|
/** List of sub-items to display. */
|
|
subItems?: NavItem[];
|
|
/** Content to display in the trailing position. */
|
|
trailingContent?: ReactNode;
|
|
/** Whether to show the avatar dropdown. */
|
|
showAvatarDropdown?: boolean;
|
|
/** Whether to hide the bottom border. */
|
|
hideBorder?: boolean;
|
|
}
|
|
|
|
export const HeaderNavigationBase = ({
|
|
activeUrl,
|
|
items,
|
|
subItems,
|
|
trailingContent,
|
|
showAvatarDropdown = true,
|
|
hideBorder = false,
|
|
}: HeaderNavigationBaseProps) => {
|
|
const activeSubNavItems = subItems || items.find((item) => item.current && item.items && item.items.length > 0)?.items;
|
|
|
|
const showSecondaryNav = activeSubNavItems && activeSubNavItems.length > 0;
|
|
|
|
return (
|
|
<>
|
|
<MobileNavigationHeader>
|
|
<aside className="flex h-full max-w-full flex-col justify-between overflow-auto border-r border-secondary bg-primary pt-4 lg:pt-6">
|
|
<div className="flex flex-col gap-5 px-4 lg:px-5">
|
|
<UntitledLogo className="h-8" />
|
|
<Input shortcut size="sm" aria-label="Search" placeholder="Search" icon={SearchLg} />
|
|
</div>
|
|
|
|
<NavList items={items} />
|
|
|
|
<div className="mt-auto flex flex-col gap-4 px-2 py-4 lg:px-4 lg:py-6">
|
|
<div className="flex flex-col gap-1">
|
|
<NavItemBase type="link" href="#" icon={LifeBuoy01}>
|
|
Support
|
|
</NavItemBase>
|
|
<NavItemBase
|
|
type="link"
|
|
href="#"
|
|
icon={Settings01}
|
|
badge={
|
|
<BadgeWithDot color="success" type="modern" size="sm">
|
|
Online
|
|
</BadgeWithDot>
|
|
}
|
|
>
|
|
Settings
|
|
</NavItemBase>
|
|
<NavItemBase type="link" href="https://www.untitledui.com/" icon={Settings01}>
|
|
Open in browser
|
|
</NavItemBase>
|
|
</div>
|
|
|
|
<NavAccountCard />
|
|
</div>
|
|
</aside>
|
|
</MobileNavigationHeader>
|
|
|
|
<header className="max-lg:hidden">
|
|
<section
|
|
className={cx(
|
|
"flex h-16 w-full items-center justify-center bg-primary md:h-18",
|
|
(!hideBorder || showSecondaryNav) && "border-b border-secondary",
|
|
)}
|
|
>
|
|
<div className="flex w-full max-w-container justify-between pr-3 pl-4 md:px-8">
|
|
<div className="flex flex-1 items-center gap-4">
|
|
<a
|
|
aria-label="Go to homepage"
|
|
href="/"
|
|
className="rounded-xs outline-focus-ring focus-visible:outline-2 focus-visible:outline-offset-2"
|
|
>
|
|
<UntitledLogo className="h-8" />
|
|
</a>
|
|
|
|
<nav>
|
|
<ul className="flex items-center gap-0.5">
|
|
{items.map((item) => (
|
|
<li key={item.label} className="py-0.5">
|
|
<NavItemBase icon={item.icon} href={item.href} current={item.current} badge={item.badge} type="link">
|
|
{item.label}
|
|
</NavItemBase>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-3">
|
|
{trailingContent}
|
|
|
|
<div className="flex gap-0.5">
|
|
<NavItemButton
|
|
current={activeUrl === "/settings-01"}
|
|
size="md"
|
|
icon={Settings01}
|
|
label="Settings"
|
|
href="/settings-01"
|
|
tooltipPlacement="bottom"
|
|
/>
|
|
<NavItemButton
|
|
current={activeUrl === "/notifications-01"}
|
|
size="md"
|
|
icon={Bell01}
|
|
label="Notifications"
|
|
href="/notifications-01"
|
|
tooltipPlacement="bottom"
|
|
/>
|
|
</div>
|
|
|
|
{showAvatarDropdown && (
|
|
<DialogTrigger>
|
|
<AriaButton
|
|
className={({ isPressed, isFocused }) =>
|
|
cx(
|
|
"group relative inline-flex cursor-pointer",
|
|
(isPressed || isFocused) && "rounded-full outline-2 outline-offset-2 outline-focus-ring",
|
|
)
|
|
}
|
|
>
|
|
<Avatar alt="Olivia Rhye" src="https://www.untitledui.com/images/avatars/olivia-rhye?bg=%23E0E0E0" size="md" />
|
|
</AriaButton>
|
|
<Popover
|
|
placement="bottom right"
|
|
offset={8}
|
|
className={({ isEntering, isExiting }) =>
|
|
cx(
|
|
"will-change-transform",
|
|
isEntering &&
|
|
"duration-300 ease-out animate-in fade-in placement-right:slide-in-from-left-2 placement-top:slide-in-from-bottom-2 placement-bottom:slide-in-from-top-2",
|
|
isExiting &&
|
|
"duration-150 ease-in animate-out fade-out placement-right:slide-out-to-left-2 placement-top:slide-out-to-bottom-2 placement-bottom:slide-out-to-top-2",
|
|
)
|
|
}
|
|
>
|
|
<NavAccountMenu />
|
|
</Popover>
|
|
</DialogTrigger>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{showSecondaryNav && (
|
|
<section className={cx("flex h-16 w-full items-center justify-center bg-primary", !hideBorder && "border-b border-secondary")}>
|
|
<div className="flex w-full max-w-container items-center justify-between gap-8 px-8">
|
|
<nav>
|
|
<ul className="flex items-center gap-0.5">
|
|
{activeSubNavItems.map((item) => (
|
|
<li key={item.label} className="py-0.5">
|
|
<NavItemBase icon={item.icon} href={item.href} current={item.current} badge={item.badge} type="link">
|
|
{item.label}
|
|
</NavItemBase>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</nav>
|
|
|
|
<Input shortcut aria-label="Search" placeholder="Search" icon={SearchLg} size="sm" className="max-w-xs" />
|
|
</div>
|
|
</section>
|
|
)}
|
|
</header>
|
|
</>
|
|
);
|
|
};
|