A dynamic, interactive web application that allows users to customize a model's outfit by selecting different positions, materials, and colors. Built with Preact and leveraging Preact Signals for efficient state management and persistence.
- Interactive Product Configuration: Change positions, materials, and colors with real-time visual updates
- Persistent Settings: User selections are saved across page reloads
- Responsive Design: Works seamlessly across desktop and mobile devices
- Optimized Performance: Using Preact Signals for efficient state management and minimal re-renders
- Validation Logic: Ensures compatible selections between positions, materials, and colors
- Preact - A fast 3kB alternative to React with the same API
- @preact/signals - Fine-grained reactive state management
- LocalStorage API - For persisting user preferences
-
Clone the repository:
git clone https://github.com/asuh/configurator.git cd configurator -
Install dependencies:
npm install
-
Start the development server:
npm run dev
- Position Selection: Choose between different product positions/angles
- Material Selection: Select from available materials for the current position
- Color Selection: Pick a color from the available options for the selected material
Your selections are automatically saved and will persist even after refreshing the page or returning later.
This application uses Preact Signals for reactive state management:
// Core state signals
const positionId = signal(defaultPosition);
const materialId = signal(defaultMaterial);
const colorId = signal(defaultColor);
// Computed values derived from state
const currentPosition = computed(() =>
data.Positions.find(p => p.Position === positionId.value)
);
const currentMaterial = computed(() =>
currentPosition.value.Materials.find(m => m.Id === materialId.value)
);
// Automatic persistence
effect(() => {
saveState({
positionId: positionId.value,
materialId: materialId.value,
colorId: colorId.value
});
});- App: Main container component
- Positions: Position component
- Materials: Material component
- Colors: Color component
- User interactions update signal values
- Computed signals automatically derive new values
- UI components react to signal changes
- State is automatically persisted to localStorage
Product data is loaded from a JSON configuration file with the following structure:
{
"BaseImageUrl": "https://example.com/api/image",
"Positions": [
{
"Position": "position1",
"ImageUrl": "https://example.com/images/position1.png",
"Materials": [
{
"Id": "material1",
"Name": "Material 1",
"Colors": [
{
"Id": "color1",
"Name": "Color 1",
"SwatchUrl": "https://example.com/swatches/color1.png"
}
]
}
]
}
]
}- Accessibility improvements - Ensure all interactive elements are accessible via keyboard navigation to enhance usability for users with disabilities
- Testing - Verify TypeScript covers all potential unit tests and type safety
- Performance improvements
- Use better image formats
- Remove swatches and use CSS
- Refactor and break down components further
- Add loading indicators or spinners