/** * AnimatedBadge — a status pill whose icon and label roll over when the status * changes. * * A badge that swaps its word between one frame and the next is a badge people * miss. The status is the smallest thing on the screen and usually not the * thing being looked at, so a change with no movement in it registers as * having always said that. Rolling the old glyph out and the new one in is * what makes the change itself visible. * * ```tsx * Deploying * Live * ``` * * ## The roll, and the width * * The outgoing glyph rises out of the pill and fades; the incoming one comes * up from below and settles on a spring, with a slight rotation and scale so * it reads as turning over rather than sliding. Both are clipped to the pill, * which is what keeps the movement inside the badge instead of over whatever * it sits beside. * * The pill's width springs to the new word rather than jumping, because a * badge in a row of them shoves its neighbours as it changes and a jump does * that in one frame. Everything runs on the UI thread. * * That spring covers position as well as width, so a badge set inside a * paragraph slides across a line the text engine has already finished laying * out. Pass `animateLayout={false}` there: the figure still rolls, and the * pill stays where the sentence puts it. * * ## Which change counts as a change * * The label is keyed on what it says, so `"Queued"` to `"Building"` rolls and * a re-render with the same word does not. Where the label is an element * rather than a string, or where two different states share a word, pass * `contentKey` — the badge cannot tell those apart on its own, and without a * key it either animates on every render or never. * * ## Reduced motion * * With the preference on, every part of this is skipped: the glyph and the * label cut over, the pill resizes immediately, and the pulse does not run. * The badge still says what it says, which is the part that mattered. */ import { type ReactNode } from 'react'; import { View, type ViewProps } from 'react-native'; import { type VariantProps } from 'tailwind-variants'; export type AnimatedBadgeStatus = 'neutral' | 'info' | 'success' | 'warning' | 'danger' | 'loading'; export type AnimatedBadgeSize = 'sm' | 'md'; declare const animatedBadgeVariants: import("tailwind-variants").TVReturnType<{ status: { neutral: { root: string; label: string; pulse: string; }; info: { root: string; label: string; pulse: string; }; success: { root: string; label: string; pulse: string; }; warning: { root: string; label: string; pulse: string; }; danger: { root: string; label: string; pulse: string; }; loading: { root: string; label: string; pulse: string; }; }; size: { sm: { root: string; label: string; }; md: { root: string; label: string; }; }; }, { root: string; label: string; /** The pulse's fill, behind the content and inside the same clip. */ pulse: string; /** One clipped column per rolling element, so the two move independently. */ slot: string; }, undefined, { status: { neutral: { root: string; label: string; pulse: string; }; info: { root: string; label: string; pulse: string; }; success: { root: string; label: string; pulse: string; }; warning: { root: string; label: string; pulse: string; }; danger: { root: string; label: string; pulse: string; }; loading: { root: string; label: string; pulse: string; }; }; size: { sm: { root: string; label: string; }; md: { root: string; label: string; }; }; }, { root: string; label: string; /** The pulse's fill, behind the content and inside the same clip. */ pulse: string; /** One clipped column per rolling element, so the two move independently. */ slot: string; }, import("tailwind-variants").TVReturnType<{ status: { neutral: { root: string; label: string; pulse: string; }; info: { root: string; label: string; pulse: string; }; success: { root: string; label: string; pulse: string; }; warning: { root: string; label: string; pulse: string; }; danger: { root: string; label: string; pulse: string; }; loading: { root: string; label: string; pulse: string; }; }; size: { sm: { root: string; label: string; }; md: { root: string; label: string; }; }; }, { root: string; label: string; /** The pulse's fill, behind the content and inside the same clip. */ pulse: string; /** One clipped column per rolling element, so the two move independently. */ slot: string; }, undefined, unknown, unknown, undefined>>; export interface AnimatedBadgeProps extends ViewProps, VariantProps { /** * Which state the badge shows. Anything other than the six statuses is drawn * as `neutral`, with a warning in development — map a boolean or a state of * your own onto one first, as in `status={synced ? 'success' : 'neutral'}`. */ status?: AnimatedBadgeStatus; size?: AnimatedBadgeSize; /** The word. Changing it rolls the old one out and the new one in. */ children?: ReactNode; /** A glyph of your own, in place of the status's. */ icon?: ReactNode; /** Whether a glyph is drawn at all. */ showIcon?: boolean; /** * A slow swell behind the content, for a status that is still happening. * On by default while `status` is `loading`, and off otherwise — pass it * explicitly for a state of your own that is also still running. */ pulse?: boolean; /** * What counts as a change, when the label cannot say. The label is keyed on * its own text, so this is only needed where it is an element rather than a * string, or where two states share a word. */ contentKey?: string | number; /** * Whether the pill springs to its new size, and to its new place when what * is around it moves. * * On by default, which is what a badge standing on its own wants: growing to * a longer word in one frame shoves whatever is beside it. * * Turn it off for a badge set in a line of text. The animation covers * position as well as size, and the words around it are placed by the text * engine and simply appear where they now belong — so an animating badge * slides across a sentence that has already finished moving, which reads as * the badge coming loose from the line rather than as the figure changing. */ animateLayout?: boolean; className?: string; labelClassName?: string; } export declare const AnimatedBadge: import("react").ForwardRefExoticComponent>; export {}; //# sourceMappingURL=index.d.ts.map