egui-material3 0.0.9

Material Design 3 components for egui with comprehensive theming support
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
# egui-material3

A Material Design component library for egui, providing Material Design 3 components with theme support.

## Screenshots

<img src="./resources/screenshot.png" alt="Material Design Components" width="600"/>

## What's New

### v0.0.9 (Latest)
- **Optimized Package Size**: SVG icon collections are now optional features, reducing default package size significantly
  - Enable only the collections you need: `svg_solar`, `svg_noto`, `svg_twemoji`
  - Or enable all with `svg_emoji` feature
- **Build Optimization**: SVG resources excluded from default package, downloaded on-demand during build when features are enabled

### v0.0.8
- **New Components**: ActionSheet, Badge, Breadcrumbs, Notification, Timeline, Toolbar, Tooltip, TreeView
- **Enhanced Components**: Button, Chip, and List now support small size variants
- **Improved Carousel**: Added mouse drag support for better interaction
- **Better Mobile Support**: Optimized DataTable padding for mobile UI

### v0.0.7
- **Spreadsheet Component**: Full-featured spreadsheet with DuckDB backend
- **Image Carousel**: New MaterialCarousel component
- **Small Controls**: Added size variants for buttons, chips, and lists

### v0.0.6
- Initial release with core Material Design 3 components

## Installation

Add egui-material3 to your project:

```bash
# Basic installation
cargo add egui-material3

# With optional features
cargo add egui-material3 --features ondemand
cargo add egui-material3 --features "svg_solar,spreadsheet"
cargo add egui-material3 --features svg_emoji  # All icon collections
```

Or manually in `Cargo.toml`:

```toml
[dependencies]
egui-material3 = "0.0.9"

# With features
egui-material3 = { version = "0.0.9", features = ["ondemand", "svg_solar"] }
```

## Usage

### Quick Start Example

```rust
use eframe::egui;
use egui_material3::{
    MaterialButton, MaterialCheckbox, MaterialSlider, MaterialChip,
    MaterialBadge, MaterialSwitch, ButtonVariant,
    theme::{setup_google_fonts, setup_local_fonts, setup_local_theme,
           load_fonts, load_themes, update_window_background}
};

fn main() -> Result<(), eframe::Error> {
    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default().with_inner_size([800.0, 600.0]),
        ..Default::default()
    };

    eframe::run_native(
        "Material Design App",
        options,
        Box::new(|cc| {
            // Setup Material Design fonts and themes
            setup_google_fonts(Some("Roboto"));
            setup_local_fonts(Some("resources/MaterialSymbolsOutlined.ttf"));
            setup_local_theme(None); // Use default theme

            // Load fonts and themes
            load_fonts(&cc.egui_ctx);
            load_themes();

            // Apply theme background
            update_window_background(&cc.egui_ctx);

            Ok(Box::<MyApp>::default())
        }),
    )
}

#[derive(Default)]
struct MyApp {
    checked: bool,
    switch_on: bool,
    slider_value: f32,
    chip_selected: bool,
}

impl eframe::App for MyApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            ui.heading("Material Design Components");

            // Buttons with different variants
            ui.horizontal(|ui| {
                ui.add(MaterialButton::new("Filled").variant(ButtonVariant::Filled));
                ui.add(MaterialButton::new("Outlined").variant(ButtonVariant::Outlined));
                ui.add(MaterialButton::new("Text").variant(ButtonVariant::Text));
            });

            // Input controls
            ui.add(MaterialCheckbox::new(&mut self.checked, "Check me"));
            ui.add(MaterialSwitch::new(&mut self.switch_on, "Enable feature"));
            ui.add(MaterialSlider::new(&mut self.slider_value, 0.0..=100.0));

            // Chips and badges
            ui.horizontal(|ui| {
                ui.add(MaterialChip::new("Filter chip")
                    .selected(&mut self.chip_selected));
                ui.add(MaterialBadge::new().value(5).show(ui, |ui| {
                    ui.add(MaterialButton::new("Inbox"));
                }));
            });
        });
    }
}
```

### Advanced Example

Here's a more comprehensive example showcasing recent additions:

```rust
use egui_material3::{
    MaterialButton, MaterialBadge, MaterialToolbar, MaterialBreadcrumbs,
    MaterialNotification, MaterialTimeline, MaterialTooltip, MaterialTreeView,
    ButtonVariant, TimelineItem, TreeNode,
};

impl eframe::App for MyApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            // Toolbar with actions
            ui.add(MaterialToolbar::new()
                .title("My Application")
                .add_action("search", || println!("Search"))
                .add_action("settings", || println!("Settings")));

            // Breadcrumb navigation
            ui.add(MaterialBreadcrumbs::new()
                .add_item("Home", || println!("Home"))
                .add_item("Projects", || println!("Projects"))
                .add_current("Current Project"));

            // Badge example
            ui.horizontal(|ui| {
                ui.add(MaterialBadge::new().value(3).show(ui, |ui| {
                    ui.add(MaterialButton::new("Messages"));
                }));

                // Tooltip example
                MaterialTooltip::new("Click to refresh").show(ui, |ui| {
                    ui.add(MaterialButton::new("Refresh")
                        .variant(ButtonVariant::Outlined));
                });
            });

            // Notification
            ui.add(MaterialNotification::new("Update available")
                .description("Version 2.0 is ready to install")
                .add_action("Update", || println!("Updating..."))
                .closable(true));

            // Timeline
            let events = vec![
                TimelineItem::new("Project created").with_timestamp("2024-01-01"),
                TimelineItem::new("First commit").with_timestamp("2024-01-02"),
                TimelineItem::new("Version 1.0 released").with_timestamp("2024-02-01"),
            ];
            ui.add(MaterialTimeline::new(events));

            // TreeView for hierarchical data
            let tree = vec![
                TreeNode::new("Root")
                    .add_child(TreeNode::new("Child 1"))
                    .add_child(TreeNode::new("Child 2")
                        .add_child(TreeNode::new("Grandchild"))),
            ];
            ui.add(MaterialTreeView::new(tree));
        });
    }
}
```

## Theme System

The library provides comprehensive Material Design 3 theming capabilities:

### Build-time Theme Inclusion

Themes are automatically included from JSON files during compilation:

```rust
use egui_material3::theme::{setup_local_theme, load_themes};

// Uses themes from resources/ and examples/ directories automatically
setup_local_theme(None);
load_themes();
```

### Runtime Theme Loading

Load custom themes dynamically:

```rust
use egui_material3::theme::{setup_local_theme, load_themes};

// Load specific theme file
setup_local_theme(Some("path/to/my-theme.json"));
load_themes();
```

### Theme Modes and Contrast Levels

Dynamically change theme appearance at runtime:

```rust
use egui_material3::theme::{get_global_theme, update_window_background, ThemeMode, ContrastLevel};

// Switch between light and dark modes
if let Ok(mut theme) = get_global_theme().lock() {
    theme.theme_mode = ThemeMode::Dark; // or ThemeMode::Light
    theme.contrast_level = ContrastLevel::High; // Standard, Medium, or High
}
update_window_background(ctx);

// Or toggle mode with a button
if ui.add(MaterialButton::new("Toggle Dark Mode")).clicked() {
    if let Ok(mut theme) = get_global_theme().lock() {
        theme.theme_mode = match theme.theme_mode {
            ThemeMode::Light => ThemeMode::Dark,
            ThemeMode::Dark => ThemeMode::Light,
        };
    }
    update_window_background(ctx);
}
```

### Component Size Variants

Many components support size variants for different design needs:

```rust
use egui_material3::{MaterialButton, MaterialChip, ButtonSize, ChipSize};

// Small button for compact UIs
ui.add(MaterialButton::new("Compact").size(ButtonSize::Small));

// Standard size (default)
ui.add(MaterialButton::new("Standard"));

// Small chips for tags
ui.add(MaterialChip::new("Tag").size(ChipSize::Small));
```

## Available Components

### Input & Selection

- **MaterialButton** - Material Design buttons with multiple variants (filled, outlined, text, elevated, tonal) and size options
- **MaterialIconButton** - Icon buttons (standard, filled, filled tonal, outlined, toggle)
- **MaterialCheckbox** - Checkboxes following Material Design guidelines
- **MaterialSwitch** - Toggle switches
- **MaterialRadio** / **MaterialRadioGroup** - Radio button groups with list tile support
- **MaterialSlider** / **MaterialRangeSlider** - Sliders with Material Design styling
- **MaterialSelect** - Dropdown selection components with menu alignment options
- **MaterialChip** - Filter, assist, input, and suggestion chips with size variants

### Navigation & Layout

- **MaterialTabs** - Tab navigation (primary and secondary variants)
- **MaterialDrawer** - Navigation drawers (permanent, dismissible, modal, standard)
- **MaterialTopAppBar** - App bars and toolbars (standard, center-aligned, medium, large)
- **MaterialToolbar** - Flexible toolbar component with action items
- **MaterialBreadcrumbs** - Breadcrumb navigation for hierarchical paths
- **MaterialMenu** - Context menus and menu items with nested support

### Feedback & Information

- **MaterialDialog** - Modal dialogs and alerts
- **MaterialSnackbar** - Toast notifications with optional actions
- **MaterialNotification** - Notification cards with actions and dismissal
- **MaterialBadge** - Badge indicators for counts and status
- **MaterialProgress** - Progress indicators (circular and linear)
- **MaterialTooltip** - Contextual tooltips with rich text support
- **MaterialActionSheet** - Bottom sheets for action selection

### Data Display

- **MaterialCard2** - Material Design cards (elevated, filled, outlined variants)
- **MaterialList** - Lists following Material Design patterns with visual density control
- **MaterialDataTable** - Data tables with sorting, selection, and custom cell content
- **MaterialSpreadsheet** - Full-featured spreadsheet with DuckDB backend (requires `spreadsheet` feature)
- **MaterialTimeline** - Timeline component for chronological data
- **MaterialTreeView** - Hierarchical tree view with expand/collapse

### Media & Content

- **MaterialCarousel** - Carousel for displaying items in a scrollable view with mouse drag support
- **MaterialImageList** - Image lists with online/offline support and smart caching (standard, masonry, woven variants)
- **MaterialLayoutGrid** - Grid layout with tile bars
- **MaterialFab** - Floating Action Buttons (primary, secondary, tertiary, surface, branded)

### Icons & Symbols

- **MaterialIcon** - Material Design icons with font support
- **MaterialSymbol** - Material Symbols rendering (outlined, rounded, sharp variants)

## Common Patterns

### Building a Complete UI

Combine components to create rich user interfaces:

```rust
use egui_material3::*;

impl eframe::App for MyApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        // Top app bar
        egui::TopBottomPanel::top("top_bar").show(ctx, |ui| {
            ui.add(MaterialTopAppBar::new()
                .title("My App")
                .add_action("notifications", |ui| {
                    // Badge on icon button
                    MaterialBadge::new().value(5).show(ui, |ui| {
                        ui.add(MaterialIconButton::new("notifications"));
                    });
                }));
        });

        // Navigation drawer
        egui::SidePanel::left("drawer").show(ctx, |ui| {
            ui.add(MaterialDrawer::new()
                .add_item("Home", "home", || println!("Home"))
                .add_item("Settings", "settings", || println!("Settings")));
        });

        // Main content
        egui::CentralPanel::default().show(ctx, |ui| {
            // Action buttons with tooltips
            ui.horizontal(|ui| {
                MaterialTooltip::new("Create new item").show(ui, |ui| {
                    if ui.add(MaterialButton::new("New")
                        .variant(ButtonVariant::Filled)).clicked() {
                        // Show action sheet
                        self.show_action_sheet = true;
                    }
                });
            });

            // Data display with cards
            ui.add(MaterialCard2::elevated()
                .show(ui, |ui| {
                    ui.heading("Recent Activity");
                    ui.add(MaterialTimeline::new(self.recent_events.clone()));
                }));

            // Notifications
            if self.has_updates {
                ui.add(MaterialNotification::new("Update available")
                    .add_action("Install", || self.install_update())
                    .closable(true));
            }
        });

        // Bottom action sheet
        if self.show_action_sheet {
            ui.add(MaterialActionSheet::new()
                .add_action("Create Document", || println!("Document"))
                .add_action("Create Folder", || println!("Folder"))
                .on_dismiss(|| self.show_action_sheet = false));
        }

        // FAB (Floating Action Button)
        egui::Area::new("fab")
            .anchor(egui::Align2::RIGHT_BOTTOM, egui::vec2(-16.0, -16.0))
            .show(ctx, |ui| {
                if ui.add(MaterialFab::primary().icon("add")).clicked() {
                    println!("FAB clicked");
                }
            });
    }
}
```

### Form with Validation

Create forms with Material components:

```rust
ui.vertical(|ui| {
    ui.label("User Information");

    // Text inputs with validation
    ui.add(MaterialTextField::new(&mut self.name)
        .label("Full Name")
        .required(true));

    // Selection controls
    ui.add(MaterialSelect::new(&mut self.country)
        .label("Country")
        .options(vec!["USA", "UK", "Canada"]));

    // Checkboxes for preferences
    ui.add(MaterialCheckbox::new(&mut self.newsletter,
        "Subscribe to newsletter"));

    ui.add(MaterialCheckbox::new(&mut self.terms,
        "I agree to the terms"));

    // Action buttons
    ui.horizontal(|ui| {
        if ui.add(MaterialButton::new("Submit")
            .variant(ButtonVariant::Filled)
            .enabled(self.terms)).clicked() {
            self.submit_form();
        }

        ui.add(MaterialButton::new("Cancel")
            .variant(ButtonVariant::Text));
    });
});
```

## Optional Icon & Emoji Collections

The library provides three comprehensive SVG collections as optional features. Each can be enabled independently:

- **Solar Icons** (`svg_solar`) - ~1,200 UI/UX icons with variants
- **Noto Emoji** (`svg_noto`) - ~3,600 Google emojis with skin tone and gender variants
- **Twemoji** (`svg_twemoji`) - ~3,700 Twitter emoji

### Feature Configuration

Choose the collections you need:

```toml
[dependencies]
# Enable individual collections (recommended - smaller binary size)
egui-material3 = { version = "0.0.9", features = ["svg_solar"] }

# Or enable specific combinations
egui-material3 = { version = "0.0.9", features = ["svg_solar", "svg_noto"] }

# Or enable all collections
egui-material3 = { version = "0.0.9", features = ["svg_emoji"] }
```

### Usage

Icons and emojis are accessible through HashMaps with O(1) lookup:

```rust
use egui_material3::svg_emoji::{SOLAR_ICONS, NOTO_EMOJIS, TWEMOJI};

// Access Solar icons (requires svg_solar feature)
if let Some(svg) = SOLAR_ICONS.get("home") {
    // Use SVG data for rendering
}

// Access Noto emoji (requires svg_noto feature)
// Filename format: "emoji_u" + unicode codepoint
if let Some(svg) = NOTO_EMOJIS.get("emoji_u1f600") {
    // 😀 Grinning face emoji
}

// Access Twemoji (requires svg_twemoji feature)
// Filename format: unicode codepoint
if let Some(svg) = TWEMOJI.get("1f600") {
    // 😀 Grinning face emoji
}
```

**Note**: SVG files are embedded at compile time when features are enabled. If building from crates.io (not git), files are automatically downloaded during build.

## Features

### OnDemand Feature

Enable online image support for `MaterialImageList`:

```toml
[dependencies]
egui-material3 = { version = "0.0.9", features = ["ondemand"] }
```

The `MaterialImageList` component supports multiple image sources:

```rust
use egui_material3::image_list;

// Local image files
ui.add(image_list()
    .columns(3)
    .item_spacing(8.0)
    .items_from_paths(glob::glob("resources/*.png")?));

// Online images (requires 'ondemand' feature)
ui.add(image_list()
    .columns(4)
    .item_spacing(8.0)
    .items_from_urls(vec![
        "https://example.com/image1.jpg".to_string(),
        "https://example.com/image2.png".to_string(),
    ]));

// Embedded images from byte arrays
ui.add(image_list()
    .columns(2)
    .item_spacing(8.0)
    .items_from_bytes(vec![
        include_bytes!("image1.png").to_vec(),
        include_bytes!("image2.png").to_vec(),
    ]));
```

Key capabilities:
- **Smart caching**: Downloaded images cached locally with correct file extensions
- **Format detection**: Automatically detects PNG, JPEG, GIF, and WebP formats
- **Efficient loading**: Images downloaded once and reused from cache
- **Performance optimized**: UI repaints only when new images available
- **Error handling**: Graceful fallback with visual indicators for failed loads

### Spreadsheet Feature

Enable spreadsheet components with DuckDB backend:

```toml
[dependencies]
egui-material3 = { version = "0.0.9", features = ["spreadsheet"] }
```

The spreadsheet feature provides:

- **MaterialSpreadsheet** - Full-featured spreadsheet widget with DuckDB backend
- **Column types**: Text, Integer, Real, Boolean
- **File formats**: Import/export CSV, Excel (xls/xlsx), Parquet formats
- **Async loading**: Background data loading with progress indicators
- **Data manipulation**: Full SQL query support via DuckDB

```rust
use egui_material3::{MaterialSpreadsheet, SpreadsheetDataModel, ColumnDef, ColumnType};

// Create spreadsheet with column definitions
let columns = vec![
    ColumnDef { name: "Name".to_string(), col_type: ColumnType::Text, width: 150.0 },
    ColumnDef { name: "Age".to_string(), col_type: ColumnType::Integer, width: 80.0 },
    ColumnDef { name: "Score".to_string(), col_type: ColumnType::Real, width: 100.0 },
];

let mut model = SpreadsheetDataModel::new("my_table", columns)?;

// Import data from CSV/Excel/Parquet
model.import_file("data.csv", FileFormat::Csv)?;

// Display in UI
ui.add(MaterialSpreadsheet::new(&mut model));
```

## Examples

The crate includes comprehensive examples demonstrating all components:

```bash
# Complete showcase of all Material components with theme switching
cargo run --example widget_gallery_example

# Real-world data table implementation with Nobel Prize data
cargo run --example nobel_prizes_example

# Interactive component gallery (recommended for exploration)
cargo run --example stories

# SVG icon demonstration (requires svg_solar feature)
cargo run --example svg_icon_demo --features svg_solar
```

### Stories Example - Component Explorer

The `stories` example provides an interactive gallery with individual showcases for each component:

**Input & Selection**: actionsheet, button, checkbox, chips, iconbutton, radio, select, slider, switch
**Navigation**: breadcrumbs, drawer, menu, tabs, toolbar, topappbar, treeview
**Feedback**: badge, dialog, notification, progress, snackbar, tooltip
**Data Display**: card2, datatable, list, spreadsheet, timeline
**Media**: carousel, imagelist, layoutgrid, svgemoji, symbol

Each story window demonstrates component variants, states, and common usage patterns.

### Standalone Examples

```bash
# OnDemand example - demonstrates online image loading
cd examples/ondemand && cargo run

# Package example - standalone deployable app with bundled resources
cd examples/package && cargo run
```

### Running with Features

```bash
# Run with spreadsheet support
cargo run --example stories --features spreadsheet

# Run with all SVG icon collections
cargo run --example stories --features svg_emoji

# Run with specific features
cargo run --example stories --features "ondemand,svg_solar"
```

## Documentation

- [API Documentation]https://docs.rs/egui-material3
- [Material Design 3 Guidelines]https://m3.material.io/
- [Examples]./examples/

## Contributing

Contributions are welcome! Please check the [issues](https://github.com/nikescar/egui-material3/issues) for open tasks or create a new one.

## License

Licensed under either of:

- Apache License, Version 2.0 ([LICENSE-Apache-2.0]LICENSE-Apache-2.0 or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT]LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

---

<details markdown>
<summary>Development Notes</summary>

## Todos

* SVG sprite support
* Bump egui_extras to match resvg version (currently using patched 0.47)
* Additional component variants
* Performance optimizations for large datasets

</details>