Files
web/packages/design-system/lib/components/Icons/MaterialIcon/MaterialSymbol/MaterialSymbol.tsx
Rasmus Langvad d0546926a9 Merged in fix/3697-prettier-configs (pull request #3396)
fix(SW-3691): Setup one prettier config for whole repo

* Setup prettierrc in root and remove other configs


Approved-by: Joakim Jäderberg
Approved-by: Linus Flood
2026-01-07 12:45:50 +00:00

102 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// This is adapted from https://github.com/edjonesdev/react-material-symbols
// since it doesn't support React 19 and is not maintained anymore.
// We should probably move to a different solution in the future.
import type { ElementType, CSSProperties, ReactElement, Ref } from "react"
import type {
MaterialSymbolWeight,
PolymorphicComponentProps,
SymbolCodepoints,
} from "./types"
import { cx } from "class-variance-authority"
export type { MaterialSymbolWeight, SymbolCodepoints } from "./types"
export type MaterialSymbolProps = {
/** Required. The name of the icon to render. */
icon: SymbolCodepoints
/** Default `false`.
*
* Fill gives you the ability to modify the default icon style. A single icon can render both unfilled and filled states. */
fill?: boolean
/** Weight defines the symbols stroke weight, with a range of weights between thin (100) and heavy (900). Weight can also affect the overall size of the symbol. */
weight?: MaterialSymbolWeight
/** Weight and grade affect a symbols thickness. Adjustments to grade are more granular than adjustments to weight and have a small impact on the size of the symbol. */
grade?: number
/** Default `'inherit'`.
*
* Size defines the icon width and height in pixels. For the image to look the same at different sizes, the stroke weight (thickness) changes as the icon size scales. */
size?: number
/** Default `'inherit'`
*
* Color accepts key values (`'red'`, `'blue'`, `'indigo'`, etc.), `<hex-color>`, `<rgb()>`, `<hsl()>` and `<hwb()>` values. */
color?: CSSProperties["color"]
className?: string
style?: CSSProperties
}
export type PolymorphicMaterialSymbolProps<C extends ElementType> =
PolymorphicComponentProps<C, MaterialSymbolProps>
export const MaterialSymbol = (<C extends ElementType>(
{
icon,
onClick,
as,
weight,
fill = false,
grade,
size,
style: propStyle,
color,
className,
...props
}: PolymorphicMaterialSymbolProps<C>,
ref: Ref<C>
): ReactElement => {
const Component =
onClick !== undefined ? "button" : ((as as ElementType) ?? "span")
const style = { color, ...propStyle }
if (fill)
style.fontVariationSettings = [style.fontVariationSettings, '"FILL" 1']
.filter(Boolean)
.join(", ")
if (weight)
style.fontVariationSettings = [
style.fontVariationSettings,
`"wght" ${weight}`,
]
.filter(Boolean)
.join(", ")
if (grade)
style.fontVariationSettings = [
style.fontVariationSettings,
`"GRAD" ${grade}`,
]
.filter(Boolean)
.join(", ")
if (size) {
style.fontVariationSettings = [
style.fontVariationSettings,
`"opsz" ${size}`,
]
.filter(Boolean)
.join(", ")
style.fontSize = size
}
return (
<Component
{...props}
ref={ref}
style={style}
onClick={onClick}
className={cx("material-symbols", className)}
>
{icon}
</Component>
)
}) as <C extends ElementType>(
props: PolymorphicMaterialSymbolProps<C>
) => ReactElement