material_3_expressive 1.1.4
material_3_expressive: ^1.1.4 copied to clipboard
A faithful Flutter implementation of the Material 3 Expressive component set, exposed as direct M3E component widgets.
1.1.4 #
Changed #
- Sliders: sizes XS–XL (tracks 16 / 24 / 40 / 56 / 96, handles 44 / 44 / 52 /
68 / 108). Active track and handle are primary; inactive track is secondary
container. Stops are 4 with 4 trailing space (on secondary container on
the inactive end). Press and keyboard focus pinch the handle to 2; there is
no focus ring, and hover does not paint a fill. At the end of the track the filled
cap uses the outer corner. An inset icon stays at its end and springs to the other
side of the thumb when that spot is too small.
wavelengthandwaveSpeedupdate a wavy track while it runs. Vertical sliders take the same stops as horizontal ones (divisions,dotSize,dotSpacing,dotBuilder). The value indicator is 48×44, fully rounded, inverse surface. Arrows move 1% (or one stop); Space+arrow moves 10% (or one stop); Home and End jump to the ends. Inset icons on M, L, and XL move to the other track segment when they do not fit. - Toolbars: docked and floating bars are 64 tall. Docked padding is 16, with action gaps that prefer 32 and shrink toward 4. Floating padding is 8 with a 4 gap, a pill shape, and elevation level 3 (docked stays 0). Horizontal floating margin is 16; vertical is 24. The paired FAB is 56 (icon 24) expanded and 80 (icon 28) collapsed, 8 from the bar, at the same elevation. Standard content is surface container / on surface variant, with secondary container for a selected toggle and the FAB. Vibrant content is primary container / on primary container, with surface container when selected and a tertiary container FAB. One emphasis action stays primary. Disabled content is on surface at 0.38. Arrows move between actions. Focus rings hide on pointer input. Scroll-exit does not run together with collapse-to-FAB. At 600 and wider, docked actions can sit evenly, centered, or at the edges.
- Focus rings: hover, scroll, and press hide every keyboard focus ring as soon as the pointer interaction starts. Tab and the arrow keys show it again.
- Navigation drawer: standard sheet is surface at elevation 0; modal sheet is
surface container. Width 360, height fills the parent, end corners 16.
Destinations are 56 tall with a 336×56 pill inset 12 and a 28 icon
origin. Active icon and label are on secondary container (label weight 700);
inactive icon and label are on surface variant. The pill is secondary
container. Hover is 0.08, focus and press are 0.1. Press uses InkSparkle.
The focus ring is secondary, 3 thick, inset 3, and hides when any
pointer interaction starts. Arrows move focus. Enter and Space select. A modal drawer opens from a button,
slides with the expressive spatial spring, and dismisses on a destination, the scrim,
a drag toward the start edge, or system back. A dismissible standard drawer closes
only from its menu. Sections are separated by an outline divider. Trailing badge
labels and an optional semantic label are supported.
M3ENavigationDrawerControllerselects, opens, and closes the drawer. - Navigation rail: collapsed width 96 (narrow 80), expanded 220–360.
Collapsed items are 64 (56 without a label) with a 56×32 pill. Expanded
items are 56 tall; the pill hugs the icon and label unless it fills the rail.
Container is surface at elevation 0. Horizontal body scroll switches it to
surface container at elevation 1, and offset 0 restores both. Active icon
is on secondary container, active label on surface, pill secondary container.
Arrows move focus. Enter and Space select, including the current destination. A modal
rail opens from a button, dismisses on the scrim, Escape, or system back, and leaves
no collapsed rail behind. Hide when collapsed opens already expanded and stays
expanded until it is dismissed. The destination list adds
destinationTopPadding(12) under a menu, FAB, or leading control, and drops that gap when those controls are absent.M3ENavigationRailControllerselects, expands, and shows the immersive rail. An optional divider sits on the content edge. - Lists: expressive defaults. One / two / three-line heights 56 / 72 / 88. Padding **16×10
*, slot gap 12, icons 20.
M3EListStyle.segmentedrests at 16 outer / 4 inner corners; hover, focus, press, drag, and selection use 16 all around.M3EListStyle.standardhas no resting container. Baseline rows stay square until selected, and 56 / 72 stay middle-aligned. Leading slots: avatar 40, image 56, video 100×56 and 114×64. Divider uses outline. Trailing icons use on surface. State layers: hover 0.08, focus * 0.1, press 0.1, drag 0.16, disabled 0.1, plus the inset focus ring.M3EListis the only list widget (M3ECardList,M3EDismissibleList,M3EDismissibleColumn, andM3EExpandableListare removed). Selection, variant, and reorder stay on the list. Swipe, expand, andM3EListItem.transformstay on the item. A sub-list expansion is a nestedM3EListthat inherits the parent corner join, fill, and variant.M3EExpandableExpanded.transformstill morphs an expandable row (M3EExpandableListController). Tab stops on the first and last rows; arrows walk a row, then its trailing actions. A dismissible row with swipe actions and no trailing widget shows a more icon. A dragged row lifts to level 4, shows the drag handle in the leading slot, and commits when the drag ends. - App bars: small content band is 64, with the system inset outside that band. Flexible
medium is 112 (136 with a subtitle) and flexible large is 120 (152 with a
subtitle). Baseline medium stays 112 / 136 and baseline large is 152 / 184. The
container is surface at elevation 0, and switches to surface container at elevation *
3* when content scrolls under it. Scrolling back to the top restores both. Overlay scrollables
do not clear that state. Top and search bars take the same
variantas the sliver, default * small*. One title, subtitle, image, or search field moves inside the bar from the action row to the band below. A title with no leading control starts 16 in from the edge.M3EAppBarHideMode.entireslides the whole bar away.M3EAppBarHideMode.actionsslides the container away and leaves each action floating on its own surface container high fill.hideOnScrollstill means the whole bar. The search field is 56 tall, stadium 28, elevation 0. Its hint followscenterTitle, andwrapActionsgroups the pill's leading and trailing with that hint.M3EAppBarController(expand,collapse,show,hide,followScroll) drives the bar. A small bar does not rebuild on every scroll pixel. Scrollables on another route, and an idle list on desktop, do not clear the scrolled color or elevation. An auto hide slide follows the scroll and does not rebuild the page on the way down, so the bar and the body do not twitch. After a refresh replaces the list's scroll position, scrolling still updates the bar color and elevation. A bar that hides on scroll (entire,actions, orhideOnScroll) keeps its resting color, elevation, and search field color; only a bar that stays shows the scrolled-under state. In actions hide, the floating actions are part of the page, so they slide and fade with route transitions instead of showing ahead of them, and they stay tappable after the bar slides away. The bar follows every scroll step, including the sub-pixel steps of a slow drag, instead of waiting for half a pixel per event. A collapsingtitleTextis laid out once and scaled between its two sizes instead of being re-shaped every scroll frame.preferredSizeof a top or search bar is its expanded height, so the bar collapses and expands in the same frame as the scroll. The sliver bar collapses and hides by exactly the scrolled distance, so its edge stays on the content. A top or search bar does the same when itsScaffoldsetsextendBodyBehindAppBar: true: the bar keeps a fixed slot and only its surface moves. Without that flag the body moves with the bar, and hiding stays a timed slide. - Carousel: multi-browse, uncontained, uncontained multi-aspect, hero, and full-screen. Items
are
M3ECarouselItemvalues (image, optionaltitle/subtitle/prefixText,onTap,showScrim,transform). A nullonTapdisables the item.M3ECarouselControllersteps withnextandprevious, moves withanimateToItemandjumpToItem, and opens the list withshowAll. Uncontained multi-aspect uses the same shrink-and-scroll motion as uncontained; each item's width still follows its aspect ratio. Dynamic text follows the item's current size on every frame of the scroll. Large slots keep the title and subtitle. Medium slots hide the title. A small slot showsprefixTexton the subtitle line. The text stays aligned to that live size. Hero and contained horizontal insets are 16 on both sides. Uncontained tracks have no container inset. Items shrink to the shrink extent as they leave, then scroll off; the trailing item fills the leftover space and meets the edge once it reaches that extent. The item gap is the item's own padding and stays visible while the item is larger than the shrink extent. Settling does not resize the track again. Small slots stay 40–56. Hover elevation 1, focus ring **secondary ** at 3 with a 2 offset. The ring follows the tap pulse, clears when you tap outside, and is not clipped at the track edge. InkSparkle paints on the item. Disabled content is 0.38. A swipe advances one item unlessfreeScrollis true, which drags and snaps to the nearest item. The outgoing uncontained item scrolls fully off the leading edge. Full-screen items fill the viewport, keep that size while scrolling, parallax the image, and meet with no gap.isExtendedapplies to contained only. Tab and arrows move between items. Show all and the header arrow morph the carousel into a vertical list. An item withtransformmorphs after the tap pulse. Reduced motion turns off parallax and size changes. Pass aM3ECarouselControllerto callanimateToItem. - Navigation bar: flexible size is 64 and baseline 80 is the default. Vertical
items share the width; the active pill is 56×32 behind the icon. Horizontal items
start at 600 wide, use the widest label, and wrap that label in a 40 pill with
16 side insets. Horizontal items keep an 8 gap (
wideItemGap). Start and end alignment inset that group from the bar edge by the same 8 (wideEdgePadding). The container is surface container high at elevation 0. The active label is on surface, the active icon is on secondary container, and the pill is secondary container. Inactive content is on surface variant. State layers use on secondary container at 0.08 hover and 0.1 focus and press, painted on the full pill. The selected pill is opaque as soon as the destination changes; its width still springs from the center. The focus ring is secondary, 3 thick, inset 3, and a pointer tap dismisses it. Arrow keys move focus. Space or Enter selects, including the active destination.M3ENavigationBarControllerselects a destination and, withhideOnScroll, shows or hides the bar from the page's scroll controller. A screen reader never hides the bar. The system inset stays padding inside the colored bar. - Tabs: primary label-only and secondary bars are 48; primary icon plus label is 64.
Container is surface at elevation 0, with a 1dp outline-variant divider inside that
height. Primary active content is primary; secondary active content is on surface;
inactive content is on surface variant and becomes on surface on hover, focus, and press.
State layers are 0.08 hover and 0.1 focus and press. The primary indicator is 3dp,
top corners 3, inset 2, at least 24 long. The secondary indicator is 2dp, square,
and spans the slot. Icons on secondary tabs lead the label by 8. Scrollable tabs start
52 from the leading edge. Arrow keys move focus, Space or Enter selects, and a pointer tap
dismisses the inset focus ring.
M3ETabsControllerselects a tab.M3ETabsViewswipes between bodies.M3ETabs.sliverscrolls away and returns on an upward scroll. - Tooltips: a plain tooltip stays off its anchor and ignores the pointer, so the cursor on an icon button does not twitch between pointer and arrow.
- Interaction: hover stays off while a scrollable is moving, so a fast fling does not flash the controls under the pointer.
- Focus rings: a pointer tap hides the keyboard focus ring on every component until the next Tab or arrow key.
- Cards:
verticalstacks media above the text. Tab order is the card (when it is tappable), then its actions and overflow, then a revealed swipe action. Arrow keys show or hide that swipe action, and Escape closes it. Space or Enter activates the focused control. Keyboard focus keeps the secondary ring and the 10% state layer. Swipe can dismiss, reveal a leading or trailing action, or do both. A partial swipe settles open on a background action; a longer swipe or flick dismisses the card. Actions and overflow keep their own taps when the card is tappable. Outlined fill is surface. Content padding is 16 on every side. Media and an edge-to-edge divider sit outside that inset; a padding divider lines up with it on both sides. Heights follow the variant elevation table (elevated hover is level 2). Focus ring is secondary, 3dp thick, * 2dp* outside the edge. Disabled elevated and filled containers fade to 0.38. Optional media, text, actions, overflow, dividers, one swipe action, and a card group (gap 8, grid, staggered, list, carousel, reorder). A swipe springs the whole card off-screen or back. Reorder lifts the card, springs neighbors into the opening, then settles before the order changes.openBuilderruns a full-screen container transform.
1.1.3 #
Changed #
- Menus: vertical and baseline only (
M3EMenuVariant,M3EMenuSelectionMode). Vertical row 48, item radius 12, group padding 4, 4 between items, group gap 2. Opening focuses the first enabled item. Up/Down move, Left/Right open or close a submenu, letters typeahead, Escape closes, Enter or Space activates. Multi-select stays open. - Toolbars: floating
alignmentplaces the pill;screenOffset(theme default 16) insets it on every side. Docked toolbars ignore both. - Overlays:
M3EOverlayHistorycloses an open menu, dropdown, split popup, or FAB menu on the next back before the route pops. - Navigation: selection pills on the bar, rail, and drawer scale in place (spatial spring, width 0.4 to 1) and fade with the effects spring. The indicator no longer stretches between destinations.
- Dividers: thickness 1, color outline variant; full-width, inset
(16 / 0), and middle inset (16 / 16). End margin 8,
bottom margin 8, and supporting-text gap 4 are theme tokens and stay
off unless
outerMarginis set (the text gap is applied by the caller). Decorative, so the line is excluded from semantics. - Chips: height 32, radius 8, text padding 16; assist label
on surface and leading icon primary; stroke outline variant;
filter and input selected container secondary container; focus ring
secondary, 3dp, 2dp offset; InkSparkle; remove target 48
(own Tab stop when the chip also acts) and minimum width 88; elevated
level 1, dragged level 4.
M3EChipGroup: arrows move focus; Backspace or Delete removes a focused input chip. - Switches: track 52×32; handle 16 off / 24 on or with an icon / 28 pressed; state layer 40; target 48; selected icon primary; hover, focus, and press handle primary container / on surface variant; disabled selected handle surface; focus ring on the handle (secondary, 3dp, 2dp offset); InkSparkle on the handle; drag past the midpoint toggles; semantics role switch.
- Radio buttons: icon 20 (stroke 2, dot 10); state layer 40;
target 48; unselected icon on surface variant (on surface when
hovered, focused, or pressed); pressed state layer swaps (selected
on surface, unselected primary); InkSparkle on the control; semantics
role radio.
M3ERadioGroup: Tab / Shift+Tab enter on the selected radio (or the first / last if none is selected); arrows move, select, and wrap; Space does nothing when that radio is already selected. - Checkboxes: container 18 / corner 2 / icon 18; state layer
40 circle; target 48; selected outline 0; unselected outline
on surface variant (on surface when hovered, focused, or pressed);
pressed state layer swaps (unselected primary, selected on surface);
focus ring secondary, 3dp thick, 2dp offset; InkSparkle on the
control; disabled selected icon surface; semantics role checkbox
(checked / mixed). Default
checkIconPaddingis zero. - Snackbars: single/two-line min heights 48 / 68; start pad 16,
end 8 with action/close; optional close (24 / pad 12); actionable or
closable bars do not auto-dismiss (plain default 4s); one-at-a-time
via
M3ESnackbarController; InkSparkle on action/close; polite live region; Esc dismisses when focused; elevation Level 3. - Tooltips: plain min height 24 / pad 8×4; rich pad 16/12/16/8;
title on surface variant; plain dismiss instant / rich 1.5s
after leave (themable); placement
plain above / rich bottom-end with 8dp on-screen steps;
persistentrich (tap/controller);M3ETooltipController;M3ETooltipPlacement; one open tooltip at a time; semantics tooltip. - Breaking — badges: colors Error / On error; small 6dp /
large min 16dp (pad 4 / radius 8); type labelSmall 11 / 500 / 16 /
0.5; Compose placement
smallOffset6×6 /largeOffset12×14 (replacesdefaultOffset); defaultmaxCount999; optionallabel(preferred overcount); RTL mirrors trailing/leading; a11y “New notification” / “One new notification” / “{n} new notifications”. Overlay layout does not expand or shift the child (nav icons stay aligned). - Progress indicators: track color secondary container (linear +
circular); circular gap 4dp; linear stop flush (trailing space 0) with
4dp host end inset; optional
showTrack(default true); a11yprogressBar+semanticsLabel/semanticsValue; linear RTL mirror (circular unchanged). - Breaking — loading indicator: remove
elevation(widget, theme, and path shadow). Refresh host elevation stays onM3ERefreshIndicator. - Loading indicator: instance
indicatorSize/containerWidth/containerHeight,containerShape(ShapeBorder, theme defaultCircleBorder),indicatorColors(morph-interpolated; exclusive withcolor), and ratio-preservingsize(outer; active = size × 38/48; debug assert outside 24–240). A11y roleprogressBar. Keep legacycontainerRadiusgetter. - Bump
material_uito^1.4.0(Dart SDK^3.13.0). - Breaking — FAB menus: require 2–6 items; theme paddings
leading/trailing 24, icon–label 8, between items 4, close↔items
8 (replaces
itemHorizontalPadding/ old gaps). Close button 56 / icon 20; closed size followsM3EFabSize. Color sets: filled close + container items fromM3EFabColor(surface→primary). Initial focus on close (“Toggle menu”, expanded/collapsed); Tab walks items; Escape closes. Spring exit reverse; short viewports scroll items behind close. AddM3EFabMenuControllerand per-itemopenBuildercontainer transform. - Breaking — Extended FABs: add
M3EExtendedFabSize(small56 /medium80 /large96; default small). Icon is optional; label is required (no icon-only). Per-size paddings (medium leading/trailing 26), radii 16/20/28, and label type titleMedium / titleLarge / headlineSmall.M3EExtendedFabThemeresolves via size metrics; min width 80. AddM3EExtendedFabController(scroll collapse/expand, appear morph, container transform), focus ring 3dp / 2dp /secondary, TapRegion focus clear, and disabled muted colors (shared with FAB). - Breaking — FABs:
M3EFabSize.mediumis now 80dp / icon 28 / radius 20 (was 56/24/16). AddM3EFabSize.regular(56/24/16) for the baseline size. Default size remainsmedium. Add filled color stylesprimaryFilled/secondaryFilled/tertiaryFilled; existingprimary/secondary/tertiarystay as container roles. AddM3EFabController(scroll show/hide, appear morph, container transform), focus ring 3dp / 2dp gap /secondary, and disabled muted colors. - Split buttons — align to M3E size tokens: pressed inner corners match hovered (8/12/12/20/20); between-space always 2dp; optical vs centered trailing pads; small leading icon 20dp; standard-motion chevron 180°; trailing a11y expanded/collapsed + “More options”; shared button colors with state-layer-only open trailing (no toggle recolor).
- Segmented buttons — align to M3E Outlined tokens: density
(
M3ESegmentedButtonDensity0/−1/−2/−3 → 40/36/32/28dp), ≥48dp target, disabled outline/content opacities (0.12 / 0.38), focus ring 3dp /secondarywith 2dp gap, single-select cannot clear, multi-select allows empty, a11y radio/checkbox semantics, and theme overrides for selected fill, focus, and optionalmaxWidth. - Breaking — buttons: fold toggle selection into
M3EButtonvia caller-controlledisSelected,selectedIcon, andselectedLabel;M3EToggleButton,M3EToggleButtonDecoration, andM3EToggleButtonThemeare removed. Toggle text buttons are no longer supported. - Breaking — button groups: rename the component module from
toggle_button_grouptobutton_group; group actions now useisSelected,selectedIcon, andselectedLabel, and group decoration usesM3EButtonDecoration. Theme access moves fromtoggleButtonGroupThemetobuttonGroupTheme. All actions render asM3EButton(icon-only, text-only, or icon+label);M3EButtonGroupItemKindandM3EButtonGroupAction.iconButtonare removed — useminWidthfor icon-button-like resting widths. Connected groups span their surface with equal-width segments (optionalbuttonGroupTheme.maxWidthcap); standard between-space follows size tokens (18 / 12 / 8 / 8 / 8) and connected gap is 2dp. - Breaking — button groups density:
M3EButtonGroupDensityis nowregular/comfortable/compact/dense(spec levels 0 / −1 / −2 / −3). Density adjusts container height (−4dp per level), not between-space. Hover keeps resting shape; press morphs corners / neighbour squish. - Button groups — align standard spacing and connected corner tokens per
size; add
selectionRequiredandmultiSelect(withselectedIndices/onSelectedIndicesChanged); use the 1400/0.9 neighbour-squish spring; keep keyboard traversal on Tab order without capturing arrow keys; and keep all actions at a uniform group-managed height for each size. Elevated button groups remain available but are not recommended. - Bump
material_uito^1.3.0. - Raise Flutter SDK constraint to
>=3.47.0(FVM pin3.47.0) formaterial_ui1.3.0compatibility. - Buttons — align
M3EButtondefaults to Material 3 Expressive size / color / shape tokens: XS leading/trailing 12dp and icon–label gap 4dp; outline widths 1 / 1 / 1 / 2 / 3 (XS→XL); outlined outline roleoutlineVariantand label/icononSurfaceVariant; disabled container / outline opacity 0.1; shape spring default stiffness 1400 / damping 0.9 (M3EButtonTheme.shapeSpring, overridable via decoration motion); hover keeps resting corners (press morph only); pressed state layer 0.1 with defaultInkSparkle; labelmaxLines1 (up to 2 at ≥200% text scale). - Icon buttons — align
M3EIconButtonto M3E size / color / shape tokens: square radii 12 / 12 / 16 / 28 / 28, pressed 8 / 8 / 12 / 16 / 16; outline widths 1 / 1 / 1 / 2 / 3; outline roleoutlineVariant; full default/toggle color roles; disabled 0.1 / 0.38; shape spring 1400 / 0.9; hover keeps resting; pressed state layer 0.1 +InkSparkle; keyboard focus ring only (no sticky focus fill). Selected toggle icons use per-size icon tokens (20 / 24 / 24 / 32 / 40). Breaking: defaultvariantis nowfilled.
1.1.2 #
Added #
- Keyboard focus rings via foundations
M3EFocusRing,M3EFocusRingTheme(M3EThemeData.focusRingTheme), andM3EFocusInteraction. Rings follow each control’s outer shape and show for keyboard focus; pointer interaction clears them until Tab/arrow navigation resumes. Text fields and search bars keep their focused border and show the outset ring. M3EThemeData.keyboardFocusIndicatorsto globally enable/disable focus-ring chrome.- Focus rings / keyboard activation across actionable hosts (buttons, icon / toggle / split buttons, cards, lists, switches, dropdowns, sliders, nav bar / rail / drawer, text fields, search, checkboxes, radios, chips, FABs / FAB menu, segmented buttons, tabs, menus, expandable headers, and more).
- Example Focus rings playground (View tab).
- List-owned selection and reorder on
M3ECardList/M3ECardList.builder(selection,reorder,selectionController,onSelectionChanged,onReorder,selectionState,reorderState), selection and reorder on dismissible lists, and selection / reorder on expandable header rows (nested sublists keep their own list APIs; expanded rows snap-collapse for reorder). Theme tokens:M3EListSelectionState,M3EListReorderState, enumsM3EListSelectionMode/M3EListSelectionTrigger. - Dismissible swipe actions via
leadingActionsBuilder/trailingActionsBuilderandM3EListSwipeAction(icon pills, preview snap, primary auto-execute). Style tokens onM3EDismissibleListStyle/M3EListDismissibleTheme(spacing, edge padding, preview threshold, overdrag, min sizes). - Expandable nested expansions via
M3EExpandableExpanded.list/.contentonM3EExpandableData.expanded;embeddedon card / dismissible lists for inner corner radii when nested. M3EDropdownMenu.limit(int?, defaultnull= unlimited) to cap multi-select count (limittakes precedence overmaxSelectionswhen set).- Configurable spatial springs on component themes (defaults match prior
hard-coded motion), including switch position/size, FAB menu expand/shape,
nav rail indicator/icon scale, checkbox pulse, slider dock, icon button
morph, toolbar expand/label, list card
radiusSpring, dismissible neighbour / re-engage / detach / roundness / spring-back / fly /collapseDamping, and refreshsettleSpring. - Export
M3EOverflowStrategy,M3ENoOverflowStrategy, andM3EScrollOverflowStrategyforM3EButtonGroup.overflowStrategy.
Changed #
- Bump
material_uito^1.1.1. M3EDropdownMenu.openMotion/closeMotionare nullable; when null they resolve fromM3EDropdownMenuTheme.openSpring/closeSpring.- Dropdown field selected-value text defaults to
bodyMedium(wasbodyLarge); chip delete icon size follows the chip label font size. - Prefer
M3EThemeData.focusRingThemefor package-wide focus ring overrides; legacyM3EButtonTheme.focusRingWidth/focusRingGap/focusRingColorremain for compatibility. - Button-family focus clearance uses
focusRingTheme/M3EFocusRing.outsetOfinstead of hardcoded primary constants. - Icon buttons and navigation rail destinations use
SystemMouseCursors.clickwhen enabled.
Fixed #
- Focus interaction: primary-focused control only; rings clear on pointer and resume on keyboard; pointer down requests focus so Tab continues from the last clicked control; menus/dropdowns trap Tab; Escape closes overlays / unfocuses fields; keyboard focus scrolls into view when rings are allowed.
- Expandable list: Tab traverses expanded sublist rows after the header; collapsed / mid-animation bodies stay out of the focus order.
M3EFocusRingkeeps a stable tree when togglingfocusedsoEditableTextis not remounted (Tab-focus text fields stay editable).- Search bar keeps the editing row mounted under idle chrome;
M3ESearchAnchor.barparticipates in Tab with Enter/Space to open and Escape to close. - FAB menu focus scope skips as a Tab stop, focuses the first item on open,
and closed-loops Tab across items; FAB menu no longer depends on inherited
theme during
initStatefor item springs. - Web:
ButtonActivateIntentsupport onM3ETappableand navigation destinations (Enter activation). - Date picker: mode-toggle / month labels ellipsize under narrow width;
dialog actions use
OverflowBarso cancel/confirm wrap instead of overflow. M3EStateLayerOverlayInkWell no longer steals a second tab stop underM3ETappable.- Dropdown selected chips and trailing clear are keyboard Tab stops with focus rings.
1.1.1 #
Added #
- M3-aligned typography foundation:
M3ETypographypairs 15 baseline and 15 emphasized type scales (md.sys.typescale.*and.emphasized.*), token tables for static and variable-font sets,M3ETypefaceConfig(brand/plain families), andM3EVariableFontConfigfor per-roleopsz,wght, splitROND, and emphasized-onlyGRAD.M3EThemeData.typographyis the source of truth;typeScaleremains a baseline alias for components. M3EVariableFontAxesfor explicitwght,opsz,ROND,wdth,slnt,GRAD, and advanced Y-axis values with global/brand/body group overrides onM3EVariableFontConfig.M3ETypeStyleConversionconverts arbitraryTextStyles to baseline, emphasized, or variable token variants;M3ETypeStyleTokens.copyWithandfromTextStylecustomize individual token fields.M3ETypeVariations.gradedalias clarifies the weight+grade axis preset vs the M3 emphasized type scale.M3EMaterialAppacceptstypeScaleMode,typeface, andvariableFont.- Example Typography playground (View tab) with live axis and conversion controls.
- Export
buildM3EThemeDefaults()andM3EDynamicColorHostthroughfoundations.dart. M3EHourMinuteTextFieldfor Material-aligned hour/minute time inputs (used by the input time picker; exported from the time pickers entry).M3ENavigationBarwide layout APIs:autoLayout,layout(M3ENavBarLayout),alignment(M3ENavBarAlignment),iconBehavior(M3ENavBarIconBehavior), optionalwideBreakpointandwideDestinationWidth, plusM3ENavBarConstants(default chip width128, documented 5-destination breakpoint,minWideBarWidth). Destinations may be icon-only and/or label-only. Wide chips use a fixed width so the fluid pill does not clip when icons or labels appear or disappear.M3ENavigationRailexpandTooltip/collapseTooltipfor the expand/collapse toggle (defaults'Expand'/'Collapse').M3EFabandM3EExtendedFaboptionalelevation/hoverElevationoverrides;M3ENavigationRailFabSlotforwards them to the rail FAB.
Changed #
- Typography additions are additive;
M3EThemeData.typeScaleremains a baseline alias for components. - Foundations sources grouped under
lib/foundations/{color,shape,theme,type,interaction,tokens}/; the public barrel path is unchanged for consumers. - Date and time pickers aligned closer to Material dialog specs: landscape dialog sizing (12/24-hour), standardized content padding, unified action bars, calendar/year responsive layouts (year mode toggle stacked in the calendar parent), dial help-text layout, and input-time fields with labels under the boxes and AM/PM top-aligned with the hour/minute row.
M3EYearPickerno longer takesmode/onModeChanged— the mode header lives on the parent calendar. Call sites that passed those arguments should drop them (the built-inM3ECalendarDatePickeralready hosts the toggle).M3ENavBarConstants.wideBreakpointdefault is sized for five fixed-width wide chips (704at the default128chip width) instead of a flat600. WhenwideBreakpointis omitted on the bar, autoLayout usesminWideBarWidthfor the current destination count and chip width.- README: document
M3ENavigationBarwide-layout public surface and samples.
Fixed #
- Date picker landscape/year layouts: year grid overflow and vertical stretch,
header alignment with calendar and actions, help text compact only in input
entry mode (
alignHelpWithSubHeader). - Time picker landscape dial: help text no longer covered by hour/minute fields; input mode field geometry matches filled Material time inputs.
- Complete public surface exports from all component entry files so
import 'package:material_3_expressive/material_3_expressive.dart'is sufficient: missing themes/decorations (app bar, FAB, navigation drawer, icon button shapes, button motion/overflow, split button decorations), tokens/utils (slider, toolbar, carousel scroll helper, progress indicator, navigation rail layout), dismissible list extension APIs, picker composables (date/time form fields, headers, actions), carousel view/controller/wrapper, toolbar building blocks, and button-group overflow controller. - Export missing public enums and models from component entry files so the
barrel alone is enough: button style/size/shape, FAB color/size, split
button enums, navigation bar / rail enums and models, and
M3EButtonGroupActionfrom the toggle button group entry. M3EDropdownMenu: do not fireonSelectionChangeduringdidUpdateWidgetrebuilds when the selection did not actually change (lifecycle / build-phase safe).
Chore #
- Remove redundant deep imports in library, example, and tests now covered by
entry / barrel exports (
unnecessary_import/ analyzer cleanup).
1.1.0 #
Documentation #
- README: document current public APIs for
M3ERefreshIndicator(controller, pad/reveal, elevation, contained spinner),M3ELoadingIndicator(elevation,rotationTurns, colors),M3ECheckboxlabel/sizing options,M3EProgressIndicatorstroke overrides, anddynamic_color2.x /material_ui^1.1.0harmonization notes.
Fixed #
- Compatible with
dynamic_color2.x (material_ui): drop duplicateColorScheme.harmonizedextension; re-export package harmonization; tests use local channel mocks (test_utilsmoved todynamic_color_testing). - Nav bar, rail, and drawer selection pills remasure on size / constraint changes (window resize); stale geometry cache no longer blocks morphs to other destinations.
M3ERefreshIndicatorpointer-pull platforms (Flutter web and native desktop): mouse drag, 1:1 pointer deltas, host reveal/arm math (2 × indicatorPaddingdelay, arm at full reveal), list pad hard-capped atcontentDragOffsetwith safe leading underscroll clamp. Web also uses Opacity+scale reveal, split rebuilds, andRepaintBoundaryso CanvasKit does not freeze. Mobile keeps classic overscroll deltas.M3ERefreshIndicatorexpressive and contained kinds always useM3ELoadingIndicatorcontained variant so shell elevation works on all platforms (avoids morph-pathdrawShadow, which freezes CanvasKit).M3ERefreshIndicatorControllerattach/detach uses one stable show closure (fresh method tear-offs are neveridentical), so dispose clears correctly and manualshow()does not hit disposed animation controllers after keyed rebuilds; keyed variant switches still keep the newer attachment.
1.0.9 #
Added #
M3ESafeArea— keyboard-aware system insets from raw view metrics (paddingOf,topOf/bottomOf/leftOf/rightOf, andoverlayBottomOffor floating overlays). Docked chrome, snackbar, search, nav rail indicator, and dialog inset hosts use it instead ofMediaQuery.viewPaddingOf.M3EDialogInset— pads dialogs with screen margin and optional keyboard view insets (Material Dialog behavior).M3EDialogTheme.resizeToAvoidBottomInset(default true),insetAnimationDuration, andinsetAnimationCurve.M3ECheckboxoptionallabel,boxSize,hitSize,checkedChild,uncheckedChild, andcheckIconPadding(default right inset for optical centering of the built-in check), with a spatial-spring pulse on value changes.M3EProgressIndicator.circular/.linearoptionaltrackStrokeWidth(and.linearstrokeWidth) so all kinds can override track and value thickness.M3ERefreshIndicator.contentDragOffset— caps list top padding while pulling (defaults to indicator height +2 * indicatorPadding).M3ERefreshIndicator.indicatorPadding— vertical gap above/below the spinner in the list pad (default 8); reveal starts after2 ×this value.M3ERefreshIndicatorTheme.releaseBubbleSpring/releaseBubbleFromScale(and matching widget overrides) for the release scale bubble (defaults stiffness 350 / damping 0.1 / from-scale 0.96).M3ELoadingIndicator.elevation(theme default0) — contained uses rounded-shell [M3EElevation] shadows; uncontained casts a path shadow that follows the morphing polygon (including rotate / scale / morph).M3ELoadingIndicator.rotationTurns— when set, disables auto spin and morph pulse so a host (e.g. refresh) can drive rotation.M3ELoadingIndicator.color/containerColordocument shape vs contained shell colors (both overridable).M3ERefreshIndicatorControllerto trigger refresh programmatically (same as MaterialRefreshIndicatorState.show).
Fixed #
M3ECheckboxcheck mark is centered in the box (with default optical padding on the built-in check icon).M3EProgressIndicator.linearWavyhonorslinearSizefor stroke thickness; linear painters draw track and active with separate stroke widths.M3EButtonGrouplabeled actions with distinctcheckedLabelno longer blank for a frame when the parent rebuilds a newactionslist on selection change. Measured widths are kept across remotion, and layout signatures ignore visual-only decoration / widget identity noise.M3ERefreshIndicatorlocks resting inset on refresh; release bubble is scale-only (does not move layout). Short pulls cancel withoutonRefresh.M3ECardoutlined variant defaults to a transparent fill (border only); list surfaces that useM3ECardinherit this unless an explicit color is set.- Time dial minutes: drag selects any 0–59; tap snaps to nearest ×5; interstitial
selector dot when between labels (Material
_Dialbehavior). - Time AM/PM control uses Material portrait / landscape / input sizes and sits beside dial/input hour–minute fields (not a button row below input).
- Date range input fields are side-by-side (8dp gap), matching Material.
- Date, date-range, and time picker entry-mode toggles sit at the bottom-left of the dialog actions row (Material time-picker placement).
- Date and time entry-mode icons use
keyboard_outlined(calendar/clock when returning from input). - Time picker manual entry no longer autofocuses the hour field.
M3EDialogInset+M3EDialogTheme.resizeToAvoidBottomInset(default true) shift dialogs above the keyboard; opt out via theme orresizeToAvoidBottomInset: falseonM3EDialog.show/ date / time pickers.
Changed #
- Internal
klin_dartcompliance: splitM3EInputTimePickerFormFieldbuild helpers to clear cognitive complexity (no behavior change). M3EExpressiveLoadingIndicatorapplies a noticeable scale pulse (spatial spring) to the active polygon holder on each morph — not the outer container. Morph rotation defaults are slower (45° / cycle, slower spring); timing and springs are configurable via widget params andM3ELoadingIndicatorTheme.M3ERefreshIndicatordefaultdisplacementis 8 (top padding). List pad defaults to spinner height + 16. Scale/fade/downward reveal lags until pad reaches2 × indicatorPadding, then fills through full visibility.onRefreshruns only when fully revealed and the pointer is released.M3ETimePickerThemeperiod sizes align with Material (periodPortraitSize52×80,periodLandscapeSize216×38,periodInputSize52×72).- Vendor/source attribution headers removed from
lib/Dart sources; third-party notices remain inNOTICEonly.
1.0.8 #
Added #
M3EDimensions— shared spacing (4dp grid) and corner-radius catalog.M3ESpacing.regularandM3EShapesradius tokens forward to it.- Shape catalog helpers:
M3EShapeKind,M3EShapeClipper, andM3EShapeContainer(named constructors for all 35 expressive polygons). Clip paths come fromM3EMaterialNewShapesmorph polygons. - Example gallery: copyable Dart snippets on every playground (live with current controls). Wide split view highlights the active catalog row with the same fill and radius spring as selection list cards.
Fixed #
M3EButtonGroupno longer jumps whenselectedIndexchanges while using the default scroll overflow. Fitting groups keep an unclipped, non-scrolling viewport; overflowing groups keep their scroll offset across rebuilds.
Changed #
- Depend on
material_ui^1.0.0and importpackage:material_ui/material_ui.dartinstead ofpackage:flutter/material.dart. Flutter SDK constraint is>=3.44.0.
1.0.6 #
Added #
- Multi-select host
M3ESelectionwithM3ESelectionController,M3ESelectionAppBar,M3ESelectionLeading,M3ESelectionScope, andM3ESelectionTheme. OptionalselectedColor/ themehighlightColorfill selected rows;M3ECardListandM3EDismissibleListpick that fill up automatically when hosted under the selection scope. - Gradient decorations on action surfaces:
backgroundGradient,foregroundGradient,overlayGradient, andoutlineGradientonM3EButtonDecoration,M3EToggleButtonDecoration,M3EIconButtonDecoration,M3EFabDecoration, andM3ESplitButtonDecoration(plus trailing-segment gradient overrides). M3ESegmentedButtonThemeoutline, divider, selected/unselected fill, and foreground colors/gradients. Dividers can sample a group-widedividerGradient.M3EFabMenu.decoration(M3EFabDecoration) for the trigger FAB, plusM3EFabMenuThemeitem fill, foreground, and outline gradients.M3EBadge.alignment(M3EBadgeAlignment.topLeft/topCenter/topRight). The badge sizes itself to the child's box; no parentSizedBoxis required.M3ETextField.inputFormatters.M3ETextFieldVariantandM3ETextFieldThemeare exported from the package barrel.M3ECarousel.onChangewithM3ECarouselChangeDetails(leading / focal index).M3ESplitButton.m3eMenuBuilderfor a rich M3E menu tree (groups, dividers, submenus).M3EButtonDecoration.animationDurationis honored by split segments (defaults toDuration.zeroso radius morph stays on the spring).- Search idle
alignment/barAlignment(M3EAppBar.searchdefaults to center). ToolbarfabExpandsToolbarandpillActiveSpring. - List
colorBuilder/borderRadiusBuilder, plus spring radius motion when a selected card's corners change. Card list / list itemvariantandborder. M3ETypeScale.applyfor shared typography (family, fallback, package, size factor/delta, color, decoration,fontVariations).withColordelegates toapply.M3ETypeVariationsis an enum of Roboto Flex presets (.variations: regular, emphasized, condensed, extra condensed, wide, extra wide, round).M3EThemeData.copyWith(fontFamily:)/fontFamilyFallback/package/fontVariationsand the same fields onM3EMaterialApp.- Example gallery: catalog-driven playgrounds, palette theme-config screen (auto theming, dynamic color, five seed colors, font family and M3 Expressive type styles).
Fixed #
M3ETextFieldno longer grows when the focused stroke thickens (border is painted as a foreground decoration). Height grows withmaxLines. Empty labels sit vertically centered; unlabeled values sit vertically centered.- Split-button foreground gradients tint text/icons instead of filling the segment; trailing radius morphs immediately after the menu closes when a background gradient is set.
- Button gradient outlines no longer expand into unbounded height.
- Selection highlight color (
selectedColor/highlightColor) now reaches hosted list rows.
Changed #
- Example app shell uses the playground catalog under
example/lib/pages/playground/and a theme config route from the home app bar.
1.0.5 #
Fixed #
M3ESwitch— pressed thumb now bleeds into left/right track padding (matching vertical edge contact); defaultthumbSizePressedistrackHeight(32).M3EExpressiveLoadingIndicator— morph settle usesM3EMotion.expressiveSpatialDefault(keeps droppy overshoot velocity).- Dropdown menu search field — defaults to
surfacefill and panelcontainerRadius(was unfilled with item outer radius). - Navigation bar, drawer, and rail destinations —
SystemMouseCursors.clickon desktop/web hover. - Classic circular indeterminate progress — shares wavy circular rotation and sweep timing (flat arcs unchanged).
M3ESlider/M3ERangeSlider— tap outside clears focus viaTapRegionandM3EFocus.tapOutsideHandler.M3EMenu— no longer autofocuses the first item on open; popup focus scope is still focused so keyboard navigation works without a pre-highlight.
Changed #
M3EIconButton— hover radius morph (with press), aligned with button-style state listening; themeradiusHoveredtokens.M3ESearchBarTheme.maxWidthdefault isdouble.infinity(full-width layouts).
1.0.4 #
Added #
- Shared foundations haptics API (
M3EHapticFeedback,M3EHaptics) withnone/light/medium/heavyimpact levels plusselection()for discrete snaps. - Opt-in haptic wiring across
M3ETappable, buttons, icon buttons, navigation destinations, carousel item taps, dismissible lists, and related surfaces (defaults tonone). - Selection haptics on stepped slider tick changes.
- Dismissible list haptic hooks on tap and swipe-action commit (defaults to
none). M3ESlider/M3ERangeSlidercornerRadius(theme defaulttrackCornerRadius= 8) — fixed outer track radius, not derived from thickness.M3ESwitchthumb-centered state layer (stateLayerSizeon widget/theme, default 48) for hover/focus/press.- Toolbar scroll-exit / manual visibility via
M3EToolbarVisibilityControllerandM3EToolbarScrollBehavior. - Toolbar action selection via
activeIndex/onActiveIndexChanged, labeled action width springs, and FAB expand/collapse icons with pill↔FAB morph. M3EFabMenuexpand/collapse icons, size morph (80↔56), andM3EFabMenuPosition(left/right).M3EIconButton.visualSizefor layout-driven visual size overrides.
Fixed #
- Classic linear and wavy linear/circular indeterminate progress indicators — dual traveling segments with track gaps (linear) and spin + sweep (circular wavy); classic circular indeterminate unchanged.
- Switch thumb press feedback now shows the Material concentric translucent state-layer circle.
Changed #
- Internal analyze /
klin_dartcompliance refactors (progress controller sync, toolbar build/scroll helpers, carousel wrapperpartsplits) with no intentional public API or behavior breaks. - Default slider outer track corners use fixed radius 8 (previously half of track thickness).
1.0.3 #
Fixed #
- Re-implement
M3ECarouselWrapperpulse logic to use a sliding clip window instead ofTransformscaling, ensuring content remains stable and does not snap during animations. - Introduce
_stableInnerContentExtentto calculate fixed layout sizes for carousel items based on viewport constraints and flex weights. - Update
ContainmentPagein the example app to demonstrate image-based carousel items with gradient overlays and labels. - Add sample image assets to the example project and update
pubspec.yamlto include the assets directory. - Enhance documentation for
M3ECarouselWrapperparameters and internal state management.
1.0.2 #
Fixed #
- Platform tags — declare all six Flutter platforms in
pubspec.yamlso pub.dev lists iOS and Web (dynamic color still no-ops where unsupported).
1.0.1 #
Fixed #
- License detection —
LICENSEis now a clean OSI-recognized MIT text so pub.dev awards the license points; third-party and vendored attributions live inNOTICE. - Date / range / time picker dialogs — landscape layouts no longer stretch to the screen edge; dialogs use bounded height and wrap content correctly.
- Landscape picker sizing — slightly wider dialog and title panel defaults for date, range, and time pickers.
- Vertical
M3EDivider— fills the parent’s bounded height again so it renders in rows (for example the containment gallery demo).
Changed #
- Internal refactors for analyzer /
klin_dartcompliance (file and complexity splits) with no intentional public API breaks.
1.0.0 #
Initial release.
A faithful Flutter implementation of the Material 3 Expressive component set,
exposed as direct M3E* widgets with spring-driven motion and design tokens
via M3ETheme.
Added #
- 39 component modules spanning the official Material 3 groups:
- Actions — buttons, icon buttons, FAB, extended FAB, FAB menu, button groups, segmented buttons, split buttons, toggle buttons.
- Communication — badges, linear & circular progress indicators, loading indicator, snackbar, tooltips.
- Containment — cards, carousel, dividers, lists, dialogs (standard & full-screen), bottom sheets, side sheets.
- Navigation — top & bottom app bars (incl. search), tabs, navigation bar, navigation rail, navigation drawer, toolbars, menus.
- Selection — checkbox, radio button, switch, chips, sliders (incl. wavy), dropdown menus, date picker, time picker.
- Text inputs — text fields, search bar / search view.
- Direct component API — construct each
M3E*widget directly; enums and models are exported from a single library import. - Design token foundations — a centralized
foundationslayer for color schemes, typography, motion/spring physics, shapes, elevation, and state layers, provided through theM3EThemeinherited widget. - Expressive motion — spring-driven press feedback, shape morphing, liquid
selection indicators, and M3-accurate hover/focus/press state layers via the
shared
M3ETappableinteraction primitive.