A Mithril.js component library inspired by materialize-css design principles, available on npm. This library provides you with ready-to-use Mithril components that follow Material Design guidelines, with no external JavaScript dependencies.
The current stable release that provides a complete Mithril.js Material Design component library with no external JavaScript dependencies.
materialize-css
JavaScript or material-icons
fontsmaterialize-css
JavaScript or material-icons
fontsnpm install mithril mithril-materialized
Components marked with an * are not included in the original materialize-css library.
Online flems examples: FlatButton and Select.
Install the package:
npm install mithril mithril-materialized
Import the CSS (optional, for Material Design styling):
import 'mithril-materialized/index.css';
Use components in your app:
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
})
])
});
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 for examples and component APIs.
Note: The date range picker is now fully implemented with comprehensive validation and formatting support.
✅ Completed:
✅ Recently Completed (v3.2.x):
textarea
height to match TextInput components perfectlyData Display:
Input & Forms:
Navigation & Layout:
Developer Experience:
Performance & Optimization:
Current Status (v3.2.2):
Phase 1 Targets:
Long-term Goals:
We welcome contributions! Priority areas for community involvement:
See our contributing guide for detailed information.
Bundle Size Comparison:
Runtime Performance:
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 in case port 1234 is not occupied already.
The library includes carefully crafted CSS that provides Material Design styling without external dependencies. You can import the ready-to-use CSS:
import 'mithril-materialized/index.css';
Important: The CSS styling is completely independent of the original materialize-css. This means:
Tree-shakable CSS modules for optimal bundle sizes! Import only the CSS you need:
// 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 componentsadvanced.css
- Specialized components (carousel, sidenav, navbar, preloader)utilities.css
- Visual utilities (badges, cards, icons, toast, chips)Bundle Size Optimization:
core.css
+ specific modules for your use caseBuilt-in dark theme support with CSS custom properties:
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:
: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);
}
For advanced customization, you can use the SASS source files directly:
// 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:
// Customize Material Design variables
$primary-color: #2196F3;
$secondary-color: #FF9800;
// Then import the library
@import 'mithril-materialized/sass/materialize.scss';
The library includes these additional styles for enhanced functionality:
/* 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;
}