Rating
The Rating component displays a visual star rating, typically used to show product ratings, review scores, or user satisfaction levels. The current implementation is read-only.
Installation
npm install @naturacosmeticos/natds-web
Usage
import { Rating } from '@naturacosmeticos/natds-web';
function ProductRating() {
return <Rating rate={4} size="small" />;
}
Rating Sizes
Small (Default)
Compact rating for inline display:
<Rating rate={3.5} size="small" />
Standard
Standard size for general use:
<Rating rate={4} size="standard" />
Semi
Larger rating for emphasis:
<Rating rate={5} size="semi" />
SemiX
Extra large for high visibility:
<Rating rate={4.5} size="semix" />
Product Card Example
import { Card, CardContent, Typography, Rating } from '@naturacosmeticos/natds-web';
function ProductCard({ product }) {
return (
<Card>
<CardContent>
<img src={product.image} alt={product.name} style={{ width: '100%' }} />
<Typography variant="h6">{product.name}</Typography>
<Typography variant="body2" color="textSecondary">
{product.description}
</Typography>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 8 }}>
<Rating rate={product.rating} size="small" />
<Typography variant="body2" color="textSecondary">
({product.reviewCount} reviews)
</Typography>
</div>
<Typography variant="h6" style={{ marginTop: 8 }}>
${product.price}
</Typography>
</CardContent>
</Card>
);
}
Review List Example
function ReviewList({ reviews }) {
return (
<div>
{reviews.map((review) => (
<div key={review.id} style={{ marginBottom: 24, padding: 16, border: '1px solid #e0e0e0' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 8 }}>
<div>
<Typography variant="subtitle1">{review.author}</Typography>
<Typography variant="caption" color="textSecondary">
{review.date}
</Typography>
</div>
<Rating rate={review.rating} size="small" />
</div>
<Typography variant="h6" style={{ marginBottom: 8 }}>
{review.title}
</Typography>
<Typography variant="body2">
{review.comment}
</Typography>
</div>
))}
</div>
);
}
Rating Summary
function RatingSummary({ ratings }) {
const totalRatings = ratings.reduce((sum, r) => sum + r.count, 0);
const averageRating = ratings.reduce((sum, r) => sum + (r.stars * r.count), 0) / totalRatings;
return (
<div style={{ padding: 24 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 24 }}>
<div>
<Typography variant="h3">{averageRating.toFixed(1)}</Typography>
<Rating rate={averageRating} size="standard" />
<Typography variant="body2" color="textSecondary">
{totalRatings} ratings
</Typography>
</div>
</div>
{[5, 4, 3, 2, 1].map((stars) => {
const rating = ratings.find(r => r.stars === stars) || { count: 0 };
const percentage = (rating.count / totalRatings) * 100;
return (
<div key={stars} style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
<Typography variant="body2" style={{ width: 30 }}>
{stars}★
</Typography>
<div style={{
flex: 1,
height: 8,
backgroundColor: '#e0e0e0',
borderRadius: 4
}}>
<div style={{
width: `${percentage}%`,
height: '100%',
backgroundColor: '#ffa000',
borderRadius: 4
}} />
</div>
<Typography variant="body2" style={{ width: 50 }}>
{rating.count}
</Typography>
</div>
);
})}
</div>
);
}
Different Rating Values
function RatingExamples() {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
<div>
<Typography variant="body2">No rating (0 stars)</Typography>
<Rating rate={0} />
</div>
<div>
<Typography variant="body2">Low rating (1.5 stars)</Typography>
<Rating rate={1.5} />
</div>
<div>
<Typography variant="body2">Average rating (3 stars)</Typography>
<Rating rate={3} />
</div>
<div>
<Typography variant="body2">Good rating (4 stars)</Typography>
<Rating rate={4} />
</div>
<div>
<Typography variant="body2">Perfect rating (5 stars)</Typography>
<Rating rate={5} />
</div>
</div>
);
}
With Text Labels
function LabeledRating({ rate }) {
const getRatingLabel = (rating) => {
if (rating >= 4.5) return 'Excellent';
if (rating >= 3.5) return 'Good';
if (rating >= 2.5) return 'Average';
if (rating >= 1.5) return 'Poor';
return 'Very Poor';
};
return (
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<Rating rate={rate} size="small" />
<Typography variant="body2">
{rate.toFixed(1)} - {getRatingLabel(rate)}
</Typography>
</div>
);
}
Product Comparison
function ProductComparison({ products }) {
return (
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16 }}>
{products.map((product) => (
<Card key={product.id}>
<CardContent>
<img src={product.image} alt={product.name} style={{ width: '100%' }} />
<Typography variant="h6">{product.name}</Typography>
<div style={{ margin: '8px 0' }}>
<Rating rate={product.rating} size="standard" />
</div>
<Typography variant="body2" color="textSecondary">
{product.rating} ({product.reviews} reviews)
</Typography>
<Typography variant="h6" style={{ marginTop: 8 }}>
${product.price}
</Typography>
</CardContent>
</Card>
))}
</div>
);
}
Props
The rating value to display (0-5). Supports decimal values for partial stars.
size
'small' | 'standard' | 'semi' | 'semix'
default:"'small'"
The size of the rating stars.
The input id property for the component.
CSS class name to apply to the component.
Inline styles to apply to the component.
Component Behavior
- The Rating component is read-only and cannot be interacted with
- Displays exactly 5 stars
- Supports decimal values for partial star fills
- Uses the Natura icon set for star icons
- Automatically handles star fill based on the
rate prop
Best Practices
- Use consistent sizing across similar contexts (e.g., all product cards)
- Always display the numeric rating alongside the stars for clarity
- Include the number of reviews/ratings to provide context
- Use small size for compact layouts and lists
- Use larger sizes for emphasis on detail pages
- Consider showing 0 stars vs hiding the rating when there are no reviews
- Round displayed numbers appropriately (e.g., 4.67 → 4.7)
Accessibility
- The component renders read-only rating visualization
- Always pair with text that states the numeric rating
- Include review count for context
- Ensure sufficient color contrast for star icons
- Consider adding
aria-label for screen readers (e.g., “Rated 4 out of 5 stars”)
Common Patterns
Rating with Count
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<Rating rate={4.3} size="small" />
<Typography variant="body2">4.3 (127)</Typography>
</div>
Rating in List Item
<ListItem>
<ListItemText
primary="Product Name"
secondary={
<>
<Rating rate={4.5} size="small" />
<span style={{ marginLeft: 8 }}>4.5 stars</span>
</>
}
/>
</ListItem>
Styling
The Rating component uses design tokens from the Natura design system for consistent styling. The star icons automatically adapt to your theme’s color palette.
Related Components
- Icon - Used internally for star icons
- Typography - For rating labels and counts