muspe-cli
Version:
MusPE Advanced Framework v2.1.3 - Mobile User-friendly Simple Progressive Engine with Enhanced CLI Tools, Specialized E-Commerce Templates, Material Design 3, Progressive Enhancement, Mobile Optimizations, Performance Analysis, and Enterprise-Grade Develo
720 lines (593 loc) • 15.5 kB
Markdown
# MusPE UI Components 📱
A complete mobile-first UI component library for the MusPE Framework. Built with modern web standards and optimized for touch interfaces.
## 🎯 Features
- **📱 Mobile-First**: Designed specifically for mobile and touch devices
- **🎨 Modern Design**: Clean, minimalist design based on Material Design and iOS principles
- **⚡ Performant**: Optimized for mobile performance with efficient rendering
- **🔧 Customizable**: Extensive customization options and CSS variables
- **♿ Accessible**: Built with accessibility in mind
- **🌙 Dark Mode**: Automatic dark mode support
- **📐 Responsive**: Adaptive layouts for all screen sizes
- **👆 Touch-Friendly**: Optimized for touch interactions and gestures
- **🔄 Reactive**: Integrates seamlessly with MusPE's reactive system
## 📦 Installation
MusPE UI components are included with the MusPE Framework v2.0+:
```bash
npm install -g muspe-cli@2.0.0
```
Create a new project with UI components:
```bash
muspe create my-app
cd my-app
```
## 🚀 Quick Start
### Import Components
```javascript
// Import all components
import MusPEUI from './src/ui/index.js';
// Or import individual components
import { Button, Input, Card, Modal } from './src/ui/index.js';
```
### Include CSS
```html
<!-- Include MusPE UI CSS -->
<link rel="stylesheet" href="./src/ui/muspe-ui.css">
```
### Basic Usage
```javascript
// Create a button
const button = new MusPEUI.Button({
text: 'Click me!',
variant: 'primary',
callbacks: {
onClick: () => console.log('Button clicked!')
}
});
// Add to DOM
document.body.appendChild(button.render());
```
## 📚 Components
### 🔘 Button
Versatile button component with multiple variants and states.
```javascript
const button = new Button({
text: 'Primary Button',
variant: 'primary', // primary, secondary, outline, ghost, danger
size: 'md', // sm, md, lg, xl
icon: '⭐',
iconPosition: 'left', // left, right
loading: false,
disabled: false,
fullWidth: false,
hapticFeedback: true,
callbacks: {
onClick: (event) => {
console.log('Button clicked!');
}
}
});
```
**Methods:**
- `setText(text)` - Update button text
- `setLoading(loading)` - Toggle loading state
- `setDisabled(disabled)` - Toggle disabled state
### 📝 Input
Modern input field with validation and multiple variants.
```javascript
const input = new Input({
type: 'text', // text, email, password, number, tel, url, search
label: 'Full Name',
placeholder: 'Enter your name',
value: '',
variant: 'outline', // outline, filled, underline
size: 'md', // sm, md, lg
icon: '👤',
iconPosition: 'left',
clearable: true,
required: true,
maxLength: 50,
callbacks: {
onInput: (value, event) => console.log('Input:', value),
onChange: (value, event) => console.log('Changed:', value),
onFocus: (event) => console.log('Focused'),
onBlur: (event) => console.log('Blurred')
}
});
```
**Methods:**
- `setValue(value)` - Set input value
- `getValue()` - Get current value
- `setError(message)` - Show error message
- `setSuccess(success)` - Show success state
- `focus()` - Focus the input
- `setDisabled(disabled)` - Toggle disabled state
### 🃏 Card
Flexible card component for displaying content.
```javascript
const card = new Card({
title: 'Card Title',
subtitle: 'Card subtitle',
content: 'Card content goes here...',
image: 'path/to/image.jpg',
variant: 'elevated', // elevated, outlined, filled
clickable: true,
padding: 'default', // none, sm, default, lg
actions: [
{
text: 'Action 1',
icon: '❤️',
callback: () => console.log('Action 1')
},
{
text: 'Action 2',
callback: () => console.log('Action 2')
}
],
callbacks: {
onClick: () => console.log('Card clicked'),
onActionClick: (action, index) => console.log('Action clicked', action)
}
});
```
**Methods:**
- `setTitle(title)` - Update card title
- `setContent(content)` - Update card content
- `setImage(image)` - Update card image
### 🪟 Modal
Full-featured modal dialog component.
```javascript
const modal = new Modal({
title: 'Modal Title',
content: 'Modal content...',
size: 'md', // sm, md, lg, xl, full
closable: true,
closeOnBackdrop: true,
closeOnEscape: true,
showHeader: true,
showFooter: true,
animation: 'slideUp', // slideUp, slideDown, fade, zoom
footerActions: [
{
text: 'Cancel',
variant: 'secondary',
callback: () => console.log('Cancelled')
},
{
text: 'Confirm',
variant: 'primary',
callback: () => console.log('Confirmed')
}
],
callbacks: {
onOpen: () => console.log('Modal opened'),
onClose: () => console.log('Modal closed')
}
});
// Show modal
modal.render();
modal.open();
```
**Methods:**
- `open()` - Show the modal
- `close()` - Hide the modal
- `setContent(content)` - Update modal content
- `setTitle(title)` - Update modal title
### 📱 Action Sheet
iOS-style bottom sheet for actions.
```javascript
const actionSheet = new ActionSheet({
title: 'Choose Action',
message: 'Select one of the options below',
actions: [
{
text: 'Camera',
icon: '📷',
callback: () => console.log('Camera')
},
{
text: 'Photo Library',
icon: '🖼️',
callback: () => console.log('Photos')
},
{
text: 'Delete',
icon: '🗑️',
destructive: true,
callback: () => console.log('Delete')
}
],
cancelButton: 'Cancel',
callbacks: {
onOpen: () => console.log('Action sheet opened'),
onClose: () => console.log('Action sheet closed'),
onAction: (action, index) => console.log('Action selected', action)
}
});
actionSheet.render();
actionSheet.open();
```
### 🧭 Navbar
Mobile navigation bar component.
```javascript
const navbar = new Navbar({
title: 'App Title',
backButton: true,
searchButton: true,
menuButton: false,
theme: 'light', // light, dark, auto
fixed: true,
transparent: false,
shadow: true,
actions: [
{
icon: '⚙️',
callback: () => console.log('Settings')
}
],
callbacks: {
onBack: () => history.back(),
onSearch: () => console.log('Search'),
onMenu: () => console.log('Menu')
}
});
```
**Methods:**
- `setTitle(title)` - Update navbar title
- `setTheme(theme)` - Change theme
- `show()` - Show navbar
- `hide()` - Hide navbar
### 🔧 Toolbar
Bottom toolbar/tab bar component.
```javascript
const toolbar = new Toolbar({
position: 'bottom', // top, bottom
theme: 'light',
activeIndex: 0,
items: [
{
icon: { active: '🏠', inactive: '🏡' },
label: 'Home'
},
{
icon: { active: '🔍', inactive: '🔎' },
label: 'Search'
},
{
icon: { active: '❤️', inactive: '🤍' },
label: 'Favorites'
}
],
badge: {
2: '5' // Badge on third item
},
callbacks: {
onItemClick: (index, item) => {
console.log('Tab clicked:', index, item.label);
}
}
});
```
**Methods:**
- `setActive(index)` - Set active tab
- `setBadge(index, value)` - Update badge
- `updateItems(items)` - Update toolbar items
### 📦 Container
Layout container with responsive behavior.
```javascript
const container = new Container({
fluid: false,
safeArea: true,
padding: 'default', // none, sm, default, lg, xl
maxWidth: 'lg', // sm, md, lg, xl, full
children: [
// Child elements
]
});
```
## 🎨 Theming & Customization
### CSS Variables
Customize the appearance using CSS variables:
```css
:root {
/* Colors */
--muspe-primary: #007AFF;
--muspe-secondary: #FF9500;
--muspe-success: #34C759;
--muspe-warning: #FF9500;
--muspe-error: #FF3B30;
/* Spacing */
--muspe-space-1: 0.25rem;
--muspe-space-2: 0.5rem;
--muspe-space-3: 0.75rem;
--muspe-space-4: 1rem;
/* Typography */
--muspe-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--muspe-font-size-base: 1rem;
/* Border Radius */
--muspe-radius-sm: 0.375rem;
--muspe-radius-md: 0.5rem;
--muspe-radius-lg: 0.75rem;
--muspe-radius-xl: 1rem;
/* Shadows */
--muspe-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--muspe-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
--muspe-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
```
### Dark Mode
Dark mode is automatically applied based on system preference:
```css
@media (prefers-color-scheme: dark) {
:root {
--muspe-primary: #0A84FF;
/* Other dark mode variables */
}
}
```
Force dark mode:
```css
[data-theme="dark"] {
/* Dark mode styles */
}
```
### Custom Variants
Create custom button variants:
```css
.muspe-button--custom {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
}
.muspe-button--custom:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
}
```
## 📱 Mobile Optimizations
### Touch Interactions
All components are optimized for touch:
```javascript
// Automatic touch feedback
button.element.addEventListener('touchstart', () => {
button.element.classList.add('muspe-button--touching');
});
// Haptic feedback (where supported)
if ('vibrate' in navigator) {
navigator.vibrate(10);
}
```
### Safe Area Support
Components automatically respect device safe areas:
```css
.muspe-safe-area {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
```
### Responsive Breakpoints
```css
/* Mobile First */
@media (min-width: 640px) { /* Small tablets */ }
@media (min-width: 768px) { /* Tablets */ }
@media (min-width: 1024px) { /* Laptops */ }
@media (min-width: 1280px) { /* Desktops */ }
```
## 🔧 Integration with MusPE Framework
### Reactive Components
```javascript
import { reactive, computed } from '../core/reactivity.js';
const state = reactive({
count: 0,
name: ''
});
const button = new Button({
text: computed(() => `Count: ${state.count}`),
callbacks: {
onClick: () => state.count++
}
});
```
### Component Integration
```javascript
import { MusPEComponent } from '../core/component.js';
class MyComponent extends MusPEComponent {
constructor(props) {
super(props);
this.button = new Button({
text: 'Click me',
callbacks: {
onClick: () => this.handleClick()
}
});
}
render() {
return h('div', {}, [
this.button.render()
]);
}
handleClick() {
// Handle button click
}
}
```
## 📖 Examples
### Complete Form
```javascript
class ContactForm {
constructor() {
this.form = document.createElement('form');
this.setupInputs();
this.setupButton();
}
setupInputs() {
this.nameInput = new Input({
label: 'Name',
required: true,
callbacks: {
onBlur: () => this.validateName()
}
});
this.emailInput = new Input({
type: 'email',
label: 'Email',
required: true,
callbacks: {
onBlur: () => this.validateEmail()
}
});
this.form.appendChild(this.nameInput.render());
this.form.appendChild(this.emailInput.render());
}
setupButton() {
this.submitButton = new Button({
text: 'Submit',
variant: 'primary',
fullWidth: true,
callbacks: {
onClick: () => this.submit()
}
});
this.form.appendChild(this.submitButton.render());
}
validateName() {
const value = this.nameInput.getValue().trim();
if (!value) {
this.nameInput.setError('Name is required');
return false;
}
this.nameInput.setSuccess();
return true;
}
validateEmail() {
const value = this.emailInput.getValue().trim();
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!value) {
this.emailInput.setError('Email is required');
return false;
} else if (!emailRegex.test(value)) {
this.emailInput.setError('Please enter a valid email');
return false;
}
this.emailInput.setSuccess();
return true;
}
async submit() {
if (!this.validateName() || !this.validateEmail()) {
return;
}
this.submitButton.setLoading(true);
try {
// Submit form data
const response = await fetch('/api/contact', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: this.nameInput.getValue(),
email: this.emailInput.getValue()
})
});
if (response.ok) {
// Show success modal
const modal = new Modal({
title: 'Success!',
content: 'Your message has been sent.',
size: 'sm',
showFooter: true,
footerActions: [
{
text: 'OK',
variant: 'primary'
}
]
});
modal.render();
modal.open();
}
} catch (error) {
console.error('Submit failed:', error);
} finally {
this.submitButton.setLoading(false);
}
}
}
```
### Mobile App Layout
```javascript
class MobileApp {
constructor() {
this.setupNavbar();
this.setupContent();
this.setupToolbar();
}
setupNavbar() {
this.navbar = new Navbar({
title: 'My App',
searchButton: true,
callbacks: {
onSearch: () => this.showSearch()
}
});
document.body.appendChild(this.navbar.render());
}
setupContent() {
this.container = new Container({
safeArea: true,
padding: 'default'
});
const content = document.createElement('div');
content.style.marginTop = '60px';
content.style.marginBottom = '60px';
content.style.minHeight = 'calc(100vh - 120px)';
this.container.setContent(content);
document.body.appendChild(this.container.render());
}
setupToolbar() {
this.toolbar = new Toolbar({
items: [
{ icon: '🏠', label: 'Home' },
{ icon: '🔍', label: 'Search' },
{ icon: '❤️', label: 'Favorites' },
{ icon: '👤', label: 'Profile' }
],
callbacks: {
onItemClick: (index) => this.navigateToTab(index)
}
});
document.body.appendChild(this.toolbar.render());
}
navigateToTab(index) {
// Handle navigation
console.log('Navigating to tab:', index);
}
showSearch() {
// Show search interface
console.log('Showing search');
}
}
// Initialize app
const app = new MobileApp();
```
## 🚀 Performance Tips
1. **Lazy Loading**: Load components only when needed
2. **Event Delegation**: Use event delegation for better performance
3. **Virtual Scrolling**: For large lists, implement virtual scrolling
4. **Debouncing**: Debounce input events for better performance
5. **CSS Containment**: Use CSS containment for better rendering performance
## 📱 Browser Support
- **iOS Safari**: 12+
- **Chrome Mobile**: 70+
- **Firefox Mobile**: 68+
- **Samsung Internet**: 10+
- **Desktop browsers**: Modern browsers with touch support
## 🤝 Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests
5. Submit a pull request
## 📄 License
MIT License - see LICENSE file for details
**MusPE UI Components** - Making mobile development beautiful and efficient! 📱✨