Skip to content
sorrowfengPublic

About

Material Design 3 (incl. M3 Expressive) component library for Qt Widgets, hand-painted with QPainter — no QSS.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

qt-md3

License: MIT Qt CMake C++ Release GitHub Stars Last Commit

English | 简体中文

qt-md3 is a C++ component library that reproduces Material Design 3 (including M3 Expressive) as native Qt Widgets. Everything is hand-painted with QPainter / QProxyStyle — no QSS, no QStyleSheet.

The goal is not a loose "Material-flavoured" look. Token values, component behavior, states, and motion are aligned item by item with the official design system:

Status

Version 0.1.0 — first public release. Stage 1 (all 36 official MD3 families) and Stage 2 (55 Qt extension headers) are landed.

Metric Value
Stage 1 MD3 families 36 / 36 ported
Stage 2 Qt extensions 55 public headers (appendix D closed)
Public headers 106 under src/widgets/
Foundation modules 21
CTest entries 94 (all green)
Gallery pages 55 + three product showcases
Supported Qt 5.15.2+ and 6.5.0+

Progress is tracked in docs/md3-coverage.md. Current state: docs/project-status.md. Screenshot gallery: docs/screenshots/.

Two stages, strictly serial

  1. Stage 1 — MD3 official components. All 36 component families from https://m3.material.io/components, with every property, variant, size, shape, state, token, motion spec, and keyboard behavior.
  2. Stage 2 — Qt desktop extensions. Common Qt controls that MD3 has no spec for, redesigned with Stage 1 tokens and semantics.

Stage 2 does not start until every Stage 1 family is green across all nine columns. A CTest gate (TestMd3CoveragePolicy) fails the build if a Stage 2 public component appears early.

The 36 Stage 1 families

Buttons · Button groups · Icon buttons · FABs · Extended FABs · FAB menu · Split buttons · Segmented buttons · Badges · Progress indicators · Loading indicator · Snackbar · Tooltips · Cards · Dialogs · Bottom sheets · Side sheets · Carousel · Divider · Lists · App bars · Toolbars · Navigation bar · Navigation rail · Navigation drawer · Tabs · Checkbox · Chips · Date pickers · Menus · Radio button · Sliders · Switch · Time pickers · Text fields · Search

Stage 2 Qt extensions (55 headers)

MdScrollBar · MdSelect · MdMessageBox · MdScrollArea · MdTable · MdAvatar · MdWindow · MdFileDialog · MdInputNumber · MdScaffold · MdMenuBar · MdStatusBar · MdSplitter · MdPagination · MdEmptyState · MdSkeleton · MdSteps / MdStepper · MdUpload · MdRate · MdFlex · MdGrid · MdSpace · MdCollapse · MdNotification · MdTree / MdTreeSelect · MdStatistic · MdPopover / MdPopconfirm · MdAutoComplete · MdColorPicker · MdDockWidget / MdDockManager · MdDescriptions · MdTimeline · MdImage · MdWatermark · MdTransfer · MdMentions · MdBackTop · MdInputDialog · MdStackedWidget · MdResult · MdBreadcrumb · MdQRCode · MdLog · MdCascader · MdPlainTextEdit · MdMasonry · MdDrawer · MdTour / MdCoachMark · MdRibbon · MdNav / MdNavItem · MdAffix / MdAnchor

API overview

Everything lives in the md namespace, class prefix Md. Include the widget header and link qt-md3::qt-md3.

#include <MdDesign.h>
#include <MdTheme.h>
#include <MdButton.h>
#include <MdFab.h>

int main(int argc, char *argv[])
{
    md::MdDesign::configureHighDpi();   // before QApplication
    QApplication app(argc, argv);
    md::MdDesign::initialize(&app);     // fonts, language, base font, RTL

    auto *button = new md::MdButton;
    button->setLabelText(QStringLiteral("Filled"));
    button->setColorStyle(md::ButtonColorStyle::Filled);
    button->setSize(md::ButtonSize::Medium);   // Expressive xsmall…xlarge

    // Theme is a singleton; every widget re-paints on themeChanged.
    md::MdTheme::instance().setThemeMode(md::ThemeMode::Dark);
    md::MdTheme::instance().setSeedColor(QColor(0x6750A4));
    md::MdTheme::instance().setDynamicColor(true);
    md::MdTheme::instance().setContrastLevel(md::ContrastLevel::High);
    ...
}

Naming and properties

Convention Rule
Namespace / prefix md / Md (MdButton, MdTheme, MdColorRole)
Enums named 1:1 with the official semantics; every enum ends with a Count sentinel
Configurable items every one is a Q_PROPERTY with a NOTIFY signal
States enabled / hovered / focused / pressed / disabled / selected / dragged / loading, as applicable
Themes light / dark, seed change, contrast level, density, RTL, font switch
Painting QPainter / QProxyStyle only — QSS is forbidden and gated

Key types

Header Role
MdDesign configureHighDpi() + initialize(&app) startup entry point
MdTheme singleton: mode, seed, dynamic colour, contrast, density, RTL, themeChanged
MdTokens md.ref.* / md.sys.* / md.comp.* token layers
MdColorScheme 49 colour roles, light and dark, including the *-fixed families
MdDynamicColor nine scheme variants resolved through the ColorSpec2021 solver
MdTypeScale 15 baseline + 15 emphasized styles, script-category line height
MdShape corner scale, radius interpolation, path morph
MdMotion 10 easings, 16 durations, six Expressive spring slots
MdIcon Material Symbols (variable font, four axes) + classic SVG fallback
MdStyleBase QProxyStyle hub: paint filters, theme subscriptions

A component is only “done” when its Definition of Done holds — see CONTRIBUTING.md.

Screenshot gallery

Selected light/dark captures live in docs/screenshots/: the three product showcases (Mail, Music, Settings), the dynamic-colour page, and a couple of component pages. Full-page PNGs of every gallery page can be regenerated at any time:

cmake --build build
build/examples/qt-md3-example --language en --theme light --screenshot build/shots-light
build/examples/qt-md3-example --language en --theme dark  --screenshot build/shots-dark

Each page produces two images: <nn>-<slug>.png (the window) and <nn>-<slug>-full.png (the page grown to its heightForWidth()). Prefer the -full one — the window shot only ever shows the first screenful. Capture from the native platform when text matters; QT_QPA_PLATFORM=offscreen renders tofu boxes on Windows.

Interactive gallery:

tools/run-gallery.sh                 # open the gallery
tools/run-gallery.sh --theme dark --dynamic

Design principles

  • Tokens over literals. Every color, radius, size, spacing, and duration comes from the theme. No magic values inside components.
  • Tonal elevation, not shadow. Layering is expressed with tonal surfaces; shadows appear only where the spec explicitly requires them.
  • State layer ≠ ripple. Hover and focus are static overlays; ripple only spreads on press and clips to the current shape.
  • Shape morph. Radii come from shape tokens and tween at runtime.
  • Dynamic color. Light and dark are tone mappings of one DynamicScheme; changing the seed color regenerates every role.
  • Script-aware typography. Line height adapts to the language script height class (Chinese is taller than Latin).
  • Expressive motion. Spring physics coexists with classic easing curves.
  • No QSS. Painting is QPainter only, enforced by a gate.

Requirements and support matrix

Qt 5.15.2+ Qt 6.5.0+
Compilers MinGW 8.1+, MSVC 2019+, Clang 10+ MinGW 11+, MSVC 2019+, Clang 12+, AppleClang 14+
Modules Core, Widgets, Svg (Test for tests) same
CMake 3.16+ 3.16+
C++ C++17 C++17
OS (CI) Linux, Windows Linux, Windows, macOS
Dynamic colour Yes Yes
Expressive springs Yes Yes
Material Symbols fonts Yes (Qt 5 renders the default instance; static weights preferred) Yes
RTL Yes Yes

CI matrix: Linux Qt 5.15.2 Debug ASan+UBSan, Linux Qt 5.15.2 shared Release, Windows Qt 5.15.2, Windows Qt 6.7.3, Windows Qt 6.7.3 shared Release, macOS Qt 6 shared Release.

Build

cmake --preset windows-msvc-qt6-debug
cmake --build --preset qt6-debug
ctest --preset qt6-debug

Or configure manually:

cmake -S . -B build -DQT_MD3_BUILD_EXAMPLES=ON -DQT_MD3_BUILD_TESTS=ON
cmake --build build --config Debug --parallel
ctest --test-dir build -C Debug --output-on-failure

With the Qt 6 MinGW kit:

cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug \
  -DCMAKE_CXX_COMPILER=C:/Qt/Tools/mingw1310_64/bin/g++.exe \
  -DCMAKE_PREFIX_PATH=C:/Qt/6.9.1/mingw_64 \
  -DQT_MD3_BUILD_EXAMPLES=ON -DQT_MD3_BUILD_TESTS=ON
cmake --build build
ctest --test-dir build --output-on-failure

With the Qt 5.15 kit, point QT5_CMAKE_PREFIX_PATH (or CMAKE_PREFIX_PATH) at the Qt 5 lib/cmake directory so CMake does not pick up Qt 6.

The library is static by default; pass -DBUILD_SHARED_LIBS=ON for a shared build. On Windows every executable gets the Qt runtime, the C++ runtime and the platforms/ + styles/ plugins copied next to it, so the example in build/ runs by double-click without a Qt-aware PATH. cmake --install additionally uses windeployqt. Pass -DQT_MD3_DEPLOY_EXAMPLE=OFF to skip both.

Install and consume

cmake --install build --config Release
find_package(qt-md3 CONFIG REQUIRED)
target_link_libraries(my_app PRIVATE qt-md3::qt-md3)

The installed package re-checks the minimum Qt version on the consumer side.

Project layout

src/core/       tokens, theme, color algorithms, type scale, shape, motion, icons
src/styles/     Md*Style painting classes
src/widgets/    public components (Md*.h)
src/private/    internal helpers (not exported)
examples/       the component gallery app
tests/          QTest + CTest, including the policy gates
resources/      icons, fonts, .qrc
docs/           status, audit, specs, TODOs, screenshots

Policy gates

Gate Enforces
TestMd3NoQss No QSS anywhere in src/, examples/, tests/, resources/
TestMd3CoveragePolicy All 36 families tracked; no Stage 2 components before Stage 1 is green
TestMd3SourceEncoding Every source file is valid UTF-8; no UTF-8 literal is decoded as Latin-1
TestMd3Deployment* Every executable starts with no Qt on PATH — the double-click case

Contributing

See CONTRIBUTING.md for the development flow, the component Definition of Done, the Qt 5 portability checklist, and the build/test commands. Please also read AGENTS.md and the Code of Conduct.

License

MIT. Ported or bundled third-party assets (Material Design tokens, Material Color Utilities, Material Symbols, Roboto) keep their own licenses — see NOTICE.md. This is an independent community project, not affiliated with or endorsed by Google LLC or The Qt Company Ltd.

About

Material Design 3 (incl. M3 Expressive) component library for Qt Widgets, hand-painted with QPainter — no QSS.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages