/**
* 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