Suggestion
Starter prompts and follow-up chips a user taps instead of typing. Horizontal scrolling row; onPress receives the suggestion string.
- v0.2.1
- component
- nativewind
- uniwind
- runs in Expo Go
Install
npx @react-native-reusables/cli@latest add https://rnraielements.com/r/nativewind/suggestion.jsonnpx @react-native-reusables/cli@latest add https://rnraielements.com/r/uniwind/suggestion.jsonDependencies
No required npm packages — this item installs through the registry dependencies below.
https://reactnativereusables.com/r/nativewind/button.json |
https://reactnativereusables.com/r/nativewind/text.json |
https://reactnativereusables.com/r/uniwind/button.json |
https://reactnativereusables.com/r/uniwind/text.json |
AI SDK peers:ai@^7.0.89@ai-sdk/react@^4.0.92
Source
import { Button } from '@/registry/nativewind/components/ui/button';
import { Text } from '@/registry/nativewind/components/ui/text';
import { cn } from '@/registry/nativewind/lib/utils';
import { ScrollView, type ScrollViewProps } from 'react-native';
/**
* Suggestion — starter prompts and follow-up chips a user taps instead of typing.
*
* Ported from Vercel AI Elements. Behaviors preserved from the web original:
* - the row SCROLLS horizontally and never wraps; layout does not reflow
* - `onPress` receives the suggestion STRING, not an event, so the caller can send it
* directly without unwrapping anything
*
* Deliberate native adaptations:
* - the web `ScrollArea` exists to restyle browser scrollbar chrome. React Native has no
* scrollbar chrome, so a plain horizontal ScrollView IS the scroll area. No primitive.
* - the web chips carry `hover:` only. On touch that renders identically at rest and is
* dead under a thumb, so press feedback comes from RNR Button's own `active:` variants.
* - `onClick` is `onPress`, the React Native name.
*
* Styling is entirely RNR's: this file declares no token and no colour.
*/
export type SuggestionsProps = ScrollViewProps & {
className?: string;
contentClassName?: string;
};
function Suggestions({ className, contentClassName, children, ...props }: SuggestionsProps) {
return (
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
keyboardShouldPersistTaps="handled"
className={cn('w-full', className)}
contentContainerClassName={cn('flex-row gap-2 px-1 py-2', contentClassName)}
{...props}
>
{children}
</ScrollView>
);
}
export type SuggestionProps = Omit<React.ComponentProps<typeof Button>, 'onPress' | 'children'> & {
/** The prompt text. Also what `onPress` receives. */
suggestion: string;
/** Receives the suggestion string, not a press event. */
onPress?: (suggestion: string) => void;
};
function Suggestion({
suggestion,
onPress,
className,
variant = 'outline',
size = 'sm',
...props
}: SuggestionProps) {
return (
<Button
variant={variant}
size={size}
className={cn('rounded-full', className)}
onPress={() => onPress?.(suggestion)}
accessibilityRole="button"
accessibilityLabel={suggestion}
{...props}
>
<Text>{suggestion}</Text>
</Button>
);
}
export { Suggestion, Suggestions };
Props
| Name | Type | Default | Description |
|---|---|---|---|
| suggestion | string | — | The prompt text. Also what `onPress` receives. |
| onPress | ((suggestion: string) => void) | undefined | — | Receives the suggestion string, not a press event. |
Theming
No semantic theme classes in source — appearance follows the consumer theme and component defaults.
Usage
() => (
<Suggestions>
<Text className="rounded-full border border-border bg-background px-3 py-1.5 text-sm text-foreground">
Install the full 56-item set
</Text>
<Text className="rounded-full border border-border bg-background px-3 py-1.5 text-sm text-foreground">
Show the engine parity proof
</Text>
<Text className="rounded-full border border-border bg-background px-3 py-1.5 text-sm text-foreground">
Why does terminal stay dark in light mode?
</Text>
</Suggestions>
)