Package Exports
- @instockng/storefront-ui
- @instockng/storefront-ui/fetchers
- @instockng/storefront-ui/styles.css
Readme
@instockng/storefront-ui
Pre-built React UI components for building e-commerce storefronts with the OMS (Order Management System) API. Built with React, TypeScript, Tailwind CSS, and shadcn/ui.
Installation
npm install @instockng/storefront-ui @tanstack/react-query lucide-reactQuick Start
- ✅ Drop-in Components - Fully functional UI out of the box
- ✅ Fully Typed - TypeScript support with auto-generated API types
- ✅ Customizable - Override styles with className props
- ✅ Theme Support - Pass custom colors, fonts, and styling
- ✅ Responsive - Mobile-first design
- ✅ Accessible - Built with accessibility in mind
Installation
npm install @instockng/storefront-ui
# or
pnpm add @instockng/storefront-uiPeer Dependencies
npm install react react-dom @tanstack/react-query lucide-reactUsage
Setup
Option A: If your project already uses Tailwind CSS (Recommended)
Add storefront-ui to your Tailwind config's content array:
// tailwind.config.ts
export default {
content: [
'./app/**/*.{js,ts,jsx,tsx}',
'./node_modules/@instockng/storefront-ui/src/**/*.{js,ts,jsx,tsx}', // Add this
],
// ... rest of your config
}Option B: If your project doesn't use Tailwind CSS
Import the pre-built CSS file:
// app/layout.tsx or _app.tsx
import '@instockng/storefront-ui/styles.css';Providers
Wrap your app with providers:
import { ApiClientProvider } from '@instockng/storefront-ui';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<ApiClientProvider baseURL="https://api.yoursite.com">
<YourApp />
</ApiClientProvider>
</QueryClientProvider>
);
}Quick Start Examples
ProductGrid - Product Catalog
import { ProductGrid } from '@instockng/storefront-ui';
function ProductCatalog() {
return (
<ProductGrid
brandId="your-brand-uuid"
onAddToCart={(variantId, quantity) => {
console.log('Adding to cart:', variantId, quantity);
}}
columns={3}
showStock={true}
/>
);
}ShoppingCart - Cart Sidebar with Integrated Checkout
The ShoppingCart component now includes an integrated Checkout modal - no need to handle onCheckout unless you want custom behavior!
import { ShoppingCart, CartProvider } from '@instockng/storefront-ui';
function MyApp() {
const [isCartOpen, setIsCartOpen] = useState(false);
return (
<CartProvider cartId="cart-uuid">
{/* Your app content */}
<button onClick={() => setIsCartOpen(true)}>Open Cart</button>
{/* Cart with integrated checkout - no onCheckout needed! */}
<ShoppingCart
isOpen={isCartOpen}
onClose={() => setIsCartOpen(false)}
onOrderSuccess={(orderId) => {
console.log('Order placed:', orderId);
// Optionally navigate or show success message
}}
showDiscountCode={true}
/>
</CartProvider>
);
}Custom Checkout Handler (Optional)
If you need custom behavior, you can still pass onCheckout:
<ShoppingCart
isOpen={isCartOpen}
onClose={() => setIsCartOpen(false)}
onCheckout={() => navigate('/custom-checkout')} // Custom behavior
showDiscountCode={true}
/>CheckoutSummary - Checkout Page
import { CheckoutSummary } from '@instockng/storefront-ui';
function CheckoutPage() {
const navigate = useNavigate();
return (
<CheckoutSummary
cartId="cart-uuid"
brandId="brand-uuid"
onSuccess={(orderId, token) => {
navigate(`/order-confirmation/${orderId}/${token}`);
}}
cartSummary={{
subtotal: 100.00,
discountAmount: 10.00,
discountCode: 'SAVE10',
deliveryFee: 5.00,
total: 95.00
}}
/>
);
}OrderConfirmation - Confirmation Page
import { OrderConfirmation } from '@instockng/storefront-ui';
function OrderPage() {
const { orderId, token } = useParams();
return (
<OrderConfirmation
orderId={orderId}
token={token}
onConfirm={(orderNumber) => {
console.log('Order confirmed:', orderNumber);
}}
/>
);
}Customization
<OrderConfirmation
orderId={orderId}
token={token}
// Custom styling
className="bg-white"
headerClassName="text-brand-blue"
buttonClassName="bg-brand-primary hover:bg-brand-primary-dark"
cardClassName="shadow-lg border-brand-gray"
// Custom locale & currency
currency="USD"
locale="en-US"
// Custom WhatsApp support
whatsappHelpLink="https://wa.me/1234567890"
whatsappHelpNumber="+1 (234) 567-890"
// Callbacks
onConfirm={(orderNumber) => {
// Track analytics
analytics.track('Order Confirmed', { orderNumber });
// Redirect
router.push('/thank-you');
}}
onError={(error) => {
// Show toast notification
toast.error('Failed to confirm order');
}}
/>Available Components
Product Components
- ProductGrid - Grid of products with add to cart, filtering, and customization
- ProductCard - Individual product with variants, images, stock status, and quantity selector
Cart Components
- ShoppingCart - Full cart display with items, discount codes, and checkout button
- CartItem - Individual cart item with quantity controls and remove button
- DiscountCodeInput - Standalone discount code input with validation
Checkout Components
- CheckoutSummary - Complete checkout form with customer info, delivery, and payment
- DeliveryZoneSelector - Delivery zone dropdown grouped by state
Order Components
- OrderConfirmation - Order confirmation page for confirming prospect orders
Theming
All components accept className props for custom styling:
<OrderConfirmation
className="font-custom" // Root container
headerClassName="text-brand-color" // Header section
buttonClassName="bg-brand-primary" // Buttons
cardClassName="border-brand-gray" // Card components
/>Using with Tailwind
The components are built with Tailwind CSS. Make sure your tailwind.config.js includes the package:
module.exports = {
content: [
'./src/**/*.{js,ts,jsx,tsx}',
'./node_modules/@instockng/storefront-ui/**/*.{js,ts,jsx,tsx}',
],
// ... your config
}API Hooks
All @oms/api-client hooks are re-exported for convenience:
import {
useGetOrder,
useConfirmOrder,
useGetProducts,
useGetCart,
useCheckout,
// ... all other hooks
} from '@instockng/storefront-ui';UI Primitives
Access underlying UI components for custom layouts:
import {
Button,
Card,
CardContent,
CardHeader,
CardTitle,
Badge,
} from '@instockng/storefront-ui';Utilities
Helper functions for formatting:
import {
formatCurrency,
formatDate,
formatDateTime,
getStatusColor,
cn, // Tailwind class merger
} from '@instockng/storefront-ui';
// Usage
formatCurrency(1999.99, 'USD', 'en-US'); // "$1,999.99"
formatDate('2024-01-15'); // "January 15, 2024"
formatDateTime('2024-01-15T10:30:00'); // "January 15, 2024 at 10:30 AM"
getStatusColor('shipped'); // "bg-blue-100 text-blue-800"
cn('base-class', { 'conditional': true }); // Merges Tailwind classesTypeScript
All components are fully typed with TypeScript:
import type { OrderConfirmationProps } from '@instockng/storefront-ui';
const config: OrderConfirmationProps = {
orderId: '123',
token: 'abc',
// TypeScript will autocomplete and validate all props
};Examples
Simple Usage
import { OrderConfirmation } from '@instockng/storefront-ui';
export default function OrderPage({ orderId, token }) {
return <OrderConfirmation orderId={orderId} token={token} />;
}With Custom Brand Colors
import { OrderConfirmation } from '@instockng/storefront-ui';
export default function BrandedOrderPage({ orderId, token }) {
return (
<OrderConfirmation
orderId={orderId}
token={token}
className="bg-gray-50 font-inter"
headerClassName="text-purple-600"
buttonClassName="bg-purple-600 hover:bg-purple-700"
cardClassName="border-purple-200"
currency="USD"
locale="en-US"
/>
);
}With Analytics Tracking
import { OrderConfirmation } from '@instockng/storefront-ui';
import { analytics } from './analytics';
export default function TrackedOrderPage({ orderId, token }) {
return (
<OrderConfirmation
orderId={orderId}
token={token}
onConfirm={(orderNumber) => {
analytics.track('Order Confirmed', {
orderNumber,
orderId,
});
// Redirect to thank you page
window.location.href = '/thank-you';
}}
onError={(error) => {
analytics.track('Order Confirmation Failed', {
error: error.message,
orderId,
});
}}
/>
);
}Development
This package is part of the OMS monorepo. When the backend API changes:
# Regenerate types
cd packages/types
pnpm run generate
# The storefront-ui will automatically pick up new typesLicense
ISC