Empty
Icon, title, description and an optional action slot. The fallback surface for conversation, file-tree, sources, attachments and test-results.
- v0.2.1
- ui
- nativewind
- uniwind
- runs in Expo Go
Install
npx @react-native-reusables/cli@latest add https://rnraielements.com/r/nativewind/empty.jsonnpx @react-native-reusables/cli@latest add https://rnraielements.com/r/uniwind/empty.jsonDependencies
No required npm packages — this item installs through the registry dependencies below.
https://reactnativereusables.com/r/nativewind/text.json |
https://reactnativereusables.com/r/nativewind/icon.json |
https://reactnativereusables.com/r/uniwind/text.json |
https://reactnativereusables.com/r/uniwind/icon.json |
AI SDK peers:ai@^7.0.89@ai-sdk/react@^4.0.92
Source
import { Text, TextClassContext } from '@/registry/nativewind/components/ui/text';
import { cn } from '@/registry/nativewind/lib/utils';
import type { LucideIcon } from 'lucide-react-native';
import { Icon } from '@/registry/nativewind/components/ui/icon';
import { View, type ViewProps } from 'react-native';
/**
* Empty — icon + title + description + optional action.
*
* RNR ships no `empty`. This is AI Elements' ConversationEmptyState generalised: the same
* surface is the fallback for file-tree, sources, attachments and test-results, so it is
* built once and reused rather than re-invented per component.
*
* Declares no token. Every value is an RNR role.
*/
function Empty({ className, ...props }: ViewProps) {
return (
<View
className={cn('flex-1 items-center justify-center gap-3 p-8', className)}
accessibilityRole="summary"
{...props}
/>
);
}
function EmptyIcon({ as, className }: { as: LucideIcon; className?: string }) {
// Via RNR's Icon wrapper — a raw Lucide element silently ignores className.
return <Icon as={as} size={32} className={cn('text-muted-foreground', className)} />;
}
function EmptyTitle({ className, ...props }: React.ComponentProps<typeof Text>) {
return <Text className={cn('text-center text-base font-medium text-foreground', className)} {...props} />;
}
function EmptyDescription({ className, ...props }: React.ComponentProps<typeof Text>) {
return (
<Text className={cn('max-w-sm text-center text-sm text-muted-foreground', className)} {...props} />
);
}
/** Action slot. TextClassContext so a Button's label inherits without per-call classes. */
function EmptyActions({ className, ...props }: ViewProps) {
return (
<TextClassContext.Provider value="text-sm font-medium">
<View className={cn('flex-row items-center gap-2 pt-1', className)} {...props} />
</TextClassContext.Provider>
);
}
export { Empty, EmptyActions, EmptyDescription, EmptyIcon, EmptyTitle };
Theming
Themed via text-muted-foreground, text-foreground.
Usage
() => (
<Empty>
<EmptyIcon icon={SearchIcon} />
<EmptyTitle>
<Text className="text-sm font-medium text-foreground">No matching items</Text>
</EmptyTitle>
<EmptyDescription>
<Text className="text-sm text-muted-foreground">
Nothing in the 56-item set matches that filter.
</Text>
</EmptyDescription>
</Empty>
)