@tvashtr/ui
@tvashtr/ui
A rich, high-performance Nuxt 4 UI Layer providing reusable e-commerce components, reactive state composables, and client-side plugins.
@tvashtr/ui is the frontend core of the Tvashtr Suite. Built as a native Nuxt 4 Layer, it automatically injects generic storefront components, reactive cart state managers, shipping threshold calculators, and geolocation boundary helpers into any tenant store application extending it.
📦 Installation
This package is designed to be used internally within the Tvashtr Suite monorepo npm workspace:
{
"dependencies": {
"@tvashtr/ui": "*"
}
}
🔌 Extending the Layer in your Store
To enable @tvashtr/ui inside an app, extend the package path inside your tenant's nuxt.config.ts:
// apps/your-store-name/nuxt.config.ts
export default defineNuxtConfig({
extends: [
'@tvashtr/ui' // Auto-imports all components, composables, and plugins!
],
future: {
compatibilityVersion: 4 // Requires Nuxt 4 architecture compatibility
}
})
🧱 Reusable Storefront Components
All UI components are built using Nuxt UI and TailwindCSS v4, utilizing dynamic brand parameters specified inside each tenant store's store.config.ts.
🛒 Cart & Navigation
NavBar.vue: Elegant, responsive navigation bar supporting custom logos, category listings, a dynamic cart badge, and a global product search. On desktop the search input is embedded inline. On mobile, a magnifying glass icon in the topbar opens a full-width, auto-focused search overlay without requiring the hamburger menu.CartDrawer.vue: Flyout side panel showing items in the cart, item quantities, variant options, shipping thresholds, and the checkout form with Turnstile forms embedded.FooterBar.vue: Clean, modular footer containing brand links, support contacts, and license labels.
🏷️ Product Cards & Sliders
ProductCard.vue: Card component featuring high-quality images, interactive variant selectors, pricing, and "Add to Cart" triggers.ProductSlider.vue&HomeProductSlider.vue: Responsive sliders that display product arrays (e.g. popular items) in a clean, scrollable card line.
🍳 Recipe Hub
RecipeCard.vue: Clean grids displaying recipe categories, prep times, and image covers.RecipeSection.vue: Full-page details listing markdown steps, bulleted ingredient check-boxes, and an interactive section letting customers add all matching ingredients to their shopping cart in a single click.
🛡️ Bot Security
TurnstileWidget.vue: Standard wrapper component that mounts Cloudflare Turnstile's captcha client, emitting verification tokens securely upon human checks.
🧬 Product Attributes
ProductAttributesTable.vue: Generic attribute display component. Acceptstitle,subtitle, andattributesprops. Renders nothing when attributes is empty — zero DOM footprint. Suitable for any store type: Nutrition for food stores, Specifications for electronics, Features for service businesses. Stores can extend this with their own styled variant (e.g.NutritionLabelA.vue) using the same props.
🧪 Reactive Composables
The package exports robust state engines to drive client-side actions:
🔍 useProductFilters(products, categories)
A unified composable that manages both product search and category filtering with automatic, bidirectional URL query-parameter syncing. Drop it into any products page for instant search + filter functionality:
const {
// State
activeFilters, // Set<string> of active category slugs
dietaryCategories, // Computed — categories where type === 'dietary'
usageCategories, // Computed — categories where type === 'usage'
filteredProducts, // Computed — products after search + category filters applied
// Actions
toggleFilter, // Toggle a category slug on/off
clearFilters, // Clear all active category filters
isRowClear, // Check if an entire filter row (dietary/usage) is inactive
clearRowFilters, // Clear all filters in a row
countForCategory, // Count products matching a given category slug
} = useProductFilters(products, categories)
URL sync is automatic — ?q= for search, ?categories= for filters — both are read on mount and kept in sync on every change.
🛍️ useCart()
Handles reactive shopping cart state, syncing choices to LocalStorage or client Cookies:
const { cart, add, remove, updateQty, totalItems, totalPrice, clear } = useCart()
// Add item to shopping cart
add({
sku: 'FLOUR-001',
name: 'Wheat Flour',
image: '/assets/flour.jpg',
price: 4.99,
variant: '1kg',
qty: 1
})
🚚 useDelivery()
Manages delivery calculations, threshold limits, and free-shipping boundaries.
const { selectedDelivery, deliveryOptions, subtotal, totalWithDelivery } = useDelivery()
📍 useGeoRestriction()
Prevents shipping submissions outside delivery perimeters (e.g., restricting postcodes to Danish region bounds 1000-9999 or specific local zones).
const { isRestricted, checkPostcode } = useGeoRestriction()
🧬 useProductAttributes(sku)
Returns the attribute map for a given product SKU, sourced from the product attributes sheet loaded by productAttributes.client.ts. Returns an empty object when the sheet is not configured or the SKU has no row — the component self-hides automatically.
const { attributes, hasAttributes } = useProductAttributes(sku)
// attributes: { Calories: '340 kcal', Protein: '13 g', ... }
// hasAttributes: true
🏗️ Design System & Theming
@tvashtr/ui does not lock you into a single aesthetic. It abstracts colors and fonts into Tailwind variables, letting storefronts create completely unique brand identities:
/* apps/your-store-name/app/assets/main.css */
@theme {
--color-primary-50: var(--ui-color-amber-50);
--color-primary-500: var(--ui-color-amber-500);
--color-primary-950: var(--ui-color-amber-950);
--font-sans: 'Outfit', sans-serif;
}
🚀 Hydration Plugins (app/plugins/)
The UI layer automatically boots plugins to hydrate store data from sheet endpoints:
products.client.ts: Populates products state in the application during early initialization.recipes.client.ts: Safely loads and parses sheet recipe lists.delivery.client.ts: Validates initial cookie states for addresses and postcodes.categories.client.ts: Fetches and parses store categories from the categories sheet.productAttributes.client.ts: Fetches the product attributes sheet ifNUXT_PUBLIC_PRODUCT_ATTRIBUTES_SHEET_IDis configured. Silently provides an empty map if not — opt-in with zero noise for stores that don't use it.
Version History
| Version | Released | License |
|---|---|---|
| 1.0.8 | ||
| 1.0.7 | ||
| 1.0.6 | ||
| 1.0.5 | ||
| 1.0.4 | ||
| 1.0.3 | ||
| 1.0.2 | ||
| 1.0.1 | ||
| 1.0.0 |