feat(client): add Button.Icon subcomponent (#70)

Introduce Button.Icon to enforce consistent icon styling
(size, theme-aware color) instead of hardcoding Feather
props at each call site. Update showcase and json-render
registry to use it.

Co-authored-by: Ona <no-reply@ona.com>
This commit is contained in:
2026-03-14 00:39:59 +00:00
committed by GitHub
parent 45fa539d3e
commit ec083c3c77
3 changed files with 21 additions and 13 deletions

View File

@@ -1,4 +1,3 @@
import Feather from "@expo/vector-icons/Feather"
import { View } from "react-native"
import tw from "twrnc"
@@ -15,22 +14,22 @@ function ButtonShowcase() {
<Button
style={tw`self-start`}
label="Add item"
leadingIcon={<Feather name="plus" size={18} color="#e7e5e4" />}
leadingIcon={<Button.Icon name="plus" />}
/>
</Section>
<Section title="Trailing icon">
<Button
style={tw`self-start`}
label="Next"
trailingIcon={<Feather name="arrow-right" size={18} color="#e7e5e4" />}
trailingIcon={<Button.Icon name="arrow-right" />}
/>
</Section>
<Section title="Both icons">
<Button
style={tw`self-start`}
label="Download"
leadingIcon={<Feather name="download" size={18} color="#e7e5e4" />}
trailingIcon={<Feather name="chevron-down" size={18} color="#e7e5e4" />}
leadingIcon={<Button.Icon name="download" />}
trailingIcon={<Button.Icon name="chevron-down" />}
/>
</Section>
</View>

View File

@@ -1,8 +1,19 @@
import Feather from "@expo/vector-icons/Feather"
import { type PressableProps, Pressable, View } from "react-native"
import tw from "twrnc"
import { SansSerifText } from "./sans-serif-text"
type FeatherIconName = React.ComponentProps<typeof Feather>["name"]
type ButtonIconProps = {
name: FeatherIconName
}
function ButtonIcon({ name }: ButtonIconProps) {
return <Feather name={name} size={18} color={tw.color("text-stone-100 dark:text-stone-200")} />
}
type ButtonProps = Omit<PressableProps, "children"> & {
label: string
leadingIcon?: React.ReactNode
@@ -12,7 +23,7 @@ type ButtonProps = Omit<PressableProps, "children"> & {
export function Button({ style, label, leadingIcon, trailingIcon, ...props }: ButtonProps) {
const hasIcons = leadingIcon != null || trailingIcon != null
const textElement = <SansSerifText style={tw`text-stone-200 font-medium`}>{label}</SansSerifText>
const textElement = <SansSerifText style={tw`text-stone-100 dark:text-stone-200 font-medium`}>{label}</SansSerifText>
return (
<Pressable style={[tw`rounded-full bg-teal-600 px-4 py-3 w-fit`, style]} {...props}>
@@ -28,3 +39,5 @@ export function Button({ style, label, leadingIcon, trailingIcon, ...props }: Bu
</Pressable>
)
}
Button.Icon = ButtonIcon