Button
tetra-ui/buttonFreeComponent
A component to display a button and allows a user to trigger an action.
Live preview
live · rendered by the registry
Rendered by tetra-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://tetra-ui.com/r/button.jsonSource
1import { cva, type VariantProps } from "class-variance-authority";2import {3 Children,4 cloneElement,5 createContext,6 useContext,7 useMemo,8} from "react";9import { ActivityIndicator, Pressable, Text } from "react-native";10import { cn } from "@/lib/utils";1112// Types13type InternalButtonContextType = VariantProps<typeof buttonVariants> & {14 busy?: boolean;15 disabled?: boolean;16};1718type ButtonChildProps = {19 children: React.ReactNode;20 className?: string;21};2223export type ButtonProps = React.ComponentProps<typeof Pressable> &24 InternalButtonContextType & {25 children: React.ReactNode;26 };2728// Context29const ButtonContext = createContext<InternalButtonContextType | null>(null);3031const useButtonContext = () => {32 const context = useContext(ButtonContext);33 if (!context) {34 throw new Error("useButtonContext must be used within a Button component");35 }36 return context;37};3839// Components40export const Button = ({41 className,42 variant,43 size,44 busy,45 disabled,46 children,47 accessibilityRole = "button",48 ...props49}: ButtonProps) => {50 const ctx = useMemo(() => {51 return {52 busy,53 disabled,54 size,55 variant,56 };57 }, [variant, size, busy, disabled]);5859 return (60 <ButtonContext.Provider value={ctx}>61 <Pressable62 accessibilityRole={accessibilityRole}63 accessibilityState={{ busy, disabled }}64 className={cn(65 buttonVariants({ className, size, variant }),66 disabled && "opacity-50"67 )}68 disabled={disabled || busy}69 {...props}70 >71 {Children.map(children, (child) => {72 if (typeof child === "string") {73 if (size === "icon") {74 // Icon buttons shouldn't render text75 return null;76 }77 return <ButtonText>{child}</ButtonText>;78 }7980 return child;81 })}82 {busy ? <ButtonSpinner /> : null}83 </Pressable>84 </ButtonContext.Provider>85 );86};8788export const ButtonText = (props: ButtonChildProps) => {89 const ctx = useButtonContext();9091 return (92 <Text93 {...props}94 className={cn(95 buttonTextVariants(ctx),96 ctx.busy && "opacity-0",97 props.className98 )}99 />100 );101};102103export const ButtonIcon = ({ children, ...props }: ButtonChildProps) => {104 const ctx = useButtonContext();105106 const child = Children.only(children);107108 if (!child) {109 if (__DEV__) {110// … truncated
Files it writes
More from tetra-ui
All 41 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | tetra-ui | Components | Free | 1 dep | |
| Action Inputaction-input | tetra-ui | Components | Free | no deps | |
| Alertalert | tetra-ui | Components | Free | no deps | |
| Avataravatar | tetra-ui | Components | Free | no deps | |
| Badgebadge | tetra-ui | Components | Free | no deps | |
| Bottom Sheetbottom-sheet | tetra-ui | Components | Free | 4 deps · 7 files | |
| Cardcard | tetra-ui | Components | Free | no deps | |
| Checkboxcheckbox | tetra-ui | Components | Free | 1 dep |
