mithril-materialized
Version:
A materialize library for mithril.
600 lines (482 loc) • 21.5 kB
Markdown
# mithril-materialized
A Mithril.js component library inspired by [materialize-css](https://materializecss.com) design principles, [available on npm](https://www.npmjs.com/package/mithril-materialized). This library provides you with ready-to-use Mithril components that follow Material Design guidelines, with **no external JavaScript dependencies**.
## 🚀 v3.4 - Latest Release
The current stable release that provides a complete Mithril.js Material Design component library with no external JavaScript dependencies.
### ✨ What's New
- **🔥 Zero External JS Dependencies**: No longer requires `materialize-css` JavaScript or `material-icons` fonts
- **📦 Smaller Bundle Size**: Reduced package size by eliminating external dependencies
- **⚡ Better Performance**: Direct implementations without jQuery or other heavy dependencies
- **🛠️ Enhanced Components**: Improved DatePicker with date ranges, week numbers, and TimePicker with configurable AM/PM/24h or inline style
- **🛠️ New Components**: DataTable, TreeView, Timeline, Masonry, RatingControl, ImageList, Wizard/Stepper, Breadcrumb
- **📱 Modern Architecture**: Factory components with proper TypeScript support
- **🎯 CSS-Only Styling**: Uses only CSS for styling - no JavaScript initialization needed
- **🎨 Custom SVG Icons**: Built-in MaterialIcon component with custom SVG icons (caret, close)
### ✨ Key Features
- **🔥 Zero External JS Dependencies**: No longer requires `materialize-css` JavaScript or `material-icons` fonts
- **📦 Smaller Bundle Size**: Reduced package size by eliminating external dependencies
- **🎨 Custom SVG Icons**: Built-in MaterialIcon component with custom SVG icons
- **⚡ Better Performance**: Direct implementations without jQuery or other heavy dependencies
- **🛠️ Enhanced Components**: Comprehensive component library with modern features
- **🌗 Dark Theme Support**: Built-in light/dark theme system with CSS custom properties
- **📱 Modern Architecture**: Factory components with proper TypeScript support, and clear separation between [controlled and uncontrolled](CONTROLLED_COMPONENTS.md) component state
- **🎯 CSS-Only Styling**: Uses only CSS for styling - no JavaScript initialization needed
### 📦 Installation
```bash
npm install mithril mithril-materialized
```
## Supported Components
Components marked with an * are not included in the original materialize-css library.
- [Buttons](https://erikvullings.github.io/mithril-materialized/#!/buttons)
- Button
- FlatButton
- RoundButton
- SubmitButton
- [Inputs](https://erikvullings.github.io/mithril-materialized/#!/inputs)
- TextInput
- TextArea
- AutoComplete
- UrlInput
- EmailInput
- NumberInput
- ColorInput
- RangeInput* (with vertical, double-thumb support, and smart tooltip display)
- Chips
- [Pickers](https://erikvullings.github.io/mithril-materialized/#!/pickers)
- DatePicker (with optional week numbers and date range selection)*
- TimePicker (with inline mode and switchable AM/PM/24h)*
- [Selections](https://erikvullings.github.io/mithril-materialized/#!/selections)
- Select
- SearchSelect*, a searchable select dropdown
- Options
- RadioButtons
- Switch
- Dropdown
- [Collections](https://erikvullings.github.io/mithril-materialized/#!/collections)
- Basic, Link and Avatar Collections
- Collapsible or accordion
- [Theme & Upload](https://erikvullings.github.io/mithril-materialized/#!/theme)
- ThemeSwitcher* (light/dark/auto theme switching)
- ThemeToggle* (simple light/dark toggle)
- FileUpload* (drag-and-drop with validation and preview)
- [Navigation](https://erikvullings.github.io/mithril-materialized/#!/navigation)
- Sidenav (responsive navigation drawer)
- Breadcrumb* (navigation path indicator)
- Wizard/Stepper* (multi-step process guidance)
- [Others](https://erikvullings.github.io/mithril-materialized/#!/modals)
- ModalPanel
- MaterialBox
- Carousel
- Pagination
- PaginationControls*
- Parallax
- Layout & Display
- [Masonry](https://erikvullings.github.io/mithril-materialized/#!/masonry)* (Pinterest-style responsive grid layout)
- [ImageList](https://erikvullings.github.io/mithril-materialized/#!/image-list)* (responsive image galleries with various layouts)
- [Timeline](https://erikvullings.github.io/mithril-materialized/#!/timeline)* (vertical timeline with events and milestones)
- [Rating](https://erikvullings.github.io/mithril-materialized/#!/rating)*
- RatingControl (Horizontal control, configurable range and step size, optionally with custom icons)
- [Data & Tables](https://erikvullings.github.io/mithril-materialized/#!/datatable)
- DataTable* (sorting, filtering, pagination, selection)
- TreeView* (hierarchical data with expand/collapse, selection, and customizable icons)
- Additional
- Label
- HelperText
- CodeBlock
- Icon, a simple wrapper for creating icons using material-icons font
- MaterialIcon, for creating the close/clear and caret as SVG
## 📖 Usage Instructions
Online [flems](flems.io) examples: [FlatButton](https://flems.io/#0=N4IgtglgJlA2CmIBcBWFA6AnAJgDQgGd4EBjAF3imRHTIJHwDMIF6kBtUAOwEMxEkNABZkwsBiBIB7LhVnUAPLAhcA1gAIATsQC8AHUJkAnqyHx4ZA+qHbG+kCLIAHAkgD0bgK5cnqgObo0mBukGQ2LAC0YDwUmhA8ygBelG5QEARkbipQ8AAegQQEBgB8elwSRKRkEDJsIACMSAAMIAC+uNx8AjR0EtKy8PKC-RnqwOoAYrAxAEKeZGQy6q3qOuoA7tlS6+wA5KHhsFEx8HEJEMlQuwC6ANxlZSNk6jIkyiQaawAUAJSrxeoEqcyF9dqoAFZCCG7H4PLhgdDaLg5TRfKBSEiefiydAAIykUCMuHUYC+U1m80WXGJ42muOISHUBgAskZJtNnrjKTIDMTXu8NK0fj97lwyhViPByDUuHUAGzNNodEC8fjUAr0fD9ORkahta74ZRqNicFVdagHOLifCeTTiQSOFzuLw+fyBKTBS0sAAC2HQAGZ0AB2EIQMJW9CQLjocGakDGJzdAgkOJOXXtTpqwReo7RWLxJKUCS2+0OBZOjzeXwBIKh8ORPOnAsXSjewOBgAsqXSmWyeXQWKgMbjCaTKYgaf1rSAA) and [Select](https://flems.io/#0=N4IgtglgJlA2CmIBcBWFA6AnAJgDQgGd4EBjAF3imRHTIJHwDMIF6kBtUAOwEMxEkNABZkwsBiBIB7LhVnUAPLAhcA1gAIATsQC8AHUJkAnqyHx4ZA+qHbG+kCLIAHAkgD0bgK5cnqgObo0mBukGQ2LAC0YDwUmhA8ygBelG5QEARkbipQ8AAegQQEBgB8elwSRKRkEDJsIACMSAAMIAC+uNx8AjR0EtKy8PKC-RnqwOoAysTw5Oqt6jrqAO7ZUkvsAOSh4bBRMfBxCRDJUBsAugDcZWUIZOokZiSqlACSUAvqG9gbV1xlYOgwFJvGQABRQKQkTz8WToABGUigRlwY2uZAAbhB4EskOpQQBKBbFdRgUEbdCaNYbFHjDImeC48bRTR+FQAFSkTlxG3qTScuQ2czmKLK6jFJNBUyqNPUsB4cOI3KlMzu-Gp6lF4rFTjlJHgQiksBymm5AGFlE91DJ4NTNVqHjNnlA3rg7eLOdVarj2G6teNoNz6uq5QrYNyAPJOT1cdRB4W+8X+qDc74okOKz6R6Pqb7xmNaxPqAOfADMwflGY2WZqMbLeYL6jOrvzWpkDx4XD8DLx6MJOmJwATYodT1e70W6N+Dfabta+LKc+uf3K+EqKprdSazQi2EaLXanX41AK9Hw-TkZGobSbIGUajYnBAvCPgm2cXE+E8mnEgkcLncXg+P4gRSMEb4sAAAtg6AlugADsIQQGE76Aio6AAFaniAxhON0BAkHEUZtB0T5dNQ4G7NEsTxEklASF+P4OGQziuB43i+AEQSIchkRUQcNHHJQEGwbBAAsqTpJk2R5Og0JQBhWE4XhBEQERrRnK0QA).
### Quick Start
1. **Install the package**:
```bash
npm install mithril mithril-materialized
```
2. **Import the CSS** (optional, for Material Design styling):
```typescript
import 'mithril-materialized/index.css';
```
3. **Use components in your app**:
```typescript
import m from 'mithril';
import {
TextInput,
Button,
RangeInput,
DatePicker,
DataTable,
TreeView,
ThemeToggle,
FileUpload,
Sidenav,
Breadcrumb,
Wizard,
Masonry,
Timeline,
ImageList
} from 'mithril-materialized';
const MyComponent = () => ({
view: () => m('.container', [
// Theme toggle in header
m('nav', [
m('.nav-wrapper', [
m('.right', m(ThemeToggle))
])
]),
// Breadcrumb navigation
m(Breadcrumb, {
items: [
{ text: 'Home', href: '/' },
{ text: 'Products', href: '/products' },
{ text: 'Details', active: true }
]
}),
// Form inputs
m(TextInput, {
label: 'Your name',
onchange: (value) => console.log(value)
}),
// Enhanced range sliders with smart tooltips
m(RangeInput, {
label: 'Volume',
min: 0,
max: 100,
valueDisplay: 'auto', // Show tooltip on drag
onchange: (value) => console.log('Volume:', value)
}),
m(RangeInput, {
label: 'Price Range',
min: 0,
max: 1000,
minmax: true,
minValue: 100,
maxValue: 500,
valueDisplay: 'always', // Always show values
onchange: (min, max) => console.log('Range:', min, '-', max)
}),
m(RangeInput, {
label: 'Vertical Slider',
min: 0,
max: 100,
vertical: true,
height: '200px',
valueDisplay: 'auto',
tooltipPos: 'right',
onchange: (value) => console.log('Vertical:', value)
}),
// Enhanced DatePicker with range selection
m(DatePicker, {
label: 'Event Date',
helperText: 'Select a single date',
format: 'mmmm d, yyyy',
onchange: (value) => console.log('Date:', value)
}),
m(DatePicker, {
dateRange: true,
label: 'Project Timeline',
helperText: 'Select start and end dates',
format: 'mmmm d, yyyy',
minDateRange: 1,
maxDateRange: 30,
onchange: (value) => console.log('Date range:', value)
}),
m(Button, {
label: 'Submit',
onclick: () => alert('Hello!')
}),
// File upload
m(FileUpload, {
accept: 'image/*',
multiple: true,
onFilesSelected: (files) => console.log(files)
}),
// TreeView for hierarchical data
m(TreeView, {
data: [
{
id: 'root',
label: 'Project Root',
expanded: true,
children: [
{ id: 'src', label: 'src/' },
{ id: 'docs', label: 'docs/' },
]
}
],
selectionMode: 'multiple',
iconType: 'caret',
showConnectors: true,
onselection: (selectedIds) => console.log('Selected:', selectedIds)
}),
// Layout components
m(Masonry, {
items: [
{ id: 1, title: 'Card 1', content: 'Short content' },
{ id: 2, title: 'Card 2', content: 'Much longer content...' },
{ id: 3, title: 'Card 3', content: 'Medium content' }
],
columnWidth: 250,
gap: 16,
renderItem: (item) => m('.card', [
m('.card-content', [
m('span.card-title', item.title),
m('p', item.content)
])
])
}),
m(Timeline, {
events: [
{
id: 1,
title: 'Project Started',
date: '2024-01-15',
description: 'Initial project kickoff',
type: 'milestone'
},
{
id: 2,
title: 'First Release',
date: '2024-03-20',
description: 'Released version 1.0',
type: 'release'
}
]
}),
m(ImageList, {
images: [
{ src: '/image1.jpg', alt: 'Image 1' },
{ src: '/image2.jpg', alt: 'Image 2' },
{ src: '/image3.jpg', alt: 'Image 3' }
],
layout: 'masonry', // 'grid' | 'masonry' | 'quilted'
cols: 3
})
])
});
```
### Integration with Build Tools
**Webpack/Vite/Parcel**: The library works out-of-the-box with modern bundlers.
**CSS Framework Integration**: You can use the components with any CSS framework. The included CSS provides Material Design styling, but you can override it with your own styles.
**TypeScript**: Full TypeScript support with comprehensive type definitions included.
See the [live documentation](https://erikvullings.github.io/mithril-materialized/index.html) for examples and component APIs.
> **Note**: The date range picker is now fully implemented with comprehensive validation and formatting support.
## 🗺️ Roadmap & Planned Improvements
### 🚀 Phase 1: Core Optimizations & New Components (In Progress)
**✅ Completed:**
- ✅ Modular CSS architecture with tree-shaking support
- ✅ Dark theme system with CSS custom properties
- ✅ File upload component with drag-and-drop
- ✅ Theme switching components (ThemeSwitcher, ThemeToggle)
- ✅ Sidenav component with responsive behavior
- ✅ Breadcrumb navigation component
- ✅ Wizard/Stepper component for multi-step forms
**✅ Recently Completed (v3.2.x):**
- ✅ **TextArea Height Alignment**: Fixed single-line `textarea` height to match TextInput components perfectly
- ✅ **Improved AutoResize Logic**: TextArea now only sets custom height for multi-line content, matching Materialize CSS reference behavior
- ✅ **Better Mithril Integration**: Hidden div for height measurement now properly managed within Mithril's render cycle
- ✅ DataTable component with sorting, filtering, and pagination
- ✅ TreeView component for hierarchical data with expand/collapse, selection, and VSCode-style connectors
- ✅ Enhanced TypeScript definitions with better JSDoc comments
- ✅ Performance optimizations and bundle size improvements
- ✅ Enhanced RangeInput with vertical orientation, double-thumb range selection, and smart tooltip display
- ✅ Advanced DatePicker with date range selection, constraints, and format support
- ✅ Layout components: Masonry (Pinterest-style grid), Timeline (vertical event display), ImageList (responsive galleries)
- ✅ RatingControl with configurable icons, min/max, tooltip/helpers, readonly and disabled mode
- ✅ Improved RangeInput components converted to proper Mithril components with better lifecycle management
- ✅ Enhanced accessibility with individual thumb slider elements and PageUp/PageDown keyboard support
### 🎯 Phase 2: Advanced Components & Features
**Data Display:**
- Card layouts with enhanced Material Design 3.0 styling
- Advanced tree operations (drag & drop, context menus)
**Input & Forms:**
- ✅ Advanced date range picker with validation and constraints
- Autocomplete with async data loading
**Navigation & Layout:**
- AppBar/Toolbar component with responsive behavior
- Bottom navigation component for mobile apps
- Drawer/Sidebar component with overlay and push modes
- Grid system enhancements with CSS Grid support
### 🔮 Phase 3: Modern Features & Integration
**Developer Experience:**
- Storybook integration for component documentation
- Figma design system integration
- CLI tools for component generation
- Better accessibility (ARIA) support throughout
**Performance & Optimization:**
- Virtual scrolling for large lists
- Lazy loading component utilities
- Bundle analyzer and optimization tools
- CSS-in-JS runtime support option
### 📊 Bundle Size Targets
**Current Status (v3.2.2):**
- Total: ~65KB gzipped (42KB JS + 23KB CSS)
- Modular CSS can reduce bundle by 30-50%
- Optimized component implementations reduce overhead
**Phase 1 Targets:**
- Core bundle: <40KB gzipped
- Modular approach: <25KB for typical apps
- Tree-shaking effectiveness: 60%+
**Long-term Goals:**
- Individual components: <2KB each
- Micro-bundle support for single components
- Zero-runtime CSS option for static sites
### 🤝 Contributing
We welcome contributions! Priority areas for community involvement:
1. **Usage**: Accessibility improvements, performance optimizations
2. **Documentation**: Examples, guides, API documentation
3. **Testing**: Unit tests, visual regression tests, browser compatibility
See our [contributing guide](CONTRIBUTING.md) for detailed information.
### 📈 Performance Benchmarks
**Bundle Size Comparison:**
- mithril-materialized v3.2.2: ~65KB gzipped
- Material-UI: ~350KB gzipped
- Materialize CSS + jQuery: ~180KB gzipped
- Vuetify: ~250KB gzipped
**Runtime Performance:**
- Component initialization: <5ms average
- Theme switching: <10ms for full page
- File upload processing: Real-time without blocking
- TextArea auto-resize: <1ms per keystroke
## Build instructions
This repository consists of two packages, combined using `lerna`: the `lib` package that is published to `npm`, as well as an `example` project which uses this library to display the Mithril components that it contains.
To install the dependencies, you can use `npm i`, or, alternatively, use `pnpm m i` (assuming you have installed `pnpm` as alternative package manager using `npm i -g pnpm`) to perform a multi-repository install. Next, build everything using `npm start` and visit the documentation page on [http://localhost:1234](http://localhost:1234) in case port 1234 is not occupied already.
## 🎨 Styling & CSS
### CSS Usage
The library includes carefully crafted CSS that provides Material Design styling without external dependencies. You can import the ready-to-use CSS:
```typescript
import 'mithril-materialized/index.css';
```
**Important**: The CSS styling is **completely independent** of the original materialize-css. This means:
- ✅ No conflicting styles from materialize-css
- ✅ Smaller CSS bundle size
- ✅ Custom optimizations for better performance
- ✅ No external font dependencies
### 🔥 NEW: Modular CSS Architecture
**Tree-shakable CSS modules** for optimal bundle sizes! Import only the CSS you need:
```typescript
// Option 1: Import everything (64KB total)
import 'mithril-materialized/index.css';
// Option 2: Import only what you need (modular approach)
import 'mithril-materialized/core.css'; // Essential styles (18KB)
import 'mithril-materialized/forms.css'; // Form components only
import 'mithril-materialized/components.css'; // Interactive components
// Option 3: Advanced components only when needed
import 'mithril-materialized/pickers.css'; // Date/Time pickers
import 'mithril-materialized/advanced.css'; // Carousel, sidenav, etc.
import 'mithril-materialized/utilities.css'; // Badges, icons, cards
```
**CSS Modules Available:**
- `core.css` (18KB) - Essential foundation (normalize, grid, typography, variables)
- `components.css` - Interactive components (buttons, dropdowns, modals, tabs)
- `forms.css` - All form components (inputs, selects, switches, file upload)
- `pickers.css` - Date and time picker components
- `advanced.css` - Specialized components (carousel, sidenav, navbar, preloader)
- `utilities.css` - Visual utilities (badges, cards, icons, toast, chips)
**Bundle Size Optimization:**
- Full bundle: 64KB gzipped (44KB JS + 20KB CSS)
- Modular approach can reduce CSS by 30-50%
- Use only `core.css` + specific modules for your use case
### 🌓 Dark Theme Support
Built-in dark theme support with CSS custom properties:
```typescript
import { ThemeManager, ThemeSwitcher } from 'mithril-materialized';
// Programmatic theme control
ThemeManager.setTheme('dark'); // 'light' | 'dark' | 'auto'
ThemeManager.toggle(); // Toggle between light/dark
ThemeManager.getTheme(); // Get current theme
// UI Components
m(ThemeSwitcher, {
onThemeChange: (theme) => console.log('Theme:', theme)
});
m(ThemeToggle); // Simple toggle button
```
**CSS Custom Properties**: All colors use CSS variables for runtime theme switching:
```css
:root {
--mm-primary-color: #26a69a;
--mm-background-color: #ffffff;
--mm-text-primary: rgba(0, 0, 0, 0.87);
}
[data-theme="dark"] {
--mm-primary-color: #80cbc4;
--mm-background-color: #121212;
--mm-text-primary: rgba(255, 255, 255, 0.87);
}
```
### SASS Usage
For advanced customization, you can use the SASS source files directly:
```css
// Import all SASS components
@import 'mithril-materialized/sass/materialize.scss';
// Or import individual components
@import 'mithril-materialized/sass/components/buttons';
@import 'mithril-materialized/sass/components/forms';
@import 'mithril-materialized/sass/components/grid';
```
**SASS Variables**: You can customize colors, spacing, and other design tokens by overriding SASS variables before importing:
```css
// Customize Material Design variables
$primary-color: #2196F3;
$secondary-color: #FF9800;
// Then import the library
@import 'mithril-materialized/sass/materialize.scss';
```
### Custom Styles
The library includes these additional styles for enhanced functionality:
```css
/* For the switch */
.clear,
.clear-10,
.clear-15 {
clear: both;
/* overflow: hidden; Precaution pour IE 7 */
}
.clear-10 {
margin-bottom: 10px;
}
.clear-15 {
margin-bottom: 15px;
}
span.mandatory {
margin-left: 5px;
color: red;
}
label+.switch {
margin-top: 1rem;
}
/* For the color input */
input[type='color']:not(.browser-default) {
margin: 0px 0 8px 0;
/** Copied from input[type=number] */
background-color: transparent;
border: none;
border-bottom: 1px solid #9e9e9e;
border-radius: 0;
outline: none;
height: 3rem;
width: 100%;
font-size: 16px;
padding: 0;
-webkit-box-shadow: none;
box-shadow: none;
-webkit-box-sizing: content-box;
box-sizing: content-box;
-webkit-transition: border 0.3s, -webkit-box-shadow 0.3s;
transition: border 0.3s, -webkit-box-shadow 0.3s;
transition: box-shadow 0.3s, border 0.3s;
transition: box-shadow 0.3s, border 0.3s, -webkit-box-shadow 0.3s;
}
/* For the options' label */
.input-field.options > label {
top: -2.5rem;
}
/* For the code block */
.codeblock {
margin: 1.5rem 0 2.5rem 0;
}
.codeblock > div {
margin-bottom: 1rem;
}
.codeblock > label {
display: inline-block;
}
```