This is a submission for the KendoReact Free Components Challenge.
What I Built
Here is the list of all KendoReact free components used in the previous App.jsx
:
1️⃣ AppBar - Used for the top navigation bar displaying the store title and user actions.
2️⃣ Avatar - Displays the user’s profile image in the AppBar.
3️⃣ PanelBar - Provides collapsible panels for categories, sizes, and colors in the filter section.
4️⃣ PanelBarItem - Individual items within the PanelBar for organizing filter options.
5️⃣ Card - Used for displaying cart contents, collections, and other boxed content.
6️⃣ GridLayout - Organizes products in a grid layout within ExpansionPanels.
7️⃣ GridLayoutItem - Defines individual items within the GridLayout for product cards.
8️⃣ StackLayout - Aligns elements horizontally or vertically (e.g., in filters, footer).
9️⃣ TabStrip - Creates tabs for Shop, Wishlist, and Profile sections.
🔟 TabStripTab - Individual tabs within the TabStrip component.
1️⃣1️⃣ Drawer - Side navigation menu for additional options like Home and Contact.
1️⃣2️⃣ DrawerItem - Items within the Drawer for navigation links.
1️⃣3️⃣ ExpansionPanel - Collapsible sections for displaying multiple product collections.
1️⃣4️⃣ Breadcrumb - Shows navigation path (e.g., Home > Shop > Category).
1️⃣5️⃣ BottomNavigation - Footer navigation bar with Home, Cart, and Profile links.
1️⃣6️⃣ BottomNavigationItem - Individual items in the BottomNavigation.
1️⃣7️⃣ TileLayout - Used for the promotional banner section.
1️⃣8️⃣ TileLayoutItem - Individual tiles within the TileLayout.
1️⃣9️⃣ Menu - Dropdown menu for additional navigation options (e.g., Shop More).
2️⃣0️⃣ MenuItem - Items within the Menu component.
2️⃣1️⃣ Button - General-purpose buttons for actions like adding to cart, submitting forms, etc.
2️⃣2️⃣ ButtonGroup - Groups buttons together (e.g., in Grid actions).
2️⃣3️⃣ DropDownList - Dropdown selection for sorting, sizes, and colors.
2️⃣4️⃣ AutoComplete - Search input with autocomplete suggestions from product names.
2️⃣5️⃣ NumericTextBox - Numeric input for quantity selection and review ratings.
2️⃣6️⃣ Input - Text input for search, login, shipping, and payment fields.
2️⃣7️⃣ Switch - Toggle for showing/hiding advanced filters.
2️⃣8️⃣ Checkbox - Checkbox for advanced filter options (e.g., "In Stock Only").
2️⃣9️⃣ RadioButton - Individual radio buttons within RadioButtonGroup.
3️⃣0️⃣ RadioButtonGroup - Group of radio buttons for filter options (e.g., New/Sale).
3️⃣1️⃣ Slider - Slider for selecting a price range in advanced filters.
3️⃣2️⃣ TextArea - Text area for writing reviews or contact messages.
3️⃣3️⃣ Calendar - Calendar picker for selecting delivery dates (not used in final UI but imported).
3️⃣4️⃣ DatePicker - Date picker for selecting delivery dates (not used in final UI but imported).
3️⃣5️⃣ DateInput - Manual date input field (not used in final UI but imported).
3️⃣6️⃣ DateTimePicker - Date and time picker for delivery scheduling.
3️⃣7️⃣ Notification - Success notifications for adding to cart or placing an order.
3️⃣8️⃣ Grid - Tabular display for products, cart, wishlist, and order history.
3️⃣9️⃣ GridColumn - Defines columns within the Grid component.
4️⃣0️⃣ Tooltip - Hover tooltip for filter information button.
4️⃣1️⃣ Popover - Popover component (imported but not used in final UI).
4️⃣2️⃣ ListBox - List selection for categories, sizes, and colors in the PanelBar.
4️⃣3️⃣ Badge - Badge for displaying cart count (not used in final UI but imported).
4️⃣4️⃣ Loader - Loading indicator during checkout processing.
4️⃣5️⃣ Skeleton - Placeholder UI component (not used in final UI but imported).
4️⃣6️⃣ ProgressBar - Progress bar showing cart fill level.
4️⃣7️⃣ Dialog - Modal dialogs for login, product details, checkout, order history, wishlist, and contact form.
4️⃣8️⃣ SvgIcon - SVG icons for Home, User, Cart, Calendar, Email, Star, Search, Menu, Close, LinkedIn, GitHub, Twitter, and Globe.
Total Components Used: 48
App.jsx
import React, { useState } from 'react';
import './App.css';
// KendoReact Free Components Imports (Expanded to Use More)
import {
AppBar,
Avatar,
PanelBar,
PanelBarItem,
Card,
GridLayout,
GridLayoutItem,
StackLayout,
TabStrip,
TabStripTab,
Drawer,
DrawerItem,
ExpansionPanel,
Breadcrumb,
BottomNavigation,
BottomNavigationItem,
TileLayout,
TileLayoutItem,
Menu,
MenuItem,
} from '@progress/kendo-react-layout';
import { Button, ButtonGroup } from '@progress/kendo-react-buttons';
import { DropDownList, AutoComplete } from '@progress/kendo-react-dropdowns';
import { NumericTextBox, Input, Switch, Checkbox, RadioButton, RadioButtonGroup, Slider, TextArea } from '@progress/kendo-react-inputs';
import { Calendar, DatePicker, DateInput, DateTimePicker } from '@progress/kendo-react-dateinputs';
import { Notification } from '@progress/kendo-react-notification';
import { Grid, GridColumn } from '@progress/kendo-react-grid';
import { Tooltip, Popover } from '@progress/kendo-react-tooltip';
import { ListBox } from '@progress/kendo-react-listbox';
import { Badge, Loader, Skeleton } from '@progress/kendo-react-indicators';
import { ProgressBar } from '@progress/kendo-react-progressbars';
import { Dialog } from '@progress/kendo-react-dialogs';
import { SvgIcon } from '@progress/kendo-react-common';
import {
homeIcon,
userIcon,
cartIcon,
calendarIcon,
emailIcon,
starIcon,
searchIcon,
menuIcon,
closeIcon,
linkedinIcon,
githubIcon,
twitterIcon,
globeIcon,
} from '@progress/kendo-svg-icons';
function App() {
// Sample T-Shirt Products (Expanded Massively)
const sampleProducts = Array.from({ length: 100 }, (_, i) => ({
id: i + 1,
name: `T-Shirt ${i + 1}`,
price: (15 + i * 0.5).toFixed(2),
category: ['Men', 'Women', 'Kids'][i % 3],
stock: Math.floor(Math.random() * 100),
description: `A premium T-shirt for ${['casual wear', 'sports', 'style'][i % 3]}.`,
rating: (3.5 + Math.random() * 1.5).toFixed(1),
image: `https://via.placeholder.com/150?text=T-Shirt+${i + 1}`,
sizes: ['XS', 'S', 'M', 'L', 'XL', 'XXL'],
colors: ['Red', 'Blue', 'Green', 'Black', 'White'],
}));
// Categories and Other Data
const categories = ['All', 'Men', 'Women', 'Kids'];
const sortOptions = ['Price Low to High', 'Price High to Low', 'Rating High to Low'];
const sizes = ['XS', 'S', 'M', 'L', 'XL', 'XXL'];
const colors = ['Red', 'Blue', 'Green', 'Black', 'White'];
// State Management (Expanded)
const [products] = useState(sampleProducts);
const [selectedCategory, setSelectedCategory] = useState('All');
const [cart, setCart] = useState([]);
const [showNotification, setShowNotification] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
const [sortOption, setSortOption] = useState('Price Low to High');
const [quantity, setQuantity] = useState(1);
const [deliveryDate, setDeliveryDate] = useState(null);
const [showFilters, setShowFilters] = useState(false);
const [user, setUser] = useState({ name: 'Guest', email: '', avatar: 'https://via.placeholder.com/50' });
const [showLogin, setShowLogin] = useState(false);
const [loginEmail, setLoginEmail] = useState('');
const [loginPassword, setLoginPassword] = useState('');
const [showCheckout, setShowCheckout] = useState(false);
const [checkoutStep, setCheckoutStep] = useState(0);
const [shippingInfo, setShippingInfo] = useState({ address: '', city: '', zip: '', country: '' });
const [paymentInfo, setPaymentInfo] = useState({ cardNumber: '', expiry: '', cvv: '', cardHolder: '' });
const [orderHistory, setOrderHistory] = useState([]);
const [showOrderHistory, setShowOrderHistory] = useState(false);
const [selectedProduct, setSelectedProduct] = useState(null);
const [showProductDetails, setShowProductDetails] = useState(false);
const [reviews, setReviews] = useState({});
const [drawerExpanded, setDrawerExpanded] = useState(false);
const [tabSelected, setTabSelected] = useState(0);
const [showWishlist, setShowWishlist] = useState(false);
const [wishlist, setWishlist] = useState([]);
const [showContactForm, setShowContactForm] = useState(false);
const [contactForm, setContactForm] = useState({ name: '', email: '', message: '' });
const [promoCode, setPromoCode] = useState('');
const [discount, setDiscount] = useState(0);
const [loading, setLoading] = useState(false);
// Handlers
const handleAddToCart = (item) => {
setCart((prev) => [...prev, { ...item, quantity }]);
setShowNotification(true);
setTimeout(() => setShowNotification(false), 3000);
};
const handleRemoveFromCart = (index) => {
setCart((prev) => prev.filter((_, i) => i !== index));
};
const handleAddToWishlist = (item) => {
setWishlist((prev) => [...prev, item]);
};
const handleRemoveFromWishlist = (index) => {
setWishlist((prev) => prev.filter((_, i) => i !== index));
};
const handleLogin = () => {
if (loginEmail && loginPassword) {
setUser({ name: loginEmail.split('@')[0], email: loginEmail, avatar: 'https://via.placeholder.com/50' });
setShowLogin(false);
}
};
const handleCheckout = () => {
if (checkoutStep === 0 && shippingInfo.address && shippingInfo.city && shippingInfo.zip) {
setCheckoutStep(1);
} else if (checkoutStep === 1 && paymentInfo.cardNumber && paymentInfo.expiry && paymentInfo.cvv) {
setCheckoutStep(2);
} else if (checkoutStep === 2) {
setLoading(true);
setTimeout(() => {
const total = cart.reduce((sum, item) => sum + item.price * item.quantity, 0);
const finalTotal = total - (total * discount) / 100;
const order = {
id: Date.now(),
items: [...cart],
total: finalTotal.toFixed(2),
date: new Date().toLocaleDateString(),
status: 'Pending',
shipping: { ...shippingInfo },
payment: { ...paymentInfo },
};
setOrderHistory((prev) => [...prev, order]);
setCart([]);
setShowCheckout(false);
setCheckoutStep(0);
setShowNotification(true);
setLoading(false);
setTimeout(() => setShowNotification(false), 3000);
}, 2000);
}
};
const handleViewProduct = (item) => {
setSelectedProduct(item);
setShowProductDetails(true);
};
const handleAddReview = (productId, comment, rating) => {
setReviews((prev) => ({
...prev,
[productId]: [...(prev[productId] || []), { user: user.name, comment, rating }],
}));
};
const handleApplyPromo = () => {
if (promoCode === 'SAVE20') setDiscount(20);
else if (promoCode === 'SAVE10') setDiscount(10);
else setDiscount(0);
};
// Filtering and Sorting
const filteredProducts = searchQuery
? products.filter((p) => p.name.toLowerCase().includes(searchQuery.toLowerCase()))
: selectedCategory === 'All'
? products
: products.filter((p) => p.category === selectedCategory);
const sortedProducts = [...filteredProducts].sort((a, b) => {
if (sortOption === 'Price Low to High') return a.price - b.price;
if (sortOption === 'Price High to Low') return b.price - a.price;
return b.rating - a.rating;
});
return (
{/* AppBar */}
setDrawerExpanded(!drawerExpanded)} />
setShowLogin(true)} />
T-Shirt Mega Store
setShowWishlist(true)}>
Wishlist ({wishlist.length})
setShowOrderHistory(true)}>
Orders
{cart.length}
{/* Drawer Navigation */}
setDrawerExpanded(false)}
>
Home
setShowContactForm(true)}>
Contact Us
setShowWishlist(true)}>
Wishlist
{/* Promotional Banner */}
Summer Sale Extravaganza!
Use code SAVE20 for 20% off!
{/* Breadcrumb */}
{/* Main Content Tabs */}
setTabSelected(e.selected)}>
{/* Filters */}
setSelectedCategory(e.value)}
/>
p.name)} value={searchQuery} onChange={(e) => setSearchQuery(e.value)} placeholder="Search..." />
setSortOption(e.value)} />
setQuantity(e.value || 1)} />
setDeliveryDate(e.value)} />
setShowFilters(e.checked)} label="Advanced Filters" />
{/* Advanced Filters */}
{showFilters && (
)}
{/* Product Grid */}
${props.dataItem.price}} />
{props.dataItem.rating} } />
(
handleAddToCart(props.dataItem)}>
handleViewProduct(props.dataItem)}>View
handleAddToWishlist(props.dataItem)}>
)}
/>
{/* Cart */}
Your Cart
{cart.length === 0 ? (
Empty
) : (
<>
${props.dataItem.price}} />
handleRemoveFromCart(props.dataIndex)}>Remove}
/>
Total: ${cart.reduce((sum, item) => sum + item.price * item.quantity, 0).toFixed(2)}
setPromoCode(e.value)} />
Apply Promo
Discount: {discount}%
setShowCheckout(true)}>Checkout
>
)}
${props.dataItem.price}} />
(
handleAddToCart(props.dataItem)}>Add to Cart
handleRemoveFromWishlist(props.dataIndex)}>Remove
)}
/>
User Profile
Name: {user.name}
Email: {user.email || 'Not logged in'}
setShowLogin(true)}>Login/Update
{/* Modals */}
{showLogin && (
setShowLogin(false)}>
setLoginEmail(e.value)} />
setLoginPassword(e.value)} />
Login
)}
{showProductDetails && selectedProduct && (
setShowProductDetails(false)} width={500}>
{selectedProduct.description}
Price: ${selectedProduct.price}
Rating: {selectedProduct.rating}
handleAddToCart(selectedProduct)}>Add to Cart
{(reviews[selectedProduct.id] || []).map((r, i) => (
{r.user}: {r.comment} ({r.rating}/5)
))}
handleAddReview(selectedProduct.id, 'Great!', 5)}>Submit Review
)}
{showCheckout && (
setShowCheckout(false)} width={600}>
{loading ? : (
<>
Shipping
Payment
Confirm
{checkoutStep === 0 && (
setShippingInfo({ ...shippingInfo, address: e.value })} />
setShippingInfo({ ...shippingInfo, city: e.value })} />
setShippingInfo({ ...shippingInfo, zip: e.value })} />
setShippingInfo({ ...shippingInfo, country: e.value })} />
)}
{checkoutStep === 1 && (
setPaymentInfo({ ...paymentInfo, cardNumber: e.value })} />
setPaymentInfo({ ...paymentInfo, expiry: e.value })} />
setPaymentInfo({ ...paymentInfo, cvv: e.value })} />
setPaymentInfo({ ...paymentInfo, cardHolder: e.value })} />
)}
{checkoutStep === 2 && (
<>
${props.dataItem.price}} />
Total: ${(cart.reduce((sum, item) => sum + item.price * item.quantity, 0) * (1 - discount / 100)).toFixed(2)}
>
)}
{checkoutStep > 0 && setCheckoutStep(checkoutStep - 1)}>Previous}
{checkoutStep === 2 ? 'Place Order' : 'Next'}
>
)}
)}
{showOrderHistory && (
setShowOrderHistory(false)} width={700}>
)}
{showContactForm && (
setShowContactForm(false)}>
setContactForm({ ...contactForm, name: e.value })} />
setContactForm({ ...contactForm, email: e.value })} />
setContactForm({ ...contactForm, message: e.value })} />
alert('Message Sent!')}>Send
)}
{showWishlist && (
setShowWishlist(false)}>
${props.dataItem.price}} />
handleAddToCart(props.dataItem)}>Add to Cart}
/>
)}
{/* Notification */}
{showNotification && (
{checkoutStep === 2 ? 'Order placed!' : 'Added to cart!'}
)}
{/* Massive Additional Content */}
{Array.from({ length: 20 }, (_, i) => (
{products.slice(i * 5, i * 5 + 5).map((p) => (
{p.name}
${p.price}
handleAddToCart(p)}>Add
))}
))}
{/* Bottom Navigation */}
setShowCheckout(true)} />
setShowLogin(true)} />
{/* Footer */}
Owner: Aniruddha Adak
© 2025 Aniruddha Adak. All rights reserved.
);
}
export default App;
App.css
/* General Styles */
.App {
font-family: 'Roboto', Arial, sans-serif;
background: linear-gradient(135deg, #f0f4f8, #d9e2ec);
min-height: 100vh;
color: #333;
}
h1, h2, h3 {
color: #2c3e50;
}
.content {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
/* AppBar */
.appbar {
background: #2980b9 !important;
padding: 15px 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}
.appbar-actions {
margin-left: auto;
}
/* Drawer */
.k-drawer {
background: #34495e;
color: white;
}
.k-drawer-item:hover {
background: #3e5f7e;
}
/* Promo Banner */
.promo-banner {
background: #f1c40f;
padding: 20px;
text-align: center;
border-radius: 8px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
/* Filters */
.filters {
background: #fff;
padding: 15px;
border-radius: 8px;
box-shadow: 0 3px 15px rgba(0, 0, 0, 0.1);
flex-wrap: wrap;
}
/* Grid */
.product-grid {
background: #fff;
border-radius: 8px;
overflow-x: auto;
}
.k-grid th {
background: #3498db;
color: white;
}
.k-grid td {
border-bottom: 1px solid #ecf0f1;
}
/* Card */
.cart, .k-card {
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 3px 15px rgba(0, 0, 0, 0.1);
margin: 20px 0;
}
/* Dialog */
.k-dialog {
border-radius: 8px;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3);
}
.checkout-steps {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.checkout-steps span {
padding: 8px 15px;
background: #ddd;
border-radius: 20px;
}
.checkout-steps .active {
background: #2980b9;
color: white;
}
/* Product Image */
.product-image {
width: 100%;
max-height: 250px;
object-fit: cover;
border-radius: 8px;
}
/* Footer */
.footer {
background: #2c3e50;
color: white;
padding: 40px 20px;
text-align: center;
margin-top: 40px;
border-top: 4px solid #3498db;
}
.social-links .k-svg-icon {
font-size: 32px !important;
color: #ecf0f1;
transition: color 0.3s;
}
.social-links .k-svg-icon:hover {
color: #3498db;
}
/* Responsive Design */
@media (max-width: 1024px) {
.content {
padding: 15px;
}
.filters {
flex-direction: column;
gap: 10px;
}
.k-grid {
font-size: 14px;
}
.k-dialog {
width: 90% !important;
}
}
@media (max-width: 768px) {
.appbar {
flex-direction: column;
align-items: flex-start;
padding: 10px;
}
.appbar-actions {
margin-top: 10px;
width: 100%;
justify-content: space-between;
}
.promo-banner {
padding: 15px;
}
.k-grid th, .k-grid td {
padding: 8px;
}
.footer {
padding: 20px;
}
.social-links {
flex-wrap: wrap;
gap: 15px;
}
}
@media (max-width: 480px) {
h1 { font-size: 20px; }
h2 { font-size: 18px; }
h3 { font-size: 16px; }
p { font-size: 12px; }
.filters {
padding: 10px;
}
.k-button {
padding: 6px 12px;
font-size: 12px;
}
.product-image {
max-height: 150px;
}
.social-links .k-svg-icon {
font-size: 24px !important;
}
}