mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-12 02:38:15 +00:00
refactor: migrate all icons from Untitled UI to FontAwesome Pro Duotone
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>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import { User01 } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faUser } from "@fortawesome/pro-duotone-svg-icons";
|
||||
import { cx } from "@/utils/cx";
|
||||
import { type AvatarProps } from "./avatar";
|
||||
import { AvatarOnlineIndicator, VerifiedTick } from "./base-components";
|
||||
@@ -90,7 +91,7 @@ export const AvatarProfilePhoto = ({
|
||||
|
||||
return (
|
||||
<div className={cx("flex size-full items-center justify-center rounded-full bg-tertiary ring-1 ring-secondary_alt", styles[size].content)}>
|
||||
{placeholder || <User01 className={cx("text-fg-quaternary", styles[size].icon)} />}
|
||||
{placeholder || <FontAwesomeIcon icon={faUser} className={cx("text-fg-quaternary", styles[size].icon)} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { type FC, type ReactNode, useState } from "react";
|
||||
import { User01 } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faUser } from "@fortawesome/pro-duotone-svg-icons";
|
||||
import { cx } from "@/utils/cx";
|
||||
import { AvatarOnlineIndicator, VerifiedTick } from "./base-components";
|
||||
|
||||
@@ -90,7 +91,7 @@ export const Avatar = ({
|
||||
return <PlaceholderIcon className={cx("text-fg-quaternary", styles[size].icon)} />;
|
||||
}
|
||||
|
||||
return placeholder || <User01 className={cx("text-fg-quaternary", styles[size].icon)} />;
|
||||
return placeholder || <FontAwesomeIcon icon={faUser} className={cx("text-fg-quaternary", styles[size].icon)} />;
|
||||
};
|
||||
|
||||
const renderBadgeContent = () => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Plus } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faPlus } from "@fortawesome/pro-duotone-svg-icons";
|
||||
import type { ButtonProps as AriaButtonProps } from "react-aria-components";
|
||||
import { Tooltip as AriaTooltip, TooltipTrigger as AriaTooltipTrigger } from "@/components/base/tooltip/tooltip";
|
||||
import { cx } from "@/utils/cx";
|
||||
@@ -26,7 +27,7 @@ export const AvatarAddButton = ({ size, className, title = "Add user", ...props
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<Plus className={cx("text-current transition-inherit-all", sizes[size].icon)} />
|
||||
<FontAwesomeIcon icon={faPlus} className={cx("text-current transition-inherit-all", sizes[size].icon)} />
|
||||
</AriaTooltipTrigger>
|
||||
</AriaTooltip>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import type { FC, ReactNode } from "react";
|
||||
import { isValidElement } from "react";
|
||||
import { ArrowRight } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faArrowRight } from "@fortawesome/pro-duotone-svg-icons";
|
||||
|
||||
const ArrowRight: FC<{ className?: string }> = ({ className }) => <FontAwesomeIcon icon={faArrowRight} className={className} />;
|
||||
import { cx, sortCx } from "@/utils/cx";
|
||||
import { isReactComponent } from "@/utils/is-react-component";
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import type { MouseEventHandler, ReactNode } from "react";
|
||||
import { X as CloseX } from "@untitledui/icons";
|
||||
import type { FC, MouseEventHandler, ReactNode } from "react";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faXmark } from "@fortawesome/pro-duotone-svg-icons";
|
||||
|
||||
const CloseX: FC<{ className?: string }> = ({ className }) => <FontAwesomeIcon icon={faXmark} className={className} />;
|
||||
import { Dot } from "@/components/foundations/dot-icon";
|
||||
import { cx } from "@/utils/cx";
|
||||
import type { BadgeColors, BadgeTypeToColorMap, BadgeTypes, FlagTypes, IconComponentType, Sizes } from "./badge-types";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { X as CloseIcon } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faXmark } from "@fortawesome/pro-duotone-svg-icons";
|
||||
import { Button as AriaButton, type ButtonProps as AriaButtonProps } from "react-aria-components";
|
||||
import { cx } from "@/utils/cx";
|
||||
|
||||
@@ -34,7 +35,7 @@ export const CloseButton = ({ label, className, size = "sm", theme = "light", ..
|
||||
)
|
||||
}
|
||||
>
|
||||
<CloseIcon aria-hidden="true" className={cx("shrink-0 transition-inherit-all", sizes[size].icon)} />
|
||||
<FontAwesomeIcon icon={faXmark} aria-hidden="true" className={cx("shrink-0 transition-inherit-all", sizes[size].icon)} />
|
||||
</AriaButton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { FC, RefAttributes } from "react";
|
||||
import { DotsVertical } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faEllipsisVertical } from "@fortawesome/pro-duotone-svg-icons";
|
||||
import type {
|
||||
ButtonProps as AriaButtonProps,
|
||||
MenuItemProps as AriaMenuItemProps,
|
||||
@@ -144,7 +145,7 @@ const DropdownDotsButton = (props: AriaButtonProps & RefAttributes<HTMLButtonEle
|
||||
)
|
||||
}
|
||||
>
|
||||
<DotsVertical className="size-5 transition-inherit-all" />
|
||||
<FontAwesomeIcon icon={faEllipsisVertical} className="size-5 transition-inherit-all" />
|
||||
</AriaButton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { type ComponentType, type HTMLAttributes, type ReactNode, type Ref, createContext, useContext } from "react";
|
||||
import { HelpCircle, InfoCircle } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCircleQuestion, faCircleExclamation } from "@fortawesome/pro-duotone-svg-icons";
|
||||
import type { InputProps as AriaInputProps, TextFieldProps as AriaTextFieldProps } from "react-aria-components";
|
||||
import { Group as AriaGroup, Input as AriaInput, TextField as AriaTextField } from "react-aria-components";
|
||||
import { HintText } from "@/components/base/input/hint-text";
|
||||
@@ -140,14 +141,15 @@ export const InputBase = ({
|
||||
tooltipClassName,
|
||||
)}
|
||||
>
|
||||
<HelpCircle className="size-4" />
|
||||
<FontAwesomeIcon icon={faCircleQuestion} className="size-4" />
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{/* Invalid icon */}
|
||||
{isInvalid && (
|
||||
<InfoCircle
|
||||
<FontAwesomeIcon
|
||||
icon={faCircleExclamation}
|
||||
className={cx(
|
||||
"pointer-events-none absolute size-4 text-fg-error-secondary",
|
||||
sizes[inputSize].iconTrailing,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { ReactNode, Ref } from "react";
|
||||
import { HelpCircle } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCircleQuestion } from "@fortawesome/pro-duotone-svg-icons";
|
||||
import type { LabelProps as AriaLabelProps } from "react-aria-components";
|
||||
import { Label as AriaLabel } from "react-aria-components";
|
||||
import { Tooltip, TooltipTrigger } from "@/components/base/tooltip/tooltip";
|
||||
@@ -37,7 +38,7 @@ export const Label = ({ isRequired, tooltip, tooltipDescription, className, ...p
|
||||
isDisabled={false}
|
||||
className="cursor-pointer text-fg-quaternary transition duration-200 hover:text-fg-quaternary_hover focus:text-fg-quaternary_hover"
|
||||
>
|
||||
<HelpCircle className="size-4" />
|
||||
<FontAwesomeIcon icon={faCircleQuestion} className="size-4" />
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { FocusEventHandler, PointerEventHandler, RefAttributes, RefObject } from "react";
|
||||
import { useCallback, useContext, useRef, useState } from "react";
|
||||
import { SearchLg as SearchIcon } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faMagnifyingGlass } from "@fortawesome/pro-duotone-svg-icons";
|
||||
import type { ComboBoxProps as AriaComboBoxProps, GroupProps as AriaGroupProps, ListBoxProps as AriaListBoxProps } from "react-aria-components";
|
||||
import { ComboBox as AriaComboBox, Group as AriaGroup, Input as AriaInput, ListBox as AriaListBox, ComboBoxStateContext } from "react-aria-components";
|
||||
import { HintText } from "@/components/base/input/hint-text";
|
||||
@@ -51,7 +52,7 @@ const ComboBoxValue = ({ size, shortcut, placeholder, shortcutClassName, ...othe
|
||||
>
|
||||
{({ isDisabled }) => (
|
||||
<>
|
||||
<SearchIcon className="pointer-events-none size-5 shrink-0 text-fg-quaternary" />
|
||||
<FontAwesomeIcon icon={faMagnifyingGlass} className="pointer-events-none size-5 shrink-0 text-fg-quaternary" />
|
||||
|
||||
<div className="relative flex w-full items-center gap-2">
|
||||
{inputValue && (
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import type { FocusEventHandler, KeyboardEvent, PointerEventHandler, RefAttributes, RefObject } from "react";
|
||||
import type { FC, FocusEventHandler, KeyboardEvent, PointerEventHandler, RefAttributes, RefObject } from "react";
|
||||
import { createContext, useCallback, useContext, useRef, useState } from "react";
|
||||
import { SearchLg } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faMagnifyingGlass } from "@fortawesome/pro-duotone-svg-icons";
|
||||
|
||||
const SearchIcon: FC<{ className?: string }> = ({ className }) => <FontAwesomeIcon icon={faMagnifyingGlass} className={className} />;
|
||||
import { FocusScope, useFilter, useFocusManager } from "react-aria";
|
||||
import type { ComboBoxProps as AriaComboBoxProps, GroupProps as AriaGroupProps, ListBoxProps as AriaListBoxProps, Key } from "react-aria-components";
|
||||
import { ComboBox as AriaComboBox, Group as AriaGroup, Input as AriaInput, ListBox as AriaListBox, ComboBoxStateContext } from "react-aria-components";
|
||||
@@ -317,7 +320,7 @@ export const MultiSelectTagsValue = ({
|
||||
shortcut,
|
||||
placeholder,
|
||||
shortcutClassName,
|
||||
placeholderIcon: Icon = SearchLg,
|
||||
placeholderIcon: Icon = SearchIcon,
|
||||
// Omit this prop to avoid invalid HTML attribute warning
|
||||
isDisabled: _isDisabled,
|
||||
...otherProps
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { isValidElement, useContext } from "react";
|
||||
import { Check } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCheck } from "@fortawesome/pro-duotone-svg-icons";
|
||||
import type { ListBoxItemProps as AriaListBoxItemProps } from "react-aria-components";
|
||||
import { ListBoxItem as AriaListBoxItem, Text as AriaText } from "react-aria-components";
|
||||
import { Avatar } from "@/components/base/avatar/avatar";
|
||||
@@ -79,11 +80,12 @@ export const SelectItem = ({ label, id, value, avatarUrl, supportingText, isDisa
|
||||
</div>
|
||||
|
||||
{state.isSelected && (
|
||||
<Check
|
||||
<FontAwesomeIcon
|
||||
icon={faCheck}
|
||||
aria-hidden="true"
|
||||
className={cx(
|
||||
"ml-auto text-fg-brand-primary",
|
||||
size === "sm" ? "size-4 stroke-[2.5px]" : "size-5",
|
||||
size === "sm" ? "size-4" : "size-5",
|
||||
state.isDisabled && "text-fg-disabled",
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { type SelectHTMLAttributes, useId } from "react";
|
||||
import { ChevronDown } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faChevronDown } from "@fortawesome/pro-duotone-svg-icons";
|
||||
import { HintText } from "@/components/base/input/hint-text";
|
||||
import { Label } from "@/components/base/input/label";
|
||||
import { cx } from "@/utils/cx";
|
||||
@@ -51,9 +52,10 @@ export const NativeSelect = ({ label, hint, options, className, selectClassName,
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<ChevronDown
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronDown}
|
||||
aria-hidden="true"
|
||||
className="pointer-events-none absolute right-3.5 size-5 text-fg-quaternary in-data-input-wrapper:right-0 in-data-input-wrapper:size-4 in-data-input-wrapper:stroke-[2.625px] in-data-input-wrapper:in-data-trailing:in-data-[input-size=sm]:right-3"
|
||||
className="pointer-events-none absolute right-3.5 size-5 text-fg-quaternary in-data-input-wrapper:right-0 in-data-input-wrapper:size-4 in-data-input-wrapper:in-data-trailing:in-data-[input-size=sm]:right-3"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { FC, ReactNode, Ref, RefAttributes } from "react";
|
||||
import { createContext, isValidElement } from "react";
|
||||
import { ChevronDown } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faChevronDown } from "@fortawesome/pro-duotone-svg-icons";
|
||||
import type { SelectProps as AriaSelectProps } from "react-aria-components";
|
||||
import { Button as AriaButton, ListBox as AriaListBox, Select as AriaSelect, SelectValue as AriaSelectValue } from "react-aria-components";
|
||||
import { Avatar } from "@/components/base/avatar/avatar";
|
||||
@@ -92,9 +93,10 @@ const SelectValue = ({ isOpen, isFocused, isDisabled, size, placeholder, placeho
|
||||
<p className={cx("text-md text-placeholder", isDisabled && "text-disabled")}>{placeholder}</p>
|
||||
)}
|
||||
|
||||
<ChevronDown
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronDown}
|
||||
aria-hidden="true"
|
||||
className={cx("ml-auto shrink-0 text-fg-quaternary", size === "sm" ? "size-4 stroke-[2.5px]" : "size-5")}
|
||||
className={cx("ml-auto shrink-0 text-fg-quaternary", size === "sm" ? "size-4" : "size-5")}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { RefAttributes } from "react";
|
||||
import { XClose } from "@untitledui/icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faXmark } from "@fortawesome/pro-duotone-svg-icons";
|
||||
import { Button as AriaButton, type ButtonProps as AriaButtonProps } from "react-aria-components";
|
||||
import { cx } from "@/utils/cx";
|
||||
|
||||
@@ -26,7 +27,7 @@ export const TagCloseX = ({ size = "md", className, ...otherProps }: TagCloseXPr
|
||||
)}
|
||||
{...otherProps}
|
||||
>
|
||||
<XClose className={cx("transition-inherit-all", styles[size].icon)} strokeWidth="3" />
|
||||
<FontAwesomeIcon icon={faXmark} className={cx("transition-inherit-all", styles[size].icon)} />
|
||||
</AriaButton>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user