Grafana Phlare: Horizontally-scalable, Highly-available

Grafana Phlare

Grafana Phlare is an open source software project for aggregating continuous profiling data. Continuous profiling is an observability signal that allows you to understand your workload's resources (CPU, memory, etc...) usage down to the exact lines of code.

Grafana Phlare is fully integrated with Grafana allowing you to correlate with other observability signals, like metrics, logs, and traces.

Explore UI

Core features of Grafana Phlare include:

  • Easy to install: Using its monolithic mode, you can get Grafana Phlare up and running with just one binary and no additional dependencies. On Kubernetes a single helm chart allows to deploy in different mode.
  • Horizontal scalability: You can run Grafana Phlare across multiple machines, which makes it effortless for you to scale the database to handle the profiling volumes your workload generates.
  • High availability: Grafana Phlare replicates incoming profiles, ensuring that no data is lost in the event of machine failure. This means you can rollout without interrupting profiles ingestion and analysis.
  • Cheap, durable profile storage: Grafana Phlare uses object storage for long-term data storage, allowing it to take advantage of this ubiquitous, cost-effective, high-durability technology. It is compatible with multiple object store implementations, including AWS S3, Google Cloud Storage, Azure Blob Storage, OpenStack Swift, as well as any S3-compatible object storage.
  • Natively multi-tenant: Grafana Phlare's multi-tenant architecture enables you to isolate data and queries from independent teams or business units, making it possible for these groups to share the same database.

Deploying Grafana Phlare

For information about how to deploy Grafana Phlare, refer to Deploy Grafana Phlare.

Getting started

If you’re new to Grafana Phlare, read the Getting started guide.

Before deploying Grafana Phlare in a production environment, read:

  1. An overview of Grafana Phlare’s architecture
  2. Configure Grafana Phlare
  3. Deploy in Kubernetes

Documentation

Refer to the following links to access Grafana Phlare documentation:

Contributing

To contribute to Grafana Phlare, refer to Contributing to Grafana Phlare.

Join the Grafana Phlare discussion

If you have any questions or feedback regarding Grafana Phlare, join the Grafana Phlare Discussion. Alternatively, consider joining the monthly Grafana Phlare Community Call.

Your feedback is always welcome, and you can also share it via the #phlare Slack channel.


Download Details:

Author: grafana
Source Code: https://github.com/grafana/phlare

License: AGPL-3.0 license

#golang 

What is GEEK

Buddha Community

Grafana Phlare: Horizontally-scalable, Highly-available

What is High Availability? A Tutorial | Liquid Web

High Availability

High availability is the description of a system designed to be fault-tolerant, highly dependable, operates continuously without intervention, or having a single point of failure. These systems are highly sought after to increase the availability and uptime required to keep an infrastructure running without issue. The following characteristics define a High Availability system.

High Availability Clustering

High-availability server clusters (aka HA Clusters) is defined as a group of servers which support applications or services that can be utilized reliably with a minimal amount of downtime. These server clusters function using a type of specialized software that utilizes redundancy to achieve mission-critical levels of five9’s uptime. Currently, approximately 60% of businesses require five9’s or greater to provide vital services for their businesses.

High availability software capitalizes on the redundant software installed on multiple systems by grouping or clustering together a group of servers focusing on a common goal in case components fail. Without this form of clustering, if the application or website crashes, the service will not be available until the servers are repaired. HA clustering addresses these situations by detecting the faults and quickly restarting or replacing the server or service or server with a new process that does not require human intervention. This is defined as a “failover” model.

The illustration below demonstrates a simple two node high availability cluster.

2nodeHAcluster

High Availability clusters are often used for mission-critical databases, data sharing, applications, and e-commerce websites spread over a network. High Availability implementations build redundancy within a cluster to remove any one single point of failure, including across multiple network connections and data storage, which can be connected redundantly via geographically diverse storage area networks.

High Availability clustered servers usually use a replication methodology called Heartbeat that is used to monitor each node’s status and health within the cluster over a private network connection. One critical circumstance all clustering software must be able to address is called split-brain, which occurs when all private internal links go down simultaneously, but the nodes in the cluster continue to run. If this occurs, every node within the cluster may incorrectly determine that all the other nodes have gone down and attempt to start services that other nodes may still be running. This condition of duplicate instances running similar services, which could cause data corruption on the system.

ha.cluster

A typical version of high availability software provides attributes that include both hardware and software redundancy. These features include:

  • The automatic detection and discovery of hardware and software components.
  • Autonomous assignment of both active and contingent roles to new elements.
  • Detection of failed software services, hardware components, and other system constructs.
  • Monitoring and notification of redundant components and when they need to be activated.
  • Ability to scale the cluster to accommodate the required changes without external intervention.

Fault tolerance

fault.tolerance

Fault tolerance is defined as the ability for a system’s infrastructure to foresee and withstand errors and provide an automatic response to those issues if encountered. The primary quality of these systems is advanced design factors, which can be called upon should a problem occur. Being able to configure an infrastructure that envisions every possible solution is a considerable task that involves the knowledge and experience to counter the multiple concerns before they occur. System architects who design such frameworks will have the methodologies which envision the means to alleviate these problems in advance, and the ability to implement these frameworks.

The following redundancy methodologies are available and should be reviewed during the initial stages of design and implementation.

  • N + 1 Model – This concept infers the sum of equipment needed (which we will refer to as ‘N’) to keep the entire framework up and running, with an additional independent component backup for each of the ‘N’ components in case of failure.
  • N + 2 Model – Similar to the N + 1 model but with an additional layer of protection if two components should fail.
  • 2N Model – This modality has a dual redundant backup for each element to ensure the system’s framework is fully functional.
  • 2N + 1 Model – Again, this model is similar to the 2N model but with a supplemental component to add a tertiary layer of protection to the system’s framework.

As models progress from Nx to 2Nx, the cost factor also increases exponentially as for truly redundant systems that require uptime. These modalities are critical for stability and availability.

Dependability and Reliability

One of the central tenants of a high availability system is uptime. Uptime is of premier importance, especially if the purpose of a system is to provide an essential service like the 911 systems that respond to emergent situations. In business, having a high availability system is required to ensure a vital service remains online. One example would be an ISP or other service that cannot tolerate a loss of function. These systems must be designed with high availability and fault tolerance to ensure reliability and availability while minimizing downtime.

Orchestrated Error Handling

Should an error occur, the system will adapt and compensate for the issue while remaining up and online. Building this type of system requires forethought and planning for the unexpected. Being able to foresee the problems in advance, and planning for their resolution is one of the main qualities of a high availability system.

Scalability

Should the system encounter an issue like a traffic spike or an increase in resource usage, the system’s ability to scale to meet those needs should be automatic and immediate. Building features like these into the system will provide the system’s ability to respond quickly to any change in the systemic functionality of the architectures processes.

Availability & Five 9’s Uptime

Five 9’s is the industry standard of measure of uptime. This measurement can be related to the system itself, the system processes within a framework, or the program operating inside an infrastructure. This estimation is often related to the program being delivered to clients in the form or a website or web application. A systems Availability can be measured as the percentage of time that systems are available by using this equation: x = (n – y) * 100/n. This formula denotes that where “n” is the total amount of minutes within a calendar month, and “y” is the amount of minutes that service is inaccessible within a calendar month. The table below outlines downtime related to the percentage of “9’s” represented.

**Availability %**90%

(“1 Nine“)99%

(“2 Nines“)99.9%

(“3 Nines“)99.99%

(“4 Nines“)99.999%

(“5 Nines“)Downtime/Year36.53 days3.65 days8.77 hours52.60 minutes5.26 minutes

As we can see, the higher the number of “9’s”, the more uptime is provided. A high availability system’s goal is to achieve a minimal amount of potential downtime to ensure the system is always available to provide the designated services.

Heartbeat

One of the main High Availability components is called Heartbeat. Heartbeat is a daemon which works with a cluster management software like Pacemaker that is designed specifically for high-availability clustering resource management. Its most important characteristics are:

  • No specific or fixed maximum number of nodes – Heartbeat can be used to build large clusters as well as elementary ones.
  • Resource monitoring: resources can be automatically restarted or moved to another node on failure.
  • A fencing mechanism needed to remove failed nodes from the cluster.
  • A refined policy-based resource management, resource inter-dependencies, and constraints.
  • A time-based rule set to allow for different policies depending on a defined timeframe.
  • A group of resource scripts (for software like Apache, DB2, Oracle, PostgreSQL, etc.) included more granular management.
  • A GUI for configuring, controlling and monitoring resources and nodes.

Cluster Architecture

**Engineered Availability **

The first segment of a highly available system is the clearly designed utilization of clustered application servers that are engineered in advance to distribute load amongst the whole cluster, which includes the ability to failover to a secondary and possibly a tertiary system.

The second division includes the need for database scalability. This entails the requirement of scaling, either horizontally or vertically, using multiple master replication, and a load balancer to improve the stability and uptime of the database.

ha cluster

#tutorials #2nx models #architecture #autonomous #availability #backups #best practice #clustering #deployment #design #disaster recovery #downtime #engineered #fault tolerance #ha cluster #heartbeat #high availability #infrastructure #monitoring #node #nx models #orchestrated #pacemaker #redundancy #reliability #replication #scalability #single point of failure #split brain #system #testing #uptime

Grafana Phlare: Horizontally-scalable, Highly-available

Grafana Phlare

Grafana Phlare is an open source software project for aggregating continuous profiling data. Continuous profiling is an observability signal that allows you to understand your workload's resources (CPU, memory, etc...) usage down to the exact lines of code.

Grafana Phlare is fully integrated with Grafana allowing you to correlate with other observability signals, like metrics, logs, and traces.

Explore UI

Core features of Grafana Phlare include:

  • Easy to install: Using its monolithic mode, you can get Grafana Phlare up and running with just one binary and no additional dependencies. On Kubernetes a single helm chart allows to deploy in different mode.
  • Horizontal scalability: You can run Grafana Phlare across multiple machines, which makes it effortless for you to scale the database to handle the profiling volumes your workload generates.
  • High availability: Grafana Phlare replicates incoming profiles, ensuring that no data is lost in the event of machine failure. This means you can rollout without interrupting profiles ingestion and analysis.
  • Cheap, durable profile storage: Grafana Phlare uses object storage for long-term data storage, allowing it to take advantage of this ubiquitous, cost-effective, high-durability technology. It is compatible with multiple object store implementations, including AWS S3, Google Cloud Storage, Azure Blob Storage, OpenStack Swift, as well as any S3-compatible object storage.
  • Natively multi-tenant: Grafana Phlare's multi-tenant architecture enables you to isolate data and queries from independent teams or business units, making it possible for these groups to share the same database.

Deploying Grafana Phlare

For information about how to deploy Grafana Phlare, refer to Deploy Grafana Phlare.

Getting started

If you’re new to Grafana Phlare, read the Getting started guide.

Before deploying Grafana Phlare in a production environment, read:

  1. An overview of Grafana Phlare’s architecture
  2. Configure Grafana Phlare
  3. Deploy in Kubernetes

Documentation

Refer to the following links to access Grafana Phlare documentation:

Contributing

To contribute to Grafana Phlare, refer to Contributing to Grafana Phlare.

Join the Grafana Phlare discussion

If you have any questions or feedback regarding Grafana Phlare, join the Grafana Phlare Discussion. Alternatively, consider joining the monthly Grafana Phlare Community Call.

Your feedback is always welcome, and you can also share it via the #phlare Slack channel.


Download Details:

Author: grafana
Source Code: https://github.com/grafana/phlare

License: AGPL-3.0 license

#golang 

Fredy  Larson

Fredy Larson

1598419500

Building Scalable Systems

Building a Reactive System is all about the balance between consistency and availability and the consequences of picking one over the other. This article mainly focuses on consistency and availability and how they impact the scalability of a system.

What is Scalability, Consistency and Availability?

A system is scalable if it can meet the increase in demand while remaining responsive.

It is consistent if all the nodes show the same data at the same time.

It is available if it remains responsive despite any failures.

How does the scalability of a system differs from the performance of the system?

Scalability and performance are related but different concepts and we need to understand what the difference is.

Scalability is the number of requests system can handle at a time, i.e. load. It’s about optimizing the ability to handle load, which means improving how many requests system can handle at a time. Performance on the other hand is the time system takes to complete a single request, i.e. latency. It’s about optimizing the response time, which means improving how quickly system can handle a single request.

Performance has a limit on reducing the response time, and we will eventually reach that limit. Whereas, scalability has no theoretical limit. We may be restricted by the implementation. But in a perfectly scalable system, we could scale forever.

So when we build Reactive Micro-services we tend to focus on improving scalability than improving performance.

How can we measure scalability and performance of a system?

Measurement like requests-per-second actually measures both. This makes it a valuable metric because we can use it to see whether we have improved our scalability or our performance. But it also means that it is somewhat restrictive in the sense that if it improves we can’t tell which one changed. So if we want to know where that improvement came from then we have to track scalability and performance individually.

How can we explain consistency in distributed systems?

Distributed systems are systems that are separated by space. This means, the system could be deployed across multiple data centers or within the same data center, or just deployed to different hardware or to the same hardware.

Even if it’s deployed to the same hardware, a distributed system is one where information has to be transferred between different parts of that system and when that information is transferred it’s crossing some sort of space. It could be going over a local network, or it could be writing to a disk, or it could be writing to a database.

Information cannot be transferred instantaneously, it takes some time. Granted that time could be very small but there is an amount of time that elapses during the transfer of information. Within that time duration when the transfer the information takes place, the state of original sender may change.

The key here is to recognize that when we are dealing with a distributed system, we are always dealing with stale data. Reality is basically eventually consistent.

What is Eventual Consistency?

When a system stops receiving updates at least for some period of time, we can guarantee that all parts of the system will eventually converge on the same state. Thus in this way we can reach that level of consistency.

Common source control tools (Git, Subversion, etc) operate on an eventually consistent model. They rely on a later merge operation in order to bring things back into alignment. That’s how modern source control tools achieve consistency and it’s all an eventually consistent system.

Traditional monolithic architectures are usually based around strong consistency they use a strongly consistent database like a SQL database.

What is Strong Consistency?

When all members of a system agree on the state, before it becomes available, then we reach the level of strong consistency.

We can achieve strong consistency by introducing mechanisms like locks. Distributed system problem occurs when we have multiple things which are responsible for the same piece of data. As long as only one thing is responsible for that data, as long as we only have one instance of the lock, it’s not a distributed system problem anymore. Thus in this way we can resolve the distributed system problem by using a non distributed resource(lock).

But when we introduce a lock, it introduces overhead in the form of contention. That overhead has consequences to our ability to be elastic, to be resilient, and it has other consequences as well.

#microservices #reactive architecture #tech blogs #cap theorm #laws of scalability #reactive microservices #reactive systems #scalability #scalable systems

Flutter Widgets Implementing Material Design

macos_ui

Flutter widgets and themes implementing the current macOS design language.

Check out our interactive widget gallery online at https://groovinchip.github.io/macos_ui/#/

Guides, codelabs, and other documentation can be found at https://macosui.dev

pub package pub package

Flutter Analysis Pana Analysis codecov codecov

🚨 Usage notes

pub.dev shows that macos_ui only supports macOS. This is because macos_ui calls some native code, and therefore specifies macOS as a plugin platform in the pubspec.yaml file. macos_ui will work on any platform that Flutter supports, but you will get best results on macOS.

The features of macos_ui that will not work on platforms other than macOS due to calling native code are:

  • The MacosColors.controlAccentColor() function
  • The MacosColorWell widget

Contents

Contributing & Resources

  •  
    •  
    •  

Layout

  •  
    •  
    •  
    •  
    •  
    •  
    •  

Icons

  •  
    •  

Buttons

  •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  

Dialogs & Sheets

  •  
    •  
    •  

Fields & Labels

  •  
    •  
    •  
  •  
    •  

Indicators

  •  
    •  
      •  
      •  
    •  
      •  
      •  
      •  

Selectors

  •  
    •  
    •  
    •  

Contributing

macos_ui welcomes contributions! Please see CONTRIBUTING.md for more information.

Resources

Layout

MacosWindow

MacosWindow is the basic frame for a macOS-style layout.

 

It supports a Sidebar on the left, an optional TitleBar at the top, and the rest of the window is typically filled out with a MacosScaffold.

A scope for the MacosWindow is provided by MacosWindowScope. The sidebar can be toggled with MacosWindowScope.of(context).toggleSidebar(). Please note that you must wrap your MacosScaffold in a Builder widget in order for this to work properly.

MacosScaffold

The MacosScaffold is what you might call a "page".

The scaffold has a toolbar property and a children property. children accepts a ContentArea widget and multiple ResizablePane widgets. To catch navigation or routes below the scaffold, consider wrapping the MacosScaffold in a CupertinoTabView. By doing so, navigation inside the MacosScaffold will be displayed inside the MacosScaffold area instead of covering the entire window. To push a route outside a MacosScaffold wrapped in a CupertinoTabView, use the root navigator Navigator.of(context, rootNavigator: true)

See the documentation for customizations and ToolBar examples.

Modern window look

A new look for macOS apps was introduced in Big Sur (macOS 11). To match that look in your Flutter app, like our screenshots, your macos/Runner/MainFlutterWindow.swift file should look like this:

import Cocoa
import FlutterMacOS

class BlurryContainerViewController: NSViewController {
  let flutterViewController = FlutterViewController()

  init() {
    super.init(nibName: nil, bundle: nil)
  }

  required init?(coder: NSCoder) {
    fatalError()
  }

  override func loadView() {
    let blurView = NSVisualEffectView()
    blurView.autoresizingMask = [.width, .height]
    blurView.blendingMode = .behindWindow
    blurView.state = .active
    if #available(macOS 10.14, *) {
        blurView.material = .sidebar
    }
    self.view = blurView
  }

  override func viewDidLoad() {
    super.viewDidLoad()

    self.addChild(flutterViewController)

    flutterViewController.view.frame = self.view.bounds
    flutterViewController.view.autoresizingMask = [.width, .height]
    self.view.addSubview(flutterViewController.view)
  }
}

class MainFlutterWindow: NSWindow, NSWindowDelegate {
  override func awakeFromNib() {
    delegate = self
    let blurryContainerViewController = BlurryContainerViewController()
    let windowFrame = self.frame
    self.contentViewController = blurryContainerViewController
    self.setFrame(windowFrame, display: true)

    if #available(macOS 10.13, *) {
      let customToolbar = NSToolbar()
      customToolbar.showsBaselineSeparator = false
      self.toolbar = customToolbar
    }
    self.titleVisibility = .hidden
    self.titlebarAppearsTransparent = true
    if #available(macOS 11.0, *) {
      // Use .expanded if the app will have a title bar, else use .unified
      self.toolbarStyle = .unified
    }

    self.isMovableByWindowBackground = true
    self.styleMask.insert(NSWindow.StyleMask.fullSizeContentView)

    self.isOpaque = false
    self.backgroundColor = .clear

    RegisterGeneratedPlugins(registry: blurryContainerViewController.flutterViewController)

    super.awakeFromNib()
  }

  func window(_ window: NSWindow, willUseFullScreenPresentationOptions proposedOptions: NSApplication.PresentationOptions = []) -> NSApplication.PresentationOptions {
    return [.autoHideToolbar, .autoHideMenuBar, .fullScreen]
  }

  func windowWillEnterFullScreen(_ notification: Notification) {
      self.toolbar?.isVisible = false
  }
  
  func windowDidExitFullScreen(_ notification: Notification) {
      self.toolbar?.isVisible = true
  }
}

See this issue comment for more details on the new look and explanations for how it works.

Please note that if you are using a title bar (TitleBar) in your MacosWindow, you should set the toolbarStyle of NSWindow to .expanded, in order to properly align the close, minimize, zoom window buttons. In any other case, you should keep it as .unified. This must be set beforehand, i.e. it cannot be switched in runtime.

ToolBar

Creates a toolbar in the MacosScaffold. The toolbar appears below the title bar (if present) of the macOS app or integrates with it, by using its title property.

A toolbar provides convenient access to frequently used commands and features (toolbar items). Different routes of your app could have different toolbars.

Toolbar items include ToolBarIconButton, ToolBarPulldownButton, and ToolBarSpacer widgets, and should be provided via the items property. The action of every toolbar item should also be provided as a menu bar command of your app.

Toolbars look best and are easiest to understand when they contain elements of the same type (so either use labels for every toolbar item or not).

You can use the ToolBarSpacer widgets to set the grouping of the different toolbar actions.

An example toolbar would be:

ToolBar(
  title: const Text('Untitled Document'),
  titleWidth: 200.0,
  leading: MacosBackButton(
    onPressed: () => debugPrint('click'),
    fillColor: Colors.transparent,
  ),
  actions: [
    ToolBarIconButton(
      label: "Add",
      icon: const MacosIcon(
        CupertinoIcons.add_circled,
      ),
      onPressed: () => debugPrint("Add..."),
      showLabel: true,
    ),
    const ToolBarSpacer(),
    ToolBarIconButton(
      label: "Delete",
      icon: const MacosIcon(
        CupertinoIcons.trash,
      ),
      onPressed: () => debugPrint("Delete"),
      showLabel: false,
    ),
    ToolBarPullDownButton(
      label: "Actions",
      icon: CupertinoIcons.ellipsis_circle,
      items: [
        MacosPulldownMenuItem(
          label: "New Folder",
          title: const Text("New Folder"),
          onTap: () => debugPrint("Creating new folder..."),
        ),
        MacosPulldownMenuItem(
          label: "Open",
          title: const Text("Open"),
          onTap: () => debugPrint("Opening..."),
        ),
      ],
    ),
  ]
),

This builds this simple toolbar:

Other toolbar examples:

Toolbar with icon buttons (no labels):

Toolbar with icon buttons and labels:

Toolbar with a pulldown button open:

Toolbar with title bar above (also see the note above):

You can also create your own CustomToolbarItem to include any type of widget in the toolbar:

// Add a grey vertical line as a custom toolbar item:
CustomToolbarItem(
  inToolbarBuilder: (context) => Padding(
    padding: const EdgeInsets.all(8.0),
    child: Container(color: Colors.grey, width: 1, height: 30),
  ),
  inOverflowedBuilder: (context) =>
      Container(color: Colors.grey, width: 30, height: 1),
),

MacosListTile

A widget that aims to approximate the [ListTile] widget found in Flutter's material library.

MacosListTile

Usage:

MacosListTile(
  leading: const Icon(CupertinoIcons.lightbulb),
  title: Text(
    'A robust library of Flutter components for macOS',
    style: MacosTheme.of(context).typography.headline,
  ),
  subtitle: Text(
    'Create native looking macOS applications using Flutter',
    style: MacosTheme.of(context).typography.subheadline.copyWith(
      color: MacosColors.systemGrayColor,
    ),
  ),
),

MacosTabView

A multipage interface that displays one page at a time. Must be used in a StatefulWidget.

You can control the placement of the tabs using the position property.

Usage:

final _controller = MacosTabController(
  initialIndex: 0,
  length: 3,
);

...

MacosTabView(
  controller: _controller,
  tabs: const [
    MacosTab(
      label: 'Tab 1',
    ),
    MacosTab(
      label: 'Tab 2',
    ),
    MacosTab(
      label: 'Tab 3',
    ),
  ],
  children: const [
    Center(
      child: Text('Tab 1'),
    ),
    Center(
      child: Text('Tab 2'),
    ),
    Center(
      child: Text('Tab 3'),
    ),
  ],
),        

Icons

MacosIcon

A MacosIcon is identical to a regular Icon in every way with one exception - it respects a MacosTheme. Use it the same way you would a regular icon:

MacosIcon(
  CupertinoIcons.add,
  // color: CupertinoColors.activeBlue.color,
  // size: 20,
),

Buttons

MacosCheckbox

A checkbox is a type of button that lets the user choose between two opposite states, actions, or values. A selected checkbox is considered on when it contains a checkmark and off when it's empty. A checkbox is almost always followed by a title unless it appears in a checklist. Learn more

OffOnMixed
Off CheckboxOn CheckboxMixed Checkbox

Here's an example of how to create a basic checkbox:

bool selected = false;

MacosCheckbox(
  value: selected,
  onChanged: (value) {
    setState(() => selected = value);
  },
)

To make a checkbox in the mixed state, set value to null.

HelpButton

A help button appears within a view and opens app-specific help documentation when clicked. All help buttons are circular, consistently sized buttons that contain a question mark icon. Learn more

HelpButton Example

Here's an example of how to create a help button:

HelpButton(
  onPressed: () {
    print('pressed help button'),
  },
)

You can customize the help button appearance and behaviour using the HelpButtonTheme, but it's not recommended by apple to change help button's appearance.

RadioButton

A radio button is a small, circular button followed by a title. Typically presented in groups of two to five, radio buttons provide the user a set of related but mutually exclusive choices. A radio button’s state is either on (a filled circle) or off (an empty circle). Learn more

RadioButton Preview

Here's an example of how to create a basic radio button:

bool selected = false;

MacosRadioButton(
  value: selected,
  onChanged: (value) {
    setState(() => selected = value);
  },
),

PulldownButton

A pull-down button (often referred to as a pull-down menu) is a type of pop-up button that, when clicked, displays a menu containing a list of choices. The menu appears below the button. Once the menu is displayed onscreen, it remains open until the user chooses a menu item, clicks outside of the menu, switches to another app, or quits the app; or until the system displays an alert. Learn more

Use a pull-down button to present a list of commands. A pull-down button can either show a title or an icon to describe the contents of the button's menu. If you use an icon, make sure it clearly communicates the button’s purpose.

If items is null, the button will be disabled (greyed out).

A title or an icon must be provided, to be displayed as the pull-down button's title, but not both at the same time.

The menu can also be navigated with the up/down keys and an action selected with the Return key.

It can also appear in the toolbar, via the ToolBarPulldownButton widget.

Dark ThemeLight Theme

Here's an example of how to create a basic pull-down button:

MacosPulldownButton(
  title: "Actions",
  // Or provide an icon to use as title:
  // icon: CupertinoIcons.ellipsis_circle, 
  items: [
    MacosPulldownMenuItem(
      title: const Text('Save'),
      onTap: () => debugPrint("Saving..."),
    ),
    MacosPulldownMenuItem(
      title: const Text('Save as...'),
      onTap: () => debugPrint("Opening Save As dialog..."),
    ),
    const MacosPulldownMenuDivider(),
    MacosPulldownMenuItem(
      enabled: false,
      title: const Text('Export'),
      onTap: () => debugPrint("Exporting"),
    ),
  ],
),

PopupButton

A pop-up button (often referred to as a pop-up menu) is a type of button that, when clicked, displays a menu containing a list of mutually exclusive choices. The menu appears on top of the button. Like other types of menus, a pop-up button’s menu can include separators and symbols like checkmarks. After the menu is revealed, it remains open until the user chooses a menu item, clicks outside of the menu, switches to another app, or quits the app; or until the system displays an alert. Learn more

The type T of the MacosPopupButton is the type of the value that each pop-up menu item represents. All the entries in a given menu must represent values with consistent types. Typically, an enum is used. Each MacosPopupMenuItem in items must be specialized with that same type argument.

The onChanged callback should update a state variable that defines the pop-up menu's value. It should also call State.setState to rebuild the pop-up button with the new value.

When there are menu items that cannot be displayed within the available menu constraints, a caret is shown at the top or bottom of the open menu to signal that there are items that are not currently visible.

The menu can also be navigated with the up/down keys and an item selected with the Return key.

Dark ThemeLight Theme

Here's an example of how to create a basic pop-up button:

String popupValue = 'One';

MacosPopupButton<String>(
  value: popupValue,
  onChanged: (String? newValue) {
    setState(() {
      popupValue = newValue!;
    });
  },
  items: <String>['One', 'Two', 'Three', 'Four']
      .map<MacosPopupMenuItem<String>>((String value) {
    return MacosPopupMenuItem<String>(
      value: value,
      child: Text(value),
    );
  }).toList(),
),

PushButton

A push button appears within a view and initiates an instantaneous app-specific action, such as printing a document or deleting a file. Push buttons contain text—not icons—and often open a separate window, dialog, or app so the user can complete a task. Learn more

Dark ThemeLight Theme

Here's an example of how to create a basic push button:

PushButton(
  child: Text('button'),
  buttonSize: ButtonSize.large,
  onPressed: () {
    print('button pressed');
  },
),

MacosSwitch

A switch is a visual toggle between two mutually exclusive states — on and off. A switch shows that it's on when the accent color is visible and off when the switch appears colorless. Learn more

OnOff

Here's an example of how to create a basic toggle switch:

bool selected = false;

MacosSwitch(
  value: selected,
  onChanged: (value) {
    setState(() => selected = value);
  },
),

MacosSegmentedControl

Displays one or more navigational tabs in a single horizontal group. Used by MacosTabView to navigate between the different tabs of the tab bar.

The typical usage of this widget is by MacosTabView, to control the navigation of its children. You do not need to specify a MacosSegmentedControl with your MacosTabView, as it is built by that widget.

Dialogs and Sheets

MacosAlertDialog

Usage:

showMacosAlertDialog(
  context: context,
  builder: (_) => MacosAlertDialog(
    appIcon: FlutterLogo(
      size: 56,
    ),
    title: Text(
      'Alert Dialog with Primary Action',
      style: MacosTheme.of(context).typography.headline,
    ),
    message: Text(
      'This is an alert dialog with a primary action and no secondary action',
      textAlign: TextAlign.center,
      style: MacosTheme.of(context).typography.headline,
    ),
    primaryButton: PushButton(
      buttonSize: ButtonSize.large,
      child: Text('Primary'),
      onPressed: () {},
    ),
  ),
);

MacosSheet

Usage:

showMacosSheet(
  context: context,
  builder: (_) => const MacosuiSheet(),
);

Fields

MacosTextField

A text field is a rectangular area in which the user enters or edits one or more lines of text. A text field can contain plain or styled text.

Here's an example of how to create a basic text field:

MacosTextField(
  placeholder: 'Type some text here',
)

MacosSearchField

A search field is a style of text field optimized for performing text-based searches in a large collection of values.

When the user starts typing into the search field, a list of selectable results appears in an overlay below (or above) the field.

Dark ThemeLight Theme

Here's an example of how to create a search field:

MacosSearchField(
  placeholder: 'Search for a country...',
  results: countries.map((e) => SearchResultItem(e)).toList(),
  onResultSelected: (resultItem) {
    debugPrint(resultItem.searchKey);
  },
)

Check the examples/fields_page for more examples.

Labels

Labels are a short description of what an element on the screen does.

MacosTooltip

Tooltips succinctly describe how to use controls without shifting people’s focus away from the primary interface. Help tags appear when the user positions the pointer over a control for a few seconds. A tooltip remains visible for 10 seconds, or until the pointer moves away from the control.

Dark ThemeLight Theme

To create a tooltip, wrap any widget on a MacosTooltip:

MacosTooltip(
  message: 'This is a tooltip',
  child: Text('Hover or long press to show a tooltip'),
),

You can customize the tooltip the way you want by customizing the theme's TooltipTheme. A tooltip automatically adapts to its environment, responding to touch and pointer events. To use a tooltip with a toolbar item, provide it with a tooltipMessage property.

Indicators

Progress Indicators

Don’t make people sit around staring at a static screen waiting for your app to load content or perform lengthy data processing operations. Use progress indicators to let people know your app hasn't stalled and to give them some idea of how long they’ll be waiting.

Progress indicators have two distinct styles:

  • Bar indicators, more commonly known as progress bars, show progress in a horizontal bar.
  • Spinning indicators show progress in a circular form, either as a spinner or as a circle that fills in as progress continues.

People don't interact with progress indicators; however, they are often accompanied by a button for canceling the corresponding operation. Learn more

Progress Indicator Example

ProgressCircle

A ProgressCircle can be either determinate or indeterminate.

Determinate Progress CircleIndeterminate Progress Circle

Here's an example of how to create an indeterminate progress circle:

ProgressCircle(
  value: null,
),

You can provide a non-null value to value to make the progress circle determinate.

ProgressBar

A ProgressBar can only be determinate.

Here's an example of how to create a determinate progress bar:

ProgressBar(
  value: 30,
)

Level Indicators

A level indicator graphically represents of a specific value within a range of numeric values. It’s similar to a slider in purpose, but more visual and doesn’t contain a distinct control for selecting a value—clicking and dragging across the level indicator itself to select a value is supported, however. A level indicator can also include tick marks, making it easy for the user to pinpoint a specific value in the range. There are three different level indicator styles, each with a different appearance, for communicating capacity, rating, and relevance.

CapacityIndicator

A capacity indicator illustrates the current level in relation to a finite capacity. Capacity indicators are often used when communicating factors like disk and battery usage. Learn more

ContinuousDiscrete
Continuous CapacityIndicator ExampleDiscrete CapacityIndicator Example
A horizontal translucent track that fills with a colored bar to indicate the current value. Tick marks are often displayed to provide context.A horizontal row of separate, equally sized, rectangular segments. The number of segments matches the total capacity, and the segments fill completely—never partially—with color to indicate the current value.

Here's an example of how to create an interactive continuous capacity indicator:

double value = 30;

CapacityIndicator(
  value: value,
  discrete: false,
  onChanged: (v) {
    setState(() => value = v);
  },
),

You can set discrete to true to make it a discrete capacity indicator.

RatingIndicator

A rating indicator uses a series of horizontally arranged graphical symbols to communicate a ranking level. The default symbol is a star.

RatingIndicator Example

A rating indicator doesn’t display partial symbols—its value is rounded in order to display complete symbols only. Within a rating indicator, symbols are always the same distance apart and don't expand or shrink to fit the control. Learn more

Here's an example of how to create an interactive rating indicator:

double value = 3;

RatingIndicator(
  amount: 5,
  value: value,
  onChanged: (v) {
    setState(() => value = v);
  }
)

RelevanceIndicator

A relevance indicator communicates relevancy using a series of vertical bars. It often appears in a list of search results for reference when sorting and comparing multiple items. Learn more

RelevanceIndicator Example

Here's an example of how to create a relevance indicator:

RelevanceIndicator(
  value: 15,
  amount: 20,
)

Selectors

MacosDatePicker

Lets the user choose a date.

There are three styles of MacosDatePickers:

  • textual: a text-only date picker where the user must select the day, month, or year and use the caret-control buttons to change the value. This is useful when space in your app is constrained.
  • graphical: a visual date picker where the user can navigate through a calendar-like interface to select a date.
  • combined: provides both textual and graphical interfaces.

Example usage:

MacosDatePicker(
  onDateChanged: (date) => debugPrint('$date'),
),

MacosTimePicker

Lets the user choose a time.

There are three styles of MacosTimePickers:

  • textual: a text-only time picker where the user must select the hour or minute and use the caret-control buttons to change the value. This is useful when space in your app is constrained.
  • graphical: a visual time picker where the user can move the hands of a clock-like interface to select a time.
  • combined: provides both textual and graphical interfaces.

Example usage:

MacosTimePicker(
  onTimeChanged: (time) => debugPrint('$time'),
),

MacosColorWell #

Lets the user choose a color via the native macOS color picker.

You can choose which mode to launch the picker in using the ColorPickerMode enum. The default is ColorPickerMode.wheel

🚨 This widget will not work on platforms other than macOS!

Example usage:

MacosColorWell(
  onColorSelected: (color) => debugPrint('$color'),
),

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add macos_ui

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  macos_ui: ^1.7.5

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:macos_ui/macos_ui.dart'; 

example/lib/main.dart

import 'package:example/pages/buttons_page.dart';
import 'package:example/pages/colors_page.dart';
import 'package:example/pages/dialogs_page.dart';
import 'package:example/pages/fields_page.dart';
import 'package:example/pages/indicators_page.dart';
import 'package:example/pages/selectors_page.dart';
import 'package:example/pages/tabview_page.dart';
import 'package:example/pages/toolbar_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:macos_ui/macos_ui.dart';
import 'package:provider/provider.dart';

import 'theme.dart';

void main() {
  runApp(const MacosUIGalleryApp());
}

class MacosUIGalleryApp extends StatelessWidget {
  const MacosUIGalleryApp({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (_) => AppTheme(),
      builder: (context, _) {
        final appTheme = context.watch<AppTheme>();
        return MacosApp(
          title: 'macos_ui Widget Gallery',
          theme: MacosThemeData.light(),
          darkTheme: MacosThemeData.dark(),
          themeMode: appTheme.mode,
          debugShowCheckedModeBanner: false,
          home: const WidgetGallery(),
        );
      },
    );
  }
}

class WidgetGallery extends StatefulWidget {
  const WidgetGallery({super.key});

  @override
  State<WidgetGallery> createState() => _WidgetGalleryState();
}

class _WidgetGalleryState extends State<WidgetGallery> {
  double ratingValue = 0;
  double sliderValue = 0;
  bool value = false;

  int pageIndex = 0;

  late final searchFieldController = TextEditingController();

  final List<Widget> pages = [
    CupertinoTabView(
      builder: (_) => const ButtonsPage(),
    ),
    const IndicatorsPage(),
    const FieldsPage(),
    const ColorsPage(),
    const Center(
      child: MacosIcon(
        CupertinoIcons.add,
      ),
    ),
    const DialogsPage(),
    const ToolbarPage(),
    const SelectorsPage(),
    const TabViewPage(),
  ];

  @override
  Widget build(BuildContext context) {
    return PlatformMenuBar(
      menus: const [
        PlatformMenu(
          label: 'macos_ui Widget Gallery',
          menus: [
            PlatformProvidedMenuItem(
              type: PlatformProvidedMenuItemType.about,
            ),
            PlatformProvidedMenuItem(
              type: PlatformProvidedMenuItemType.quit,
            ),
          ],
        ),
        PlatformMenu(
          label: 'View',
          menus: [
            PlatformProvidedMenuItem(
              type: PlatformProvidedMenuItemType.toggleFullScreen,
            ),
          ],
        ),
        PlatformMenu(
          label: 'Window',
          menus: [
            PlatformProvidedMenuItem(
              type: PlatformProvidedMenuItemType.minimizeWindow,
            ),
            PlatformProvidedMenuItem(
              type: PlatformProvidedMenuItemType.zoomWindow,
            ),
          ],
        ),
      ],
      child: MacosWindow(
        sidebar: Sidebar(
          top: MacosSearchField(
            placeholder: 'Search',
            controller: searchFieldController,
            onResultSelected: (result) {
              switch (result.searchKey) {
                case 'Buttons':
                  setState(() {
                    pageIndex = 0;
                    searchFieldController.clear();
                  });
                  break;
                case 'Indicators':
                  setState(() {
                    pageIndex = 1;
                    searchFieldController.clear();
                  });
                  break;
                case 'Fields':
                  setState(() {
                    pageIndex = 2;
                    searchFieldController.clear();
                  });
                  break;
                case 'Colors':
                  setState(() {
                    pageIndex = 3;
                    searchFieldController.clear();
                  });
                  break;
                case 'Dialogs and Sheets':
                  setState(() {
                    pageIndex = 5;
                    searchFieldController.clear();
                  });
                  break;
                case 'Toolbar':
                  setState(() {
                    pageIndex = 6;
                    searchFieldController.clear();
                  });
                  break;
                case 'Selectors':
                  setState(() {
                    pageIndex = 7;
                    searchFieldController.clear();
                  });
                  break;
                default:
                  searchFieldController.clear();
              }
            },
            results: const [
              SearchResultItem('Buttons'),
              SearchResultItem('Indicators'),
              SearchResultItem('Fields'),
              SearchResultItem('Colors'),
              SearchResultItem('Dialogs and Sheets'),
              SearchResultItem('Toolbar'),
              SearchResultItem('Selectors'),
            ],
          ),
          minWidth: 200,
          builder: (context, controller) {
            return SidebarItems(
              currentIndex: pageIndex,
              onChanged: (i) => setState(() => pageIndex = i),
              scrollController: controller,
              itemSize: SidebarItemSize.large,
              items: [
                const SidebarItem(
                  // leading: MacosIcon(CupertinoIcons.square_on_circle),
                  leading: MacosImageIcon(
                    AssetImage(
                      'assets/sf_symbols/button_programmable_2x.png',
                    ),
                  ),
                  label: Text('Buttons'),
                ),
                const SidebarItem(
                  leading: MacosImageIcon(
                    AssetImage(
                      'assets/sf_symbols/lines_measurement_horizontal_2x.png',
                    ),
                  ),
                  label: Text('Indicators'),
                ),
                const SidebarItem(
                  leading: MacosImageIcon(
                    AssetImage(
                      'assets/sf_symbols/character_cursor_ibeam_2x.png',
                    ),
                  ),
                  label: Text('Fields'),
                ),
                SidebarItem(
                  leading: const MacosIcon(CupertinoIcons.folder),
                  label: const Text('Disclosure'),
                  trailing: Text(
                    '2',
                    style: TextStyle(
                      color: MacosTheme.brightnessOf(context) == Brightness.dark
                          ? MacosColors.tertiaryLabelColor.darkColor
                          : MacosColors.tertiaryLabelColor,
                    ),
                  ),
                  disclosureItems: [
                    const SidebarItem(
                      leading: MacosImageIcon(
                        AssetImage(
                          'assets/sf_symbols/rectangle_3_group_2x.png',
                        ),
                      ),
                      label: Text('Colors'),
                    ),
                    const SidebarItem(
                      leading: MacosIcon(CupertinoIcons.infinite),
                      label: Text('Item 3'),
                    ),
                  ],
                ),
                const SidebarItem(
                  leading: MacosIcon(CupertinoIcons.square_on_square),
                  label: Text('Dialogs & Sheets'),
                ),
                const SidebarItem(
                  leading: MacosIcon(CupertinoIcons.macwindow),
                  label: Text('Toolbar'),
                ),
                const SidebarItem(
                  leading: MacosImageIcon(
                    AssetImage(
                      'assets/sf_symbols/filemenu_and_selection_2x.png',
                    ),
                  ),
                  label: Text('Selectors'),
                ),
                const SidebarItem(
                  leading: MacosIcon(CupertinoIcons.uiwindow_split_2x1),
                  label: Text('TabView'),
                ),
              ],
            );
          },
          bottom: const MacosListTile(
            leading: MacosIcon(CupertinoIcons.profile_circled),
            title: Text('Tim Apple'),
            subtitle: Text('tim@apple.com'),
          ),
        ),
        endSidebar: Sidebar(
          startWidth: 200,
          minWidth: 200,
          maxWidth: 300,
          shownByDefault: false,
          builder: (context, scrollController) {
            return const Center(
              child: Text('End Sidebar'),
            );
          },
        ),
        child: IndexedStack(
          index: pageIndex,
          children: pages,
        ),
      ),
    );
  }
} 

Download Details:

Author: 

Source Code: https://pub.dev/packages/macos_ui

#flutter #android #ios 

Hunter  Krajcik

Hunter Krajcik

1648208700

Flutter Widgets, Themes Implementing The Current MacOS Design Language

macos_ui

Flutter widgets and themes implementing the current macOS design language.

Content

Contributing

macOS welcomes contributions. Please see CONTRIBUTING.md for more information.

Resources

Layout

MacosWindow

MacosWindow is the basic frame for the macOS layout.

It has a Sidebar on the left and the rest of the window is typically filled out with a MacosScaffold. A scope for the MacosWindow is provided by MacosWindowScope. The sidebar can be toggled with MacosWindowScope.of(context).toggleSidebar(). Please note that you must wrap your MacosScaffold in a Builder widget in order for this to work properly.

MacosScaffold

The MacosScaffold is what you would call a "page".

The scaffold has a TitleBar property and the children property which accepts a ContentArea widget and multiple ResizablePane widgets. To catch navigation or routes below the scaffold, consider wrapping the MacosScaffold in a CupertinoTabView. By doing so, navigation inside the MacosScaffold will be displayed inside the MacosScaffold area instead of covering the entire window. To push a route outside a MacosScaffold wrapped in a CupertinoTabView, use the root navigator Navigator.of(context, rootNavigator: true)

See the documentation for customizations.

Modern window look

A new look for macOS apps was introduced in Big Sur (macOS 11). To match that look in your Flutter app, like our screenshots, your macos/Runner/MainFlutterWindow.swift file should look like this.

import Cocoa
import FlutterMacOS

class MainFlutterWindow: NSWindow {
  override func awakeFromNib() {
    let flutterViewController = FlutterViewController.init()
    let windowFrame = self.frame
    self.contentViewController = flutterViewController
    self.setFrame(windowFrame, display: true)

    if #available(macOS 10.13, *) {
      let customToolbar = NSToolbar()
      customToolbar.showsBaselineSeparator = false
      self.toolbar = customToolbar
    }
    self.titleVisibility = .hidden
    self.titlebarAppearsTransparent = true
    if #available(macOS 11.0, *) {
      self.toolbarStyle = .unified
    }

    self.isMovableByWindowBackground = true
    self.styleMask.insert(NSWindow.StyleMask.fullSizeContentView)

    self.isOpaque = false
    self.backgroundColor = .clear
    let contentView = contentViewController!.view;
    let superView = contentView.superview!;
    let blurView = NSVisualEffectView()
    blurView.frame = superView.bounds
    blurView.autoresizingMask = [.width, .height]
    blurView.blendingMode = NSVisualEffectView.BlendingMode.behindWindow
    if #available(macOS 10.14, *) {
      blurView.material = .underWindowBackground
    }
    superView.replaceSubview(contentView, with: blurView)
    blurView.addSubview(contentView)

    RegisterGeneratedPlugins(registry: flutterViewController)

    super.awakeFromNib()
  }
}

MacosListTile

A widget that aims to approximate the [ListTile] widget found in Flutter's material library.

MacosListTile

Usage:

MacosListTile(
  leading: const Icon(CupertinoIcons.lightbulb),
  title: Text(
    'A robust library of Flutter components for macOS',
    style: MacosTheme.of(context).typography.headline,
  ),
  subtitle: Text(
    'Create native looking macOS applications using Flutter',
    style: MacosTheme.of(context).typography.subheadline.copyWith(
      color: MacosColors.systemGrayColor,
    ),
  ),
),

Icons

MacosIcon

A MacosIcon is identical to a regular Icon in every way with one exception - it respects a MacosTheme. Use it the same way you would a regular icon:

MacosIcon(
  CupertinoIcons.add,
  // color: CupertinoColors.activeBlue.color,
  // size: 20,
),

Buttons

MacosCheckbox

A checkbox is a type of button that lets the user choose between two opposite states, actions, or values. A selected checkbox is considered on when it contains a checkmark and off when it's empty. A checkbox is almost always followed by a title unless it appears in a checklist. Learn more

OffOnMixed
Off CheckboxOn CheckboxMixed Checkbox

Here's an example of how to create a basic checkbox:

bool selected = false;

MacosCheckbox(
  value: selected,
  onChanged: (value) {
    setState(() => selected = value);
  },
)

To make a checkbox in the mixed state, set value to null.

HelpButton

A help button appears within a view and opens app-specific help documentation when clicked. All help buttons are circular, consistently sized buttons that contain a question mark icon. Learn more

HelpButton Example

Here's an example of how to create a help button:

HelpButton(
  onPressed: () {
    print('pressed help button'),
  },
)

You can customize the help button appearance and behaviour using the HelpButtonTheme, but it's not recommended by apple to change help button's appearance.

RadioButton

A radio button is a small, circular button followed by a title. Typically presented in groups of two to five, radio buttons provide the user a set of related but mutually exclusive choices. A radio button’s state is either on (a filled circle) or off (an empty circle). Learn more

RadioButton Preview

Here's an example of how to create a basic radio button:

bool selected = false;

MacosRadioButton(
  value: selected,
  onChanged: (value) {
    setState(() => selected = value);
  },
),

Pop-Up Button

A pop-up button (often referred to as a pop-up menu) is a type of button that, when clicked, displays a menu containing a list of mutually exclusive choices. The menu appears on top of the button. Like other types of menus, a pop-up button’s menu can include separators and symbols like checkmarks. After the menu is revealed, it remains open until the user chooses a menu item, clicks outside of the menu, switches to another app, or quits the app; or until the system displays an alert. Learn more

The type T of the MacosPopupButton is the type of the value that each pop-up menu item represents. All the entries in a given menu must represent values with consistent types. Typically, an enum is used. Each MacosPopupMenuItem in items must be specialized with that same type argument.

The onChanged callback should update a state variable that defines the pop-up menu's value. It should also call State.setState to rebuild the pop-up button with the new value.

When there are menu items that cannot be displayed within the available menu constraints, a caret is shown at the top or bottom of the open menu to signal that there are items that are not currently visible.

The menu can also be navigated with the up/down keys and an item selected with the Return key.

Dark ThemeLight Theme

Here's an example of how to create a basic pop-up button:

String popupValue = 'One';

MacosPopupButton<String>(
  value: popupValue,
  onChanged: (String? newValue) {
    setState(() {
      popupValue = newValue!;
    });
  },
  items: <String>['One', 'Two', 'Three', 'Four']
      .map<MacosPopupMenuItem<String>>((String value) {
    return MacosPopupMenuItem<String>(
      value: value,
      child: Text(value),
    );
  }).toList(),
),

PushButton

A push button appears within a view and initiates an instantaneous app-specific action, such as printing a document or deleting a file. Push buttons contain text—not icons—and often open a separate window, dialog, or app so the user can complete a task. Learn more

Dark ThemeLight Theme

Here's an example of how to create a basic push button:

PushButton(
  child: Text('button'),
  buttonSize: ButtonSize.large,
  onPressed: () {
    print('button pressed');
  },
),

MacosSwitch

A switch is a visual toggle between two mutually exclusive states — on and off. A switch shows that it's on when the accent color is visible and off when the switch appears colorless. Learn more

OnOff

Here's an example of how to create a basic toggle switch:

bool selected = false;

MacosSwitch(
  value: selected,
  onChanged: (value) {
    setState(() => selected = value);
  },
),

Dialogs and Sheets

MacosAlertDialog

Usage:

showMacosAlertDialog(
  context: context,
  builder: (_) => MacosAlertDialog(
    appIcon: FlutterLogo(
      size: 56,
    ),
    title: Text(
      'Alert Dialog with Primary Action',
      style: MacosTheme.of(context).typography.headline,
    ),
    message: Text(
      'This is an alert dialog with a primary action and no secondary action',
      textAlign: TextAlign.center,
      style: MacosTheme.of(context).typography.headline,
    ),
    primaryButton: PushButton(
      buttonSize: ButtonSize.large,
      child: Text('Primary'),
      onPressed: () {},
    ),
  ),
);

MacosSheet

Usage:

showMacosSheet(
  context: context,
  builder: (_) => const MacosuiSheet(),
);

Fields

MacosTextField

A text field is a rectangular area in which the user enters or edits one or more lines of text. A text field can contain plain or styled text.

Here's an example of how to create a basic text field:

MacosTextField(),

Labels

Labels are a short description of what an element on the screen does.

MacosTooltip

Tooltips succinctly describe how to use controls without shifting people’s focus away from the primary interface. Help tags appear when the user positions the pointer over a control for a few seconds. A tooltip remains visible for 10 seconds, or until the pointer moves away from the control.

Tooltip Example

To create a tooltip, wrap any widget on a Tooltip:

MacosTooltip(
  message: 'This is a tooltip',
  child: Text('Hover or long press to show a tooltip'),
),

You can customize the tooltip the way you want using its style property. A tooltip automatically adapts to its environment, responding to touch and pointer events.

Indicators

Progress Indicators

Don’t make people sit around staring at a static screen waiting for your app to load content or perform lengthy data processing operations. Use progress indicators to let people know your app hasn't stalled and to give them some idea of how long they’ll be waiting.

Progress indicators have two distinct styles:

  • Bar indicators, more commonly known as progress bars, show progress in a horizontal bar.
  • Spinning indicators show progress in a circular form, either as a spinner or as a circle that fills in as progress continues.

People don't interact with progress indicators; however, they are often accompanied by a button for canceling the corresponding operation. Learn more

Progress Indicator Example

ProgressCircle

A ProgressCircle can be either determinate or indeterminate.

Determinate Progress CircleIndeterminate Progress Circle

Here's an example of how to create an indeterminate progress circle:

ProgressCircle(
  value: null,
),

You can provide a non-null value to value to make the progress circle determinate.

ProgressBar

A ProgressBar can only be determinate.

Here's an example of how to create a determinate progress bar:

ProgressBar(
  value: 30,
)

Level Indicators

A level indicator graphically represents of a specific value within a range of numeric values. It’s similar to a slider in purpose, but more visual and doesn’t contain a distinct control for selecting a value—clicking and dragging across the level indicator itself to select a value is supported, however. A level indicator can also include tick marks, making it easy for the user to pinpoint a specific value in the range. There are three different level indicator styles, each with a different appearance, for communicating capacity, rating, and relevance.

CapacityIndicator

A capacity indicator illustrates the current level in relation to a finite capacity. Capacity indicators are often used when communicating factors like disk and battery usage. Learn more

ContinuousDiscrete
Continuous CapacityIndicator ExampleDiscrete CapacityIndicator Example
A horizontal translucent track that fills with a colored bar to indicate the current value. Tick marks are often displayed to provide context.A horizontal row of separate, equally sized, rectangular segments. The number of segments matches the total capacity, and the segments fill completely—never partially—with color to indicate the current value.

Here's an example of how to create an interactive continuous capacity indicator:

double value = 30;

CapacityIndicator(
  value: value,
  discrete: false,
  onChanged: (v) {
    setState(() => value = v);
  },
),

You can set discrete to true to make it a discrete capacity indicator.

RatingIndicator

A rating indicator uses a series of horizontally arranged graphical symbols to communicate a ranking level. The default symbol is a star.

RatingIndicator Example

A rating indicator doesn’t display partial symbols—its value is rounded in order to display complete symbols only. Within a rating indicator, symbols are always the same distance apart and don't expand or shrink to fit the control. Learn more

Here's an example of how to create an interactive rating indicator:

double value = 3;

RatingIndicator(
  amount: 5,
  value: value,
  onChanged: (v) {
    setState(() => value = v);
  }
)

RelevanceIndicator

A relevance indicator communicates relevancy using a series of vertical bars. It often appears in a list of search results for reference when sorting and comparing multiple items. Learn more

RelevanceIndicator Example

Here's an example of how to create a relevance indicator:

RelevanceIndicator(
  value: 15,
  amount: 20,
)

Author: GroovinChip
Source Code: https://github.com/GroovinChip/macos_ui 
License: MIT License

#flutter #dart