Skip to content

Instantly share code, notes, and snippets.

@fredgrott
Created December 28, 2025 18:36
Show Gist options
  • Select an option

  • Save fredgrott/44e5804a0c058f815231b6dd57630a98 to your computer and use it in GitHub Desktop.

Select an option

Save fredgrott/44e5804a0c058f815231b6dd57630a98 to your computer and use it in GitHub Desktop.
window width
// Copyright 2025 Fredrick Allan Grott. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// Modified from window_size_classes package by Yuna
// Copyright 2025 under GNU LGPL 3.0
import 'package:flutter/widgets.dart';
import 'package:material_expressive_collection/src/adaptive/breakpoints.dart';
import 'package:meta/meta.dart';
/// Opinionated set of horizontal viewport breakpoints.
///
/// ```dart
/// final windowWidth = WindowWidth.of(context);
///
/// return switch (widthClass) {
/// WindowWidth.compact => CompactLayout(),
/// WindowWidth.medium => MediumLayout(),
/// WindowWidth.expanded => ExpandedLayout(),
/// _ => LargeLayout(), // large and extraLarge
/// };
/// ```
///
/// See also:
///
/// * <https://m3.material.io/foundations/layout/applying-layout/window-size-classes>
/// * [WindowHeight], for height-based classifications.
/// * [FlutterView view.of(this).size], which provides the window dimensions.
enum WindowWidth implements Comparable<WindowWidth> {
/// Compact window width.
///
/// Applies to windows with width less than [mediumWidthBreakpoint] (600
/// logical pixels).
///
/// Common devices:
///
/// - Phone in portrait
///
/// See also:
///
/// * <https://m3.material.io/foundations/layout/applying-layout/compact>
compact(spacing: 16),
/// Medium window width.
///
/// Applies to windows with width of at least [mediumWidthBreakpoint]
/// (600 logical pixels) and less than [expandedWidthBreakpoint] (840
/// logical pixels).
///
/// Common devices:
///
/// - Tablet in portrait
/// - Foldable in portrait (unfolded)
///
/// See also:
///
/// * <https://m3.material.io/foundations/layout/applying-layout/medium>
medium(spacing: 24),
/// Expanded window width.
///
/// Applies to windows with a width of at least [expandedWidthBreakpoint]
/// (840 logical pixels) and less than [largeWidthBreakpoint] (1200 logical
/// pixels). Enables multi-column layouts, side-by-side content, and expanded
/// navigation patterns that take advantage of additional horizontal real
/// estate.
///
/// Common devices:
///
/// - Phone in landscape
/// - Tablet in landscape
/// - Foldable in landscape (unfolded)
/// - Desktop
///
/// See also:
///
/// * <https://m3.material.io/foundations/layout/applying-layout/expanded>
expanded(spacing: 24),
/// Large window width.
///
/// Applies to windows with a width of at least [largeWidthBreakpoint]
/// (1200 logical pixels) and less than [extraLargeWidthBreakpoint]
/// (1600 logical pixels). Includes a [fixedPaneWidth] of 360.0 to maintain
/// optimal content organization and reading lengths despite the generous
/// horizontal space available.
///
/// Common devices:
///
/// - Desktop
///
/// See also:
///
/// * <https://m3.material.io/foundations/layout/applying-layout/large-extra-large>
large(spacing: 24, fixedPaneWidth: 360),
/// Extra large window width.
///
/// Applies to windows with width of [extraLargeWidthBreakpoint] (1600
/// logical pixels) or more.
/// Features a larger [fixedPaneWidth] of 412.0 logical pixels to maintain
/// readable content proportions and prevent over-stretching of content
/// across very wide horizontal spaces.
///
/// Common devices:
///
/// - Desktop
/// - Ultra-wide
///
/// See also:
///
/// * <https://m3.material.io/foundations/layout/applying-layout/large-extra-large>
extraLarge(spacing: 24, fixedPaneWidth: 412);
/// Creates a window width class with the given [spacing] and optional
/// [fixedPaneWidth].
const WindowWidth({required this.spacing, this.fixedPaneWidth});
/// Value used for layout margin and pane spacing.
final double spacing;
/// The fixed pane width for [large] and [extraLarge] width classes.
///
/// When not null, this value suggests a width for fixed panes.
final double? fixedPaneWidth;
/// Returns the [WindowWidth] for the current screen width.
///
/// Retrieves the screen width from [MediaQuery] and determines the
/// appropriate [WindowWidth] based on the Material Design 3 breakpoints.
///
/// The [context] must have a [MediaQuery] ancestor.
///
/// ```dart
/// Widget build(BuildContext context) {
/// final windowWidth = WindowWidth.of(context);
/// // Use width to adapt your layout...
/// }
/// ```
@useResult
@pragma('vm:prefer-inline')
static WindowWidth of(BuildContext context) {
// changed from MediaQuery.sizeOf(context).width
// for foldables
return fromWidth(View.of(context).display.size.width);
}
/// Returns the [WindowWidth] for the given [width] value.
///
/// The [width] parameter should be in logical pixels.
/// This method applies Material Design 3 breakpoint logic to
/// determine the appropriate width class.
///
/// ```dart
/// final windowWidth = WindowWidth.fromWidth(800); // Returns medium
/// final windowWidth = WindowWidth.fromWidth(1400); // Returns large
/// ```
@useResult
static WindowWidth fromWidth(num width) {
return switch (width) {
>= extraLargeWidthBreakpoint => WindowWidth.extraLarge,
>= largeWidthBreakpoint => WindowWidth.large,
>= expandedWidthBreakpoint => WindowWidth.expanded,
>= mediumWidthBreakpoint => WindowWidth.medium,
_ => WindowWidth.compact,
};
}
/// Whether this height is smaller than [other].
///
/// Returns `true` if this height class is smaller than [other].
/// Returns `false` if this height class is greater than or equal to [other].
bool operator <(WindowWidth other) => index < other.index;
/// Whether this height class is smaller than or equal to [other].
///
/// Returns `true` if this height class is smaller than or equal to [other].
/// Returns `false` if this height class is greater than [other].
bool operator <=(WindowWidth other) => index <= other.index;
/// Whether this height is greater than [other].
///
/// Returns `true` if this height class is greater than [other].
/// Returns `false` if this height class is smaller than or equal to [other].
bool operator >(WindowWidth other) => index > other.index;
/// Whether this height is greater than or equal to [other].
///
/// Returns `true` if this height is greater than or equal to [other].
/// Returns `false` if this height is smaller than [other].
bool operator >=(WindowWidth other) => index >= other.index;
/// Compares this [WindowWidth] to [other].
///
/// Returns a negative integer if this [WindowWidth] represents a smaller
/// width than [other], zero if they represent the same width class, or a
/// positive integer if this [WindowWidth] represents a larger width than
/// [other].
@override
@pragma('dart2js:tryInline')
@pragma('vm:prefer-inline')
@pragma('wasm:prefer-inline')
int compareTo(WindowWidth other) => index.compareTo(other.index);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment