Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
c67dc15
feat: match the 2026 iOS, Android and Chrome settings look
yadaniyil Sep 24, 2026
844739e
feat(ios): add an iOS 26+ Liquid Glass switch drawn in Flutter
yadaniyil Sep 24, 2026
e865e84
chore(example): drop the signing team from the iOS project
yadaniyil Sep 24, 2026
be0322e
Move agent instructions to AGENTS.md
yadaniyil Sep 21, 2026
93b0fd4
fix: wire up brightness, alignment, paddings and empty sections
yadaniyil Sep 24, 2026
4f17a1d
docs: update README, AGENTS.md and add llms.txt for 4.0.0
yadaniyil Sep 24, 2026
d0d275e
chore: keep AGENTS.md out of the published package
yadaniyil Sep 24, 2026
47c57fe
style(example): format for the Dart 3.12 language version
yadaniyil Sep 24, 2026
f9973b5
feat: add a GNOME (libadwaita) style for Linux
yadaniyil Sep 24, 2026
7326b0c
feat(example): add a GNOME Settings Power replica and URL launch options
yadaniyil Sep 24, 2026
de4066f
feat: add a macOS System Settings style
yadaniyil Sep 24, 2026
677d25d
docs: document the GNOME style for Linux
yadaniyil Sep 24, 2026
bc66de3
feat(example): add a macOS System Settings replica and a macOS runner
yadaniyil Sep 24, 2026
0de139b
feat: add a Windows 11 (Fluent) style for DevicePlatform.windows
yadaniyil Sep 24, 2026
b0741a5
feat(example): add a Windows 11 Display settings replica
yadaniyil Sep 24, 2026
5ebf15d
docs: document the Windows 11 style and FluentSettingsSwitch
yadaniyil Sep 24, 2026
12fe16c
docs: document the macOS style and MacosSettingsSwitch
yadaniyil Sep 24, 2026
50e68fd
Merge branch 'feat/linux-style' into integration/4.0-all
yadaniyil Sep 24, 2026
a36ea13
test: cover the macOS style inside a CupertinoApp
yadaniyil Sep 24, 2026
9a2abab
fix: don't tint a macOS row while its switch is held
yadaniyil Sep 25, 2026
5b69839
Merge branch 'feat/windows-style' into integration/4.0-all
yadaniyil Sep 25, 2026
2a1129c
Merge branch 'feat/macos-style' into integration/4.0-all
yadaniyil Sep 25, 2026
186b86a
style(test): format two tests the same way on Dart 3.12 and 3.13
yadaniyil Sep 25, 2026
087093a
fix(ios): fit tile descriptions to the width the tile gets
yadaniyil Sep 25, 2026
662838a
refactor(list): resolve the list style through an inheritable config
yadaniyil Sep 25, 2026
b066d65
feat(theme): add selected tile and list pane colors
yadaniyil Sep 25, 2026
8d97b0c
feat: add SettingsSplitView and SettingsDestination
yadaniyil Sep 25, 2026
60ffbf0
feat(example): add a split view demo
yadaniyil Sep 25, 2026
a716168
docs: document the split view and destinations
yadaniyil Sep 25, 2026
3b5dec7
Merge branch 'feat/split-view' into integration/4.0-all
yadaniyil Sep 25, 2026
f90a032
feat(split): support the macOS, Windows and GNOME styles in SettingsS…
yadaniyil Sep 25, 2026
bdd648a
feat: add AdwaitaPanDownIcon for GNOME combo rows
yadaniyil Sep 25, 2026
178db8a
feat(example): match the GNOME 48+ Power page with its two tabs
yadaniyil Sep 25, 2026
e1752e6
style(test): format a list test the same with Dart 3.12 and 3.13
yadaniyil Sep 25, 2026
b80f36b
fix: match real Windows 11 Settings screenshots in the Windows style
yadaniyil Sep 25, 2026
5c04ead
fix(example): align the Windows Display replica's title with Settings
yadaniyil Sep 25, 2026
d4210f0
fix: leave 30pt after a footer in the macOS style
yadaniyil Sep 25, 2026
a6abc3e
fix(example): match the real macOS toolbar and pop-up rows
yadaniyil Sep 25, 2026
bf5d5ab
docs: note the macOS spacing after footers in AGENTS.md
yadaniyil Sep 25, 2026
e0cb660
Merge branch 'feat/linux-style' into integration/desktop
yadaniyil Sep 25, 2026
f7d5a05
Merge branch 'feat/windows-style' into integration/desktop
yadaniyil Sep 25, 2026
fdba5cf
feat(example): add a showcase screen for the README images
yadaniyil Sep 25, 2026
5147dd2
docs(example): list the showcase launch screen
yadaniyil Sep 25, 2026
3c2ec5d
Merge branch 'feat/macos-style' into integration/desktop
yadaniyil Sep 25, 2026
6ba1ce6
test(split): check the macOS footer spacing in a split view's detail …
yadaniyil Sep 25, 2026
0d46188
fix(example): keep the showcase switch check visible on Android
yadaniyil Sep 25, 2026
b5b1877
fix(split): let the keyboard focus move between the panes
yadaniyil Sep 25, 2026
eb238fe
feat(split): give the macOS, Windows and GNOME styles their own split…
yadaniyil Sep 25, 2026
caccd5c
feat(example): show System, Windows and GNOME Settings in the split v…
yadaniyil Sep 25, 2026
cdbe600
fix(split): create the Windows pane pill controller in initState
yadaniyil Sep 25, 2026
085eb0a
docs(split): describe the macOS, Windows and GNOME split views
yadaniyil Sep 25, 2026
4458d0b
fix(split): start keyboard focus in the list pane
yadaniyil Sep 25, 2026
bd4b4e9
Merge branch 'integration/desktop' into integration/4.0-all
yadaniyil Sep 25, 2026
334c671
fix(example): size the showcase icons for the desktop sidebars
yadaniyil Sep 25, 2026
df951cf
chore: stop tracking flutter-settings-ui.iml
yadaniyil Sep 25, 2026
e5f7d9f
chore(release): keep build output and unused images out of the package
yadaniyil Sep 25, 2026
7346399
chore(pubspec): complete the description, add links, topics and scree…
yadaniyil Sep 25, 2026
9173ed7
docs(llms): list everything 4.0 adds, fix the header claim, add known…
yadaniyil Sep 25, 2026
1bf2ff0
fix(theme): make a forced brightness dark or light on Android and web
yadaniyil Sep 25, 2026
df08247
docs(changelog): fix the iOS header claim, credit contributors, list …
yadaniyil Sep 25, 2026
47efbc0
docs(readme): correct the theme table, the platform default and a sni…
yadaniyil Sep 25, 2026
3dfc3aa
docs(agents): write down the release order
yadaniyil Sep 25, 2026
a1b314c
fix(tiles): make disabled iOS, Android and web tiles ignore the keyboard
yadaniyil Sep 25, 2026
81e76ec
fix(split): handle back for routes pushed from the list pane in one pane
yadaniyil Sep 25, 2026
c179f9a
fix(split): let a re-keyed view take over its controller
yadaniyil Sep 25, 2026
9ffcc50
fix(split): build the Windows compact rail without MaterialLocalizations
yadaniyil Sep 25, 2026
1752364
docs(lib): document the 3.x API that pub.dev showed without docs
yadaniyil Sep 25, 2026
7dd9fb0
fix(split): forget removed pages and follow custom-section tiles
yadaniyil Sep 25, 2026
68de561
fix(tiles): give every switch the tile title as its semantics label
yadaniyil Sep 25, 2026
35bb3c4
fix(macos): keep the button role of a disabled row with onPressed
yadaniyil Sep 25, 2026
02df917
fix(split): put the selected state on the desktop sidebar rows
yadaniyil Sep 25, 2026
6314643
fix(sections): host Material widgets and style custom tiles on Window…
yadaniyil Sep 25, 2026
6833573
fix(example): don't crash the split view demo in the Fuchsia style
yadaniyil Sep 25, 2026
9160830
fix(linux): let go of a GNOME row's pressed fill when a scroll starts…
yadaniyil Sep 25, 2026
335a052
fix(linux): make the GNOME switch knob follow a finger from where it …
yadaniyil Sep 25, 2026
4b0cc5c
fix(example): make the demo switches toggle
yadaniyil Sep 25, 2026
e17011e
feat(example): open the showcase from the gallery
yadaniyil Sep 25, 2026
9ae6e2e
fix(example): keep the Windows showcase avatar inside the rail item
yadaniyil Sep 25, 2026
ff0dfb5
fix(example): open --route screens without a navigation error
yadaniyil Sep 25, 2026
ea5a076
fix(example): follow dark mode in the Material 3 demo and Android rep…
yadaniyil Sep 25, 2026
b43e2d5
fix(example): keep the macOS replica's toolbar below a phone's status…
yadaniyil Sep 25, 2026
506dd54
docs(example): replace the Flutter boilerplate README
yadaniyil Sep 25, 2026
4c07a06
docs(tiles): correct the SettingsTile field docs
yadaniyil Sep 25, 2026
bd1b8af
feat(example): add the Linux runner
yadaniyil Sep 25, 2026
971af63
fix(split): desktop sidebar keyboard: arrows, clicks, switches, rings
yadaniyil Sep 25, 2026
a40aa38
fix(split): keep the keyboard focus across layout changes
yadaniyil Sep 25, 2026
ab9123b
chore: ignore coverage/
yadaniyil Sep 25, 2026
b6a460b
fix(split): let go of a sidebar row's pressed fill when a scroll starts
yadaniyil Sep 25, 2026
5cafaf2
fix(split): Windows pill origin, one-line page title, rail menu button
yadaniyil Sep 25, 2026
01660ec
test(example): fix the integration test on short screens, add split v…
yadaniyil Sep 25, 2026
936afde
fix(split): scale the GNOME sidebar with the text on Android 14+
yadaniyil Sep 25, 2026
c235d0f
docs(split): describe routes pushed from the list pane in one pane
yadaniyil Sep 25, 2026
878e594
fix(split): keep a clicked row's focus ring hidden until a key is pre…
yadaniyil Sep 25, 2026
923d175
Merge branch 'fix/qa-tiles' into integration/4.0-all
yadaniyil Sep 25, 2026
7845e84
Merge branch 'fix/qa-release' into integration/4.0-all
yadaniyil Sep 25, 2026
e2b7228
docs(split): fix the semanticsSelected docs of the macOS and Windows …
yadaniyil Sep 25, 2026
c13a1d3
style(split): format the split view regression tests
yadaniyil Sep 25, 2026
52a0fa4
Merge branch 'fix/qa-split' into integration/4.0-all
yadaniyil Sep 25, 2026
ef8beac
fix(split): label the switches of the macOS and Windows sidebar rows
yadaniyil Sep 25, 2026
8efb4de
fix(linux): grow the GNOME page column with the body text
yadaniyil Sep 25, 2026
778eadc
docs(split): say what happens when a picked page's tile goes away
yadaniyil Sep 25, 2026
04e5c68
docs: bring AGENTS.md and llms.txt up to date with the RC fixes
yadaniyil Sep 25, 2026
1246137
docs(changelog): list the fixes from the 4.0.0 release candidate review
yadaniyil Sep 25, 2026
cd0eb60
test(example): pick a style in the split view demo on a device
yadaniyil Sep 25, 2026
84348c6
docs(readme): bring the split view, GNOME sizes and brightness facts …
yadaniyil Sep 25, 2026
c78ad41
fix(a11y): make every tile its own semantics node
yadaniyil Sep 25, 2026
7f3a9b8
docs(readme): describe tile semantics for screen readers
yadaniyil Sep 25, 2026
ec4caaa
docs(llms): add a recipe for building a settings screen
yadaniyil Sep 25, 2026
86d400b
docs: agent-first README with the 4.0 header images
yadaniyil Sep 25, 2026
051897c
chore: release 4.0.0
yadaniyil Sep 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ example/.flutter-plugins-dependencies
doc/api/
.idea
*.iml

# Created by `flutter test --coverage` (CI). .pubignore repeats these rules.
coverage/
42 changes: 37 additions & 5 deletions .pubignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,41 @@
# IDE project files — not needed by package consumers
# What `flutter pub publish` leaves out of the package.
#
# A .pubignore replaces the .gitignore of its folder for pub: with this file,
# pub no longer reads the root .gitignore, so its rules are repeated here. Keep
# the two in sync. Pub still reads the .gitignore files of subfolders (example/
# and its platform runners), and always skips dotfiles, dot-directories
# (.github/, .dart_tool/, .idea/), pubspec.lock and pubspec_overrides.yaml.

# Build output: `flutter test` creates build/ at the root (75+ MB), and
# example/build/ comes from running the example. `build/` matches both.
build/
.dart_tool/
coverage/
doc/api/

# IDE files (pub skips the dot-directories anyway)
.idea/
*.iml
*.ipr
*.iws
.vscode/

# Internal planning docs
V3_PLAN.md
# Agent and contributor docs. llms.txt ships on purpose.
CLAUDE.md
AGENTS.md

# Coverage output
coverage/
# Images that no file in this version uses. The READMEs of earlier versions on
# pub.dev load them from GitHub, so they stay in the repository. The current
# README loads its images from GitHub too; the package only needs the files
# that `screenshots:` in pubspec.yaml lists.
assets/dark_mode_animation.gif
assets/flutter_settings_ui_logo.png
assets/navigation-tile.png
assets/settings-list.png
assets/settings-section.png
assets/simple-tile.png
assets/switch-tile.png
assets/v2/android/
assets/v2/iOS/
assets/v2/settings_ui_cover.png
assets/v3/
170 changes: 170 additions & 0 deletions AGENTS.md

Large diffs are not rendered by default.

54 changes: 49 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,70 @@
## [4.0.0] - [September 24, 2026]
## [4.0.0] - [September 25, 2026]

### Breaking changes
* Migrated from `package:flutter/material.dart` and `package:flutter/cupertino.dart` to the decoupled [`material_ui`](https://pub.dev/packages/material_ui) and [`cupertino_ui`](https://pub.dev/packages/cupertino_ui) packages (#207)
* Migrated from `package:flutter/material.dart` and `package:flutter/cupertino.dart` to the decoupled [`material_ui`](https://pub.dev/packages/material_ui) and [`cupertino_ui`](https://pub.dev/packages/cupertino_ui) packages (#207, thanks @SlayerOrnstein)
* Requires Flutter >=3.44.0 and Dart SDK >=3.12.0
* Your app must use `MaterialApp`/`CupertinoApp` from `material_ui`/`cupertino_ui`. In an app still on `package:flutter/material.dart`, `SettingsList` can't read your theme and falls back to default colors and light mode. Stay on `^3.0.1` until your app has migrated.
* New default look that matches iOS 26/27, macOS 26/27, Android 16/17, Windows 11, GNOME 51 and current Chrome settings (see Design refresh). Sizes, paddings and default colors changed. Colors you set in `SettingsThemeData` still win.
* iOS switch tiles now show the new `CupertinoSettingsSwitch` instead of `CupertinoSwitch`. Tests that find `CupertinoSwitch` need to look for `CupertinoSettingsSwitch`.
* macOS now has its own macOS System Settings style instead of the iOS style. Its switch tiles show the new `MacosSettingsSwitch`, not a `CupertinoSwitch`.
* Windows now has its own Windows 11 style instead of the iOS style. Its switch tiles show the new `FluentSettingsSwitch`, not a `CupertinoSwitch`.
* Linux now has its own GNOME style instead of the Android style. Its switch tiles show the new `AdwaitaSettingsSwitch`, not a Material `Switch`, so tests that find `Switch` on Linux need to look for `AdwaitaSettingsSwitch`.
* The default side padding of `SettingsList` now comes from the width the list gets, not the screen width (see Bug fixes). A list in a side panel or a narrow pane of a wide window gets less side padding than before.

### Design refresh
* iOS: 26pt cards with continuous corners and 20pt side margins, 52pt rows with 17pt text, 17pt semibold section headers, and the iOS secondary grey for headers and footers. Write section titles in sentence case, like iOS 26: if you passed ALL-CAPS titles for the old iOS look, change them.
* iOS: a new switch that matches the iOS 26/27 one, drawn entirely in Flutter. It has a 63x28 track and a pill-shaped thumb, and while it is pressed or dragged the thumb becomes a Liquid Glass-style lens. It is public as `CupertinoSettingsSwitch`, so you can use it outside settings lists too.
* macOS: a new style that matches macOS 26/27 System Settings (#148), instead of the iOS one: 12pt cards on a white page, 36pt rows with 13pt text, 13pt semibold headers, a 640pt column and the new public `MacosSettingsSwitch` (36x16, or 44x20 with `MacosSettingsSwitchSize.large`).
* Android, Fuchsia: every tile sits on its own card, 2dp apart, with 20dp corners at the ends of a group and 4dp in between, on a `surfaceContainer` page. 16sp titles, tighter rows, and switches that show a check or a cross.
* Windows: a new Windows 11 Settings style (#160) instead of the iOS one: one card per tile with 4px corners and a hairline border, 70px rows, 14px titles and 12px descriptions, the Windows hover, pressed and keyboard focus states, and `FluentSettingsSwitch`, a public WinUI-style toggle drawn in Flutter.
* Linux: a new GNOME style that matches GNOME Settings 51 (libadwaita 1.10): boxed-list cards with 12px corners and a soft shadow, 54px rows with full-width separators, bold group titles, dimmed subtitles and values, a `go-next` arrow on navigation tiles, hover and keyboard focus highlights, and an `AdwClamp`-style 600px column. Its switch, a 46x26 GNOME switch drawn in Flutter, is public as `AdwaitaSettingsSwitch`, and `AdwaitaPanDownIcon` gives combo rows their arrow.
* Web: Chrome-style white cards with 8px corners and a light shadow, 14px titles and 13px descriptions, 20px leading icons, a chevron on navigation tiles, near-black section titles, and a 680px column on wide screens (16px side margins in narrow windows).
* macOS, Windows, Linux: Material widgets in a `CustomSettingsTile` (a `ListTile`, a `Checkbox`) work on the cards without a `Scaffold`, and text in custom tiles takes the tile's style and color.

### Bug fixes
* Colors, dark mode and platform now follow the app theme in apps built on `material_ui` (#206)
* iOS: values are right-aligned next to the chevron again (#203, #202)
* iOS: simple tiles now show their `value`, like on Android (#201)
* iOS: values are right-aligned next to the chevron again (#203, #202, thanks @mmng-a)
* iOS: simple tiles now show their `value`, like on Android (#201, thanks @mmng-a)
* iOS: a long title no longer hides the value. The value takes at most half the row, on one line
* Compiles on Flutter forks that add platforms, such as OpenHarmony, which get the Cupertino style (#205)
* `SettingsList.brightness` now overrides the brightness from the app theme, in every style. It was ignored. The Android and web styles, whose colors come from the app's `ColorScheme`, then use a scheme of that brightness made from its primary color, and the iOS switch follows it too
* `ApplicationType.both` now goes by the platform the app runs on: the `CupertinoTheme` on iOS and macOS, the Material `Theme` elsewhere. Before, it read the Material brightness unless `platform: DevicePlatform.iOS` was set, so a `CupertinoApp` that follows the system could show light colors in dark mode
* `crossAxisAlignment: CrossAxisAlignment.start` now puts the content at the start edge on wide screens (left in LTR, right in RTL). The default padding used to keep it centered
* The wide-screen side padding now comes from the width the list gets, not the screen width, so a `SettingsList` in a narrow pane of a wide window fits the pane. iOS tile descriptions also take the list's width now
* A `SettingsSection` with no tiles no longer crashes on iOS, macOS and Windows. Empty sections now show nothing on every platform
* `SettingsTile.titleDescriptionPadding` now pads the title description on iOS. `titlePadding` was used instead
* `SettingsTile.trailingPadding` and `descriptionPadding` now work on iOS, macOS and Windows, and `titlePadding` on Android and web. They were ignored there
* Android and web: disabled switches use `SettingsThemeData.inactiveSwitchColor` with or without a `trailing` widget, and a web switch next to a `trailing` widget no longer has a hard-coded blue active color (#188)
* iOS, Android and web: a disabled tile no longer runs `onPressed` or `onToggle` from the keyboard (Tab, then Enter or Space)
* Screen readers now read a switch tile with its title, as one item ("Wi-Fi, switch, on"), instead of just "switch, on" on iOS, Android and web. Where the row also has `onPressed` (iOS, macOS and Windows), the row and its switch are two items, both named by the title
* iOS: rows that do nothing (no `onPressed`, or disabled) no longer offer screen readers a tap action
* Screen readers read each tile as its own item in every style: an Android section with one tappable tile was read as one button holding all its tiles. Tiles with `onPressed` are buttons, and section titles headings
* iOS: a widget test that ends right after tapping a tile no longer fails with a pending timer

### New features
* `SettingsSplitView`: the list and the selected page side by side on iPad, tablets, unfolded foldables, desktop and the web, and a list with pushed pages on phones. It follows each platform app: iPad Settings (320pt sidebar, blue capsule selection, two panes from 600pt on iPads), Android Settings (36.36% list pane on surface dim, two panes at 720dp wide with a 600dp smallest width, no icons in a list pane under 380dp) and Chrome (266px menu, two panes above 980px). It keeps pages, their state, pushed sub-pages and the keyboard focus when a device folds, unfolds or rotates, handles back, Android predictive back and the iOS back swipe (a `PopScope` in a page can veto), restores the shown page, closes a page whose tile goes away, puts the panes on each side of a hinge, and mirrors in right-to-left layouts. In one pane, back first closes a route that a list tile pushed itself (`Navigator.push`, a menu, a sheet), and the view stays in one pane until that route has closed. It also works in a `CupertinoApp` or `WidgetsApp` without `MaterialLocalizations`. Control it with `SettingsSplitController`, `SettingsSplitLayout`, `initialDestinationId` and `onDestinationChanged`. The arrow keys move through the list pane and Tab moves between the panes (#2)
* `SettingsSplitView` on the desktop styles: each draws its settings app's sidebar and page header. In the sidebars Up and Down stop at the first and last rows, a click focuses the row (its focus ring shows once a key is pressed), Tab reaches switch rows, and screen readers hear which row is selected.
* macOS: the System Settings sidebar (232pt, full height, 32pt rows, an accent selection with a white label that turns grey while the app is inactive, 11pt bold section titles, no hover) and a 52pt toolbar with the page title and Liquid Glass-style back and forward buttons. Two panes from 560pt. Moving the focus with the arrow keys opens the row, like macOS sidebars.
* Windows: the Windows 11 Settings `NavigationView` (a 300px pane from 1008px and a 48px icon rail with tooltips from 641px, whose menu button opens the pane over the page). The selected item has an accent pill that slides from the previous one. The page title is large, and pages opened from a page show a breadcrumb. Both stay on one line: the first crumbs collapse into "…".
* GNOME: the GNOME Settings sidebar (a quarter of the window, 180 to 280, collapsing at 550; 43px rounded rows; its own header bar) and flat header bars with centered titles and a back button when collapsed or nested. In one pane the sidebar fills the window. Its sizes, like the GNOME page column's, grow with the body text, also with the non-linear font scaling of Android 14 and later.
* `SettingsDestination` and `SettingsTile.navigation(destination: ...)`: a tile can open a page without your own `Navigator.push`. In a `SettingsList` it pushes a Cupertino or Material route with the platform's page header (iOS 26 inline title and glass back button, Android's collapsing large title, the macOS toolbar, the Windows page title with a breadcrumb, GNOME's header bar, Chrome's page title), and the `SettingsList` in the page takes the platform, brightness and themes of the list that opened it
* `SettingsThemeData.selectedTileColor`, `selectedTileTextColor`, `selectedTileIconColor` and `listPaneBackground` for the split view, with defaults for every style
* Debug builds print a one-time warning when `SettingsList` finds no `material_ui` or `cupertino_ui` theme above it

### Documentation
* README rewritten for 4.0: every style, the split view, API tables, and copy-paste prompts for coding agents (Claude Code, Codex, Cursor)
* New `llms.txt`: a compact API reference with the platform differences and the mistakes to avoid, for coding agents. It ships in the package, and the README's prompts fetch it from GitHub
* New `AGENTS.md` with instructions for agents working on this repository
* To show a value without the chevron, use `SettingsTile` instead of `SettingsTile.navigation` (#204)

### Maintenance
* CI now checks formatting with `dart format` (`flutter format` was removed from Flutter)
* Example app: updated Android Gradle setup, and moved the iOS runner to the UIScene lifecycle required on iOS 27
* Example app: updated Android Gradle setup, moved the iOS runner to the UIScene lifecycle required on iOS 27, and added a macOS runner
* Example app: a "Split view" demo with iPad, Android, Chrome, macOS System Settings, Windows Settings and GNOME Settings trees, a showcase screen (a fictional app's settings in every style, for screenshots), and replicas of macOS, Windows and GNOME settings pages. A screen, style and brightness can be opened directly, e.g. `cd example && flutter run --route '/split-view?platform=android&theme=dark'`, `?screen=showcase&platform=windows` on the web, or `--dart-define=SCREEN=gnome-power`
* Example app: added a Linux runner, the showcase in the gallery, switches that toggle in every demo, and the Material 3 demo and the Android replica follow dark mode

## [3.0.1] - [April 10, 2026]
* README rewritten with a full API reference, examples and screenshots. No code changes

## [3.0.0] - [April 10, 2026]

Expand Down
99 changes: 1 addition & 98 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,98 +1 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## About this project

`settings_ui` is a published Flutter package (pub.dev: `settings_ui`, current version: `2.0.3`) that renders native-looking settings screens for Android, iOS, macOS, Windows, Linux, Fuchsia, and Web — all from a single API. It is used in production by thousands of apps.

## Commands

```bash
# Get dependencies
flutter pub get

# Run all tests
flutter test

# Run a single test file
flutter test test/widget_test.dart

# Run tests with coverage
flutter test --coverage --test-randomize-ordering-seed random

# Analyze for lint errors
flutter analyze .

# Fix formatting
flutter format .

# Check formatting without changing files (CI-style)
flutter format --set-exit-if-changed .

# Run the example app
cd example && flutter run
```

## Architecture

### Rendering strategy: platform dispatch

Every public widget (`SettingsList`, `SettingsSection`, `SettingsTile`) is a thin dispatcher. At build time each checks `SettingsTheme.of(context).platform` and returns one of three concrete platform implementations:

- `Android/Fuchsia/Linux` → Material widgets
- `iOS/macOS/Windows` → Cupertino widgets
- `Web` → Web-specific widgets (rounded cards, adjusted padding)

Platform implementations live alongside their dispatcher:

```
lib/src/tiles/
settings_tile.dart ← dispatcher
platforms/
android_settings_tile.dart
ios_settings_tile.dart
web_settings_tile.dart
```

Same pattern for `sections/` and `list/`.

### Theme propagation via `InheritedWidget`

`SettingsList` resolves platform and brightness, calls `ThemeProvider.getTheme()` to get hardcoded platform defaults, merges in any user-supplied `lightTheme`/`darkTheme` (`SettingsThemeData`), then pushes the result down the tree via `SettingsTheme` (an `InheritedWidget`).

All platform tile/section widgets read theme from `SettingsTheme.of(context).themeData`. Never pass theme as a constructor argument.

`ThemeProvider` (`lib/src/utils/theme_provider.dart`) contains all hardcoded color values for each platform/brightness combination. This is the main place to touch when fixing theme issues.

### `DevicePlatform.device` is a sentinel

`DevicePlatform.device` means "auto-detect at runtime" and is valid only as input to `SettingsList`. It must never reach the platform switch statements inside tiles/sections — doing so throws. `PlatformUtils.detectPlatform()` resolves it to a real platform.

### `IOSSettingsTileAdditionalInfo`

An extra `InheritedWidget` injected by `IOSSettingsSection` to tell each `IOSSettingsTile` whether to draw top/bottom border radius and whether to show the inter-tile divider. This is iOS/macOS/Windows only.

### Public API surface (the only exports)

`lib/settings_ui.dart` re-exports exactly:
- `SettingsList` (+ `ApplicationType` enum)
- `SettingsSection`, `AbstractSettingsSection`, `CustomSettingsSection`
- `SettingsTile` (+ `SettingsTileType` enum), `AbstractSettingsTile`, `CustomSettingsTile`
- `DevicePlatform`, `PlatformUtils`
- `SettingsTheme`, `SettingsThemeData`

Platform-specific implementations are internal and should not be part of the public API.

## Testing conventions

- Tests live in `test/` with a flat `widget_test.dart` entry point that calls helper functions grouped by concern (`settingsListTests`, `settingsSectionsTests`, `settingsTileTests`, etc.).
- Helper test functions are parameterised over `DevicePlatform` and called for every platform value.
- The `_wrapWithMaterialApp` / `TestWidgetScreen` helper wraps a tile or section in a `SettingsList` inside a `MaterialApp` and passes the desired platform explicitly so tests are platform-deterministic.
- CI requires ≥ 35% line coverage (`very_good_coverage`).

## CI / Release

- **CI** runs on every push: format check → `flutter analyze` → `flutter test --coverage` → coverage gate (35%).
- **PR titles** must follow Conventional Commits (enforced by `action-semantic-pull-request`).
- There is currently no automated publish workflow; a new version requires bumping `version` in `pubspec.yaml`, updating `CHANGELOG.md`, tagging, then running `flutter pub publish`.
@AGENTS.md
Loading
Loading