One Logo Pool Ball
wwwwwwwwwwwwwwwwwww

Icons

One icon component that draws an SF Symbol on iOS and a Material Symbol on Android, colored by role

One.UI.Icon on iOS and Android: SF Symbols and Material Symbols in each color role

One.UI.Icon shows the right icon on each platform and colors it with the platform’s own system colors. You give it an SF Symbol for iOS, a Material Symbol for Android, and any element for web; it renders the one for the current platform.

Color it by role, such as secondary or danger, and the icon follows the system palette, light and dark mode included, with no React re-render.

Usage

import { One } from 'one'
const share = {
ios: <One.iOS.Image systemName="square.and.arrow.up" accessibilityLabel="Share" />,
android: <One.Android.Icon name="share" accessibilityLabel="Share" />,
}
function ShareIcon() {
return <One.UI.Icon icons={share} colorRole="accent" />
}

Keep the icons object at module scope and reuse it. A label makes the icon readable by VoiceOver and TalkBack; without one it is decoration.

How it works

The component picks the element for the platform and clones it with color and size added. It renders nothing of its own.

Passing color instead of colorRole sets the foreground color directly.

API reference

One.UI.IconTypeDescription
icons (required)IconElementsThe element for each platform.
IconElementsThe element for each platform.
colorRoleIconColorRole = "primary"A system color by role. Not with color.
IconColorRole = "primary"A system color by role. Not with color.
colorColorValueA fixed color. Not with colorRole.
ColorValueA fixed color. Not with colorRole.
IconElementsTypeDescription
iosReactElement<ImageProps>A One.iOS.Image element. Anything else throws on iOS.
ReactElement<ImageProps>A One.iOS.Image element. Anything else throws on iOS.
androidReactElement<ComposeIconProps>A One.Android.Icon element. Anything else throws on Android.
ReactElement<ComposeIconProps>A One.Android.Icon element. Anything else throws on Android.
webReactElementRendered as is on web. Without it, web renders nothing.
ReactElementRendered as is on web. Without it, web renders nothing.

Each role maps to these colors:

RoleiOSAndroid
primarylabelonSurface
secondarysecondaryLabelonSurfaceVariant
tertiarytertiaryLabelonSurfaceVariant at 60%
accentThe app accent colorprimary
dangersystemRederror

Platform differences

iOSAndroidWeb
ElementSwiftUI ImageCompose IconYour element
GlyphsSF SymbolsMaterial SymbolsYour own
Default size24 points24 dpYour element’s
Color rolesUIKit system colorsMaterial theme colorsNot applied

Limits and gotchas

Examples

A danger action in a row

import { Pressable, Text } from 'react-native'
import { One } from 'one'
const trash = {
ios: <One.iOS.Image systemName="trash" swiftStyle={{ fontSize: 18 }} />,
android: <One.Android.Icon name="delete" size={18} />,
}
function DeleteRow({ onDelete }: { onDelete: () => void }) {
return (
<Pressable onPress={onDelete} accessibilityRole="button" accessibilityLabel="Delete" style={{ flexDirection: 'row', gap: 8 }}>
<One.UI.Icon icons={trash} colorRole="danger" />
<Text>Delete</Text>
</Pressable>
)
}

The label is on the button, so the icon stays unlabeled and VoiceOver reads “Delete” once.

A brand color on every platform

import { One } from 'one'
const heart = {
ios: <One.iOS.Image systemName="heart.fill" accessibilityLabel="Liked" />,
android: <One.Android.Icon name="favorite" accessibilityLabel="Liked" />,
}
function Liked() {
return <One.UI.Icon icons={heart} color="#E5484D" />
}

A fixed color skips the system palette, so the heart is the same red in light and dark mode.

Edit this page on GitHub.