[libadwaita/wip/exalm/new-demo: 37/37] New demo




commit 273d22f3a66c67f427a38b9ea5831359d5be044c
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Thu Jan 14 13:38:26 2021 +0500

    New demo

 demo/adw-demo-page-info.c                          | 143 +++++
 demo/adw-demo-page-info.h                          |  15 +
 demo/adw-demo-page.c                               | 152 +++++
 demo/adw-demo-page.h                               |  16 +
 demo/adw-demo-page.ui                              |  44 ++
 demo/adw-demo-window.c                             | 114 ++++
 demo/adw-demo-window.h                             |  13 +
 demo/adw-demo-window.ui                            | 148 +++++
 demo/adwaita-demo.c                                |  45 ++
 demo/adwaita-demo.gresources.xml                   |  26 +
 .../icons/scalable/actions/call-start-symbolic.svg |   1 +
 .../scalable/actions/data-movies-symbolic.svg      |  10 +
 .../icons/scalable/actions/data-music-symbolic.svg |   3 +
 .../scalable/actions/data-photos-symbolic.svg      |   3 +
 .../scalable/actions/data-podcasts-symbolic.svg    |   8 +
 .../scalable/actions/document-edit-symbolic.svg    |   1 +
 demo/icons/scalable/actions/edit-copy-symbolic.svg |   1 +
 demo/icons/scalable/actions/edit-cut-symbolic.svg  |   1 +
 .../scalable/actions/library-music-symbolic.svg    |   6 +
 .../actions/media-playback-start-symbolic.svg      |   1 +
 demo/icons/scalable/actions/open-link-symbolic.svg |  46 ++
 .../icons/scalable/actions/page-lists-symbolic.svg |  78 +++
 .../actions/star-outline-thick-symbolic.svg        |  71 +++
 demo/meson.build                                   |  32 +
 demo/org.gnome.Adwaita.Demo.json                   |  49 ++
 demo/pages/controls/adw-demo-page-controls.c       |  30 +
 demo/pages/controls/adw-demo-page-controls.h       |  11 +
 demo/pages/controls/adw-demo-page-controls.ui      | 657 +++++++++++++++++++++
 demo/pages/lists/adw-demo-page-lists.c             |  53 ++
 demo/pages/lists/adw-demo-page-lists.h             |  11 +
 demo/pages/lists/adw-demo-page-lists.ui            | 433 ++++++++++++++
 demo/pages/stub/adw-demo-page-stub.c               |  22 +
 demo/pages/stub/adw-demo-page-stub.h               |  11 +
 demo/pages/stub/adw-demo-page-stub.ui              |  14 +
 demo/style.css                                     |   9 +
 meson.build                                        |   2 +-
 36 files changed, 2279 insertions(+), 1 deletion(-)
---
diff --git a/demo/adw-demo-page-info.c b/demo/adw-demo-page-info.c
new file mode 100644
index 0000000..3254150
--- /dev/null
+++ b/demo/adw-demo-page-info.c
@@ -0,0 +1,143 @@
+#include "adw-demo-page-info.h"
+
+#include <glib/gi18n.h>
+
+#include "adw-demo-page.h"
+
+struct _AdwDemoPageInfo
+{
+  GObject parent_instance;
+
+  char *icon_name;
+  char *title;
+  GType gtype;
+};
+
+G_DEFINE_TYPE (AdwDemoPageInfo, adw_demo_page_info, G_TYPE_OBJECT)
+
+enum {
+  PROP_0,
+  PROP_ICON_NAME,
+  PROP_TITLE,
+  PROP_GTYPE,
+  LAST_PROP
+};
+
+static GParamSpec *props[LAST_PROP];
+
+static inline void
+set_string (char       **dest,
+            const char  *source)
+{
+  if (*dest)
+    g_free (*dest);
+
+  *dest = g_strdup (source);
+}
+
+static void
+adw_demo_page_info_finalize (GObject *object)
+{
+  AdwDemoPageInfo *self = ADW_DEMO_PAGE_INFO (object);
+
+  g_clear_pointer (&self->title, g_free);
+  g_clear_pointer (&self->icon_name, g_free);
+
+  G_OBJECT_CLASS (adw_demo_page_info_parent_class)->finalize (object);
+}
+
+static void
+adw_demo_page_info_get_property (GObject    *object,
+                                 guint       prop_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  AdwDemoPageInfo *self = ADW_DEMO_PAGE_INFO (object);
+
+  switch (prop_id) {
+  case PROP_ICON_NAME:
+    g_value_set_string (value, self->icon_name);
+    break;
+  case PROP_TITLE:
+    g_value_set_string (value, self->title);
+    break;
+  case PROP_GTYPE:
+    g_value_set_gtype (value, self->gtype);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+  }
+}
+
+static void
+adw_demo_page_info_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  AdwDemoPageInfo *self = ADW_DEMO_PAGE_INFO (object);
+
+  switch (prop_id) {
+  case PROP_ICON_NAME:
+    set_string (&self->icon_name, g_value_get_string (value));
+    break;
+  case PROP_TITLE:
+    set_string (&self->title, g_value_get_string (value));
+    break;
+  case PROP_GTYPE:
+    self->gtype = g_value_get_gtype (value);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+  }
+}
+
+static void
+adw_demo_page_info_class_init (AdwDemoPageInfoClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = adw_demo_page_info_finalize;
+  object_class->get_property = adw_demo_page_info_get_property;
+  object_class->set_property = adw_demo_page_info_set_property;
+
+  props[PROP_ICON_NAME] =
+    g_param_spec_string ("icon-name",
+                         _("Icon Name"),
+                         _("Icon Name"),
+                         NULL,
+                         G_PARAM_READWRITE);
+
+  props[PROP_TITLE] =
+    g_param_spec_string ("title",
+                         _("Title"),
+                         _("Title"),
+                         NULL,
+                         G_PARAM_READWRITE);
+
+  props[PROP_GTYPE] =
+    g_param_spec_gtype ("gtype",
+                         _("Type"),
+                         _("Type"),
+                         ADW_TYPE_DEMO_PAGE,
+                         G_PARAM_READWRITE);
+
+  g_object_class_install_properties (object_class, LAST_PROP, props);
+}
+
+static void
+adw_demo_page_info_init (AdwDemoPageInfo *self)
+{
+}
+
+AdwDemoPageInfo *
+adw_demo_page_info_new (const char *title,
+                        const char *icon_name,
+                        GType       type)
+{
+  return g_object_new (ADW_TYPE_DEMO_PAGE_INFO,
+                       "title", title,
+                       "icon-name", icon_name,
+                       "gtype", type,
+                       NULL);
+}
diff --git a/demo/adw-demo-page-info.h b/demo/adw-demo-page-info.h
new file mode 100644
index 0000000..b268bfc
--- /dev/null
+++ b/demo/adw-demo-page-info.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define ADW_TYPE_DEMO_PAGE_INFO (adw_demo_page_info_get_type())
+
+G_DECLARE_FINAL_TYPE (AdwDemoPageInfo, adw_demo_page_info, ADW, DEMO_PAGE_INFO, GObject)
+
+AdwDemoPageInfo *adw_demo_page_info_new (const char *title,
+                                         const char *icon_name,
+                                         GType       type);
+
+G_END_DECLS
diff --git a/demo/adw-demo-page.c b/demo/adw-demo-page.c
new file mode 100644
index 0000000..4f05a6b
--- /dev/null
+++ b/demo/adw-demo-page.c
@@ -0,0 +1,152 @@
+#include "adw-demo-page.h"
+
+#include <glib/gi18n.h>
+
+typedef struct
+{
+  gboolean show_back_button;
+  char *title;
+  GtkWidget *child;
+
+  GtkWidget *header_bar;
+  GtkWidget *child_bin;
+} AdwDemoPagePrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (AdwDemoPage, adw_demo_page, GTK_TYPE_WIDGET)
+
+enum {
+  PROP_0,
+  PROP_SHOW_BACK_BUTTON,
+  PROP_TITLE,
+  PROP_CHILD,
+  LAST_PROP
+};
+
+static GParamSpec *props[LAST_PROP];
+
+static inline void
+set_string (char       **dest,
+            const char  *source)
+{
+  if (*dest)
+    g_free (*dest);
+
+  *dest = g_strdup (source);
+}
+
+static void
+adw_demo_page_dispose (GObject *object)
+{
+  AdwDemoPage *self = ADW_DEMO_PAGE (object);
+  AdwDemoPagePrivate *priv = adw_demo_page_get_instance_private (self);
+
+  gtk_widget_unparent (priv->header_bar);
+  gtk_widget_unparent (priv->child_bin);
+  g_clear_object (&priv->child);
+
+  G_OBJECT_CLASS (adw_demo_page_parent_class)->dispose (object);
+}
+
+static void
+adw_demo_page_finalize (GObject *object)
+{
+  AdwDemoPage *self = ADW_DEMO_PAGE (object);
+  AdwDemoPagePrivate *priv = adw_demo_page_get_instance_private (self);
+
+  g_clear_pointer (&priv->title, g_free);
+
+  G_OBJECT_CLASS (adw_demo_page_parent_class)->finalize (object);
+}
+
+static void
+adw_demo_page_get_property (GObject    *object,
+                            guint       prop_id,
+                            GValue     *value,
+                            GParamSpec *pspec)
+{
+  AdwDemoPage *self = ADW_DEMO_PAGE (object);
+  AdwDemoPagePrivate *priv = adw_demo_page_get_instance_private (self);
+
+  switch (prop_id) {
+  case PROP_SHOW_BACK_BUTTON:
+    g_value_set_boolean (value, priv->show_back_button);
+    break;
+  case PROP_TITLE:
+    g_value_set_string (value, priv->title);
+    break;
+  case PROP_CHILD:
+    g_value_set_object (value, priv->child);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+  }
+}
+
+static void
+adw_demo_page_set_property (GObject      *object,
+                            guint         prop_id,
+                            const GValue *value,
+                            GParamSpec   *pspec)
+{
+  AdwDemoPage *self = ADW_DEMO_PAGE (object);
+  AdwDemoPagePrivate *priv = adw_demo_page_get_instance_private (self);
+
+  switch (prop_id) {
+  case PROP_SHOW_BACK_BUTTON:
+    priv->show_back_button = g_value_get_boolean (value);
+    break;
+  case PROP_TITLE:
+    set_string (&priv->title, g_value_get_string (value));
+    break;
+  case PROP_CHILD:
+    g_set_object (&priv->child, g_value_get_object (value));
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+  }
+}
+
+static void
+adw_demo_page_class_init (AdwDemoPageClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->dispose = adw_demo_page_dispose;
+  object_class->finalize = adw_demo_page_finalize;
+  object_class->get_property = adw_demo_page_get_property;
+  object_class->set_property = adw_demo_page_set_property;
+
+  props[PROP_SHOW_BACK_BUTTON] =
+    g_param_spec_boolean ("show-back-button",
+                          _("Show Back Button"),
+                          _("Show Back Button"),
+                          FALSE,
+                          G_PARAM_READWRITE);
+
+  props[PROP_TITLE] =
+    g_param_spec_string ("title",
+                         _("Title"),
+                         _("Title"),
+                         NULL,
+                         G_PARAM_READWRITE);
+
+  props[PROP_CHILD] =
+    g_param_spec_object ("child",
+                         _("Child"),
+                         _("Child"),
+                         GTK_TYPE_WIDGET,
+                         G_PARAM_READWRITE);
+
+  g_object_class_install_properties (object_class, LAST_PROP, props);
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Adwaita/Demo/adw-demo-page.ui");
+  gtk_widget_class_bind_template_child_private (widget_class, AdwDemoPage, header_bar);
+  gtk_widget_class_bind_template_child_private (widget_class, AdwDemoPage, child_bin);
+}
+
+static void
+adw_demo_page_init (AdwDemoPage *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/demo/adw-demo-page.h b/demo/adw-demo-page.h
new file mode 100644
index 0000000..59f7867
--- /dev/null
+++ b/demo/adw-demo-page.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define ADW_TYPE_DEMO_PAGE (adw_demo_page_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (AdwDemoPage, adw_demo_page, ADW, DEMO_PAGE, GtkWidget)
+
+struct _AdwDemoPageClass
+{
+  GtkWidgetClass parent_class;
+};
+
+G_END_DECLS
diff --git a/demo/adw-demo-page.ui b/demo/adw-demo-page.ui
new file mode 100644
index 0000000..9169e27
--- /dev/null
+++ b/demo/adw-demo-page.ui
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk" version="4.0"/>
+  <requires lib="libadwaita" version="1.0"/>
+  <template class="AdwDemoPage" parent="GtkWidget">
+    <property name="width-request">360</property>
+    <property name="layout-manager">
+      <object class="GtkBoxLayout">
+        <property name="orientation">vertical</property>
+      </object>
+    </property>
+    <child>
+      <object class="AdwHeaderBar" id="header_bar">
+        <binding name="show-start-title-buttons">
+          <lookup name="sensitive">back_btn</lookup>
+        </binding>
+        <property name="title-widget">
+          <object class="AdwWindowTitle">
+            <binding name="title">
+              <lookup name="title">AdwDemoPage</lookup>
+            </binding>
+          </object>
+        </property>
+        <child type="start">
+          <object class="GtkButton" id="back_btn">
+            <property name="icon-name">go-previous-symbolic</property>
+            <property name="action-name">leaflet.back</property>
+            <binding name="visible">
+              <lookup name="sensitive">back_btn</lookup>
+            </binding>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="AdwBin" id="child_bin">
+        <property name="vexpand">True</property>
+        <binding name="child">
+          <lookup name="child">AdwDemoPage</lookup>
+        </binding>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/demo/adw-demo-window.c b/demo/adw-demo-window.c
new file mode 100644
index 0000000..c75b5eb
--- /dev/null
+++ b/demo/adw-demo-window.c
@@ -0,0 +1,114 @@
+#include "adw-demo-window.h"
+
+#include <glib/gi18n.h>
+
+#include "adw-demo-page-info.h"
+
+#include "pages/controls/adw-demo-page-controls.h"
+#include "pages/lists/adw-demo-page-lists.h"
+#include "pages/stub/adw-demo-page-stub.h"
+
+struct _AdwDemoWindow
+{
+  AdwApplicationWindow parent_instance;
+
+  AdwLeaflet *leaflet;
+  GtkSingleSelection *selection;
+};
+
+G_DEFINE_TYPE (AdwDemoWindow, adw_demo_window, ADW_TYPE_APPLICATION_WINDOW)
+
+static GObject *
+new_page_cb (AdwDemoWindow *self,
+             GType          type)
+{
+  return g_object_ref (g_object_new (type, NULL));
+}
+
+static void
+list_activate_cb (AdwDemoWindow *self)
+{
+  adw_leaflet_navigate (self->leaflet, ADW_NAVIGATION_DIRECTION_FORWARD);
+}
+
+static void
+folded_notify_cb (AdwDemoWindow *self)
+{
+  gtk_widget_action_set_enabled (GTK_WIDGET (self), "leaflet.back",
+                                 adw_leaflet_get_folded (self->leaflet));
+}
+
+static void
+leaflet_back_activate_cb (AdwDemoWindow *self,
+                          const char    *action_name,
+                          GVariant      *parameter)
+{
+  adw_leaflet_navigate (self->leaflet, ADW_NAVIGATION_DIRECTION_BACK);
+}
+
+static void
+adw_demo_window_class_init (AdwDemoWindowClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  // TODO: these should be on the leaflet instead
+  gtk_widget_class_install_action (widget_class, "leaflet.back", NULL,
+                                   (GtkWidgetActionActivateFunc) leaflet_back_activate_cb);
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Adwaita/Demo/adw-demo-window.ui");
+  gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, leaflet);
+  gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, selection);
+  gtk_widget_class_bind_template_callback (widget_class, new_page_cb);
+  gtk_widget_class_bind_template_callback (widget_class, list_activate_cb);
+  gtk_widget_class_bind_template_callback (widget_class, folded_notify_cb);
+}
+
+#define ADD_PAGE(list, title, icon, type) g_list_store_append ((list), adw_demo_page_info_new ((title), 
(icon), (type)));
+#define ADD_STUB(list, title) ADD_PAGE ((list), (title), "dialog-warning-symbolic", ADW_TYPE_DEMO_PAGE_STUB);
+
+static void
+adw_demo_window_init (AdwDemoWindow *self)
+{
+  GListStore *list;
+
+  g_type_ensure (ADW_TYPE_DEMO_PAGE_INFO);
+
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  list = g_list_store_new (ADW_TYPE_DEMO_PAGE_INFO);
+
+  ADD_STUB (list, _("Scrolling Window"));
+  ADD_STUB (list, _("Flat Window"));
+  ADD_STUB (list, _("Dialogs"));
+  ADD_STUB (list, _("Deck"));
+  ADD_STUB (list, _("View Switcher"));
+  ADD_STUB (list, _("Leaflet"));
+  ADD_STUB (list, _("Sidebar"));
+  ADD_STUB (list, _("Flap"));
+  ADD_STUB (list, _("Carousel"));
+  ADD_STUB (list, _("Tabs"));
+  ADD_PAGE (list, _("Lists"), "page-lists-symbolic", ADW_TYPE_DEMO_PAGE_LISTS);
+  ADD_STUB (list, _("Grids"));
+  ADD_PAGE (list, _("Controls"), "page-lists-symbolic", ADW_TYPE_DEMO_PAGE_CONTROLS);
+  ADD_STUB (list, _("Toolbars"));
+  ADD_STUB (list, _("Search"));
+  ADD_STUB (list, _("Feedback"));
+  ADD_STUB (list, _("Status Page"));
+  ADD_STUB (list, _("Avatars"));
+  ADD_STUB (list, _("Menus"));
+  ADD_STUB (list, _("Preferences"));
+  ADD_STUB (list, _("Keyboard Shortcuts"));
+  ADD_STUB (list, _("About"));
+
+  gtk_single_selection_set_model (self->selection, G_LIST_MODEL (list));
+
+  folded_notify_cb (self);
+}
+
+GtkWidget *
+adw_demo_window_new (GtkApplication *application)
+{
+  return g_object_new (ADW_TYPE_DEMO_WINDOW,
+                       "application", application,
+                       NULL);
+}
diff --git a/demo/adw-demo-window.h b/demo/adw-demo-window.h
new file mode 100644
index 0000000..455eb08
--- /dev/null
+++ b/demo/adw-demo-window.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+#define ADW_TYPE_DEMO_WINDOW (adw_demo_window_get_type())
+
+G_DECLARE_FINAL_TYPE (AdwDemoWindow, adw_demo_window, ADW, DEMO_WINDOW, AdwApplicationWindow)
+
+GtkWidget *adw_demo_window_new (GtkApplication *application);
+
+G_END_DECLS
diff --git a/demo/adw-demo-window.ui b/demo/adw-demo-window.ui
new file mode 100644
index 0000000..243feb1
--- /dev/null
+++ b/demo/adw-demo-window.ui
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk" version="4.0"/>
+  <requires lib="libadwaita" version="1.0"/>
+  <template class="AdwDemoWindow" parent="AdwApplicationWindow">
+    <property name="default-width">1000</property>
+    <property name="default-height">720</property>
+    <property name="child">
+      <object class="AdwLeaflet" id="leaflet">
+        <property name="can-swipe-back">True</property>
+        <signal name="notify::folded" handler="folded_notify_cb" swapped="true"/>
+        <child>
+          <object class="GtkBox">
+            <property name="orientation">vertical</property>
+            <property name="width-request">240</property>
+            <child>
+              <object class="AdwHeaderBar">
+                <binding name="show-end-title-buttons">
+                  <lookup name="folded">leaflet</lookup>
+                </binding>
+                <property name="title-widget">
+                  <object class="AdwWindowTitle"/>
+                </property>
+                <child type="start">
+                  <object class="GtkToggleButton" id="search_button">
+                    <property name="icon-name">edit-find-symbolic</property>
+                  </object>
+                </child>
+                <child type="end">
+                  <object class="GtkMenuButton">
+                    <property name="icon-name">open-menu-symbolic</property>
+                    <property name="menu-model">primary_menu</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkSearchBar">
+                <property name="search-mode-enabled" bind-source="search_button" bind-property="active"/>
+                <property name="child">
+                  <object class="GtkSearchEntry"/>
+                </property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="hscrollbar-policy">never</property>
+                <property name="vexpand">True</property>
+                <child>
+                  <object class="GtkListView">
+                    <signal name="activate" handler="list_activate_cb" swapped="true"/>
+                    <property name="model">
+                      <object class="GtkSingleSelection" id="selection"/>
+                    </property>
+                    <property name="factory">
+                      <object class="GtkBuilderListItemFactory">
+                        <property name="bytes"><![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="GtkListItem">
+    <property name="child">
+      <object class="GtkBox">
+        <property name="margin-top">6</property>
+        <property name="margin-bottom">6</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkImage">
+            <binding name="icon-name">
+              <lookup type="AdwDemoPageInfo" name="icon-name">
+                <lookup name="item">GtkListItem</lookup>
+              </lookup>
+            </binding>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="halign">start</property>
+            <binding name="label">
+              <lookup type="AdwDemoPageInfo" name="title">
+                <lookup name="item">GtkListItem</lookup>
+              </lookup>
+            </binding>
+          </object>
+        </child>
+      </object>
+    </property>
+  </template>
+</interface>
+                        ]]></property>
+                      </object>
+                    </property>
+                    <style>
+                      <class name="navigation-sidebar"/>
+                    </style>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwLeafletPage">
+            <property name="navigatable">False</property>
+            <property name="child">
+              <object class="GtkSeparator">
+                <property name="orientation">vertical</property>
+                <style>
+                  <class name="sidebar"/>
+                </style>
+              </object>
+            </property>
+          </object>
+        </child>
+        <child>
+          <object class="AdwBin">
+            <property name="hexpand">True</property>
+            <binding name="child">
+              <closure type="GtkWidget" function="new_page_cb">
+                <lookup type="AdwDemoPageInfo" name="gtype">
+                  <lookup type="GtkSingleSelection" name="selected-item">selection</lookup>
+                </lookup>
+              </closure>
+            </binding>
+          </object>
+        </child>
+      </object>
+    </property>
+    <child>
+      <object class='GtkShortcutController'>
+        <property name='scope'>managed</property>
+        <child>
+          <object class='GtkShortcut'>
+            <property name='trigger'>&lt;Control&gt;Q</property>
+            <property name='action'>action(window.close)</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+  <menu id="primary_menu">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">Preferences</attribute>
+        <attribute name="action">app.preferences</attribute>
+      </item>
+    </section>
+  </menu>
+</interface>
diff --git a/demo/adwaita-demo.c b/demo/adwaita-demo.c
new file mode 100644
index 0000000..0e3b6a5
--- /dev/null
+++ b/demo/adwaita-demo.c
@@ -0,0 +1,45 @@
+#include <gtk/gtk.h>
+#include <adwaita.h>
+
+#include "adw-bin.h"
+#include "adw-demo-window.h"
+
+static void
+startup_cb (GtkApplication *app)
+{
+  g_autoptr (GtkCssProvider) css_provider = NULL;
+
+  adw_init ();
+
+  // FIXME
+  g_type_ensure (ADW_TYPE_BIN);
+
+  css_provider = gtk_css_provider_new ();
+
+  gtk_css_provider_load_from_resource (css_provider, "/org/gnome/Adwaita/Demo/style.css");
+  gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+                                              GTK_STYLE_PROVIDER (css_provider),
+                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+}
+
+static void
+activate_cb (GtkApplication *app)
+{
+  GtkWidget *window = adw_demo_window_new (app);
+
+  gtk_window_present (GTK_WINDOW (window));
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  g_autoptr (GtkApplication) app = NULL;
+
+  app = gtk_application_new ("org.gnome.Adwaita.Demo", G_APPLICATION_FLAGS_NONE);
+
+  g_signal_connect (app, "startup", G_CALLBACK (startup_cb), NULL);
+  g_signal_connect (app, "activate", G_CALLBACK (activate_cb), NULL);
+
+  return g_application_run (G_APPLICATION (app), argc, argv);
+}
diff --git a/demo/adwaita-demo.gresources.xml b/demo/adwaita-demo.gresources.xml
new file mode 100644
index 0000000..a03c6e5
--- /dev/null
+++ b/demo/adwaita-demo.gresources.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/Adwaita/Demo">
+    <file preprocess="xml-stripblanks">icons/scalable/actions/call-start-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/scalable/actions/data-movies-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/scalable/actions/data-music-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/scalable/actions/data-photos-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/scalable/actions/data-podcasts-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/scalable/actions/document-edit-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/scalable/actions/edit-copy-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/scalable/actions/edit-cut-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/scalable/actions/library-music-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/scalable/actions/media-playback-start-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/scalable/actions/open-link-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/scalable/actions/page-lists-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/scalable/actions/star-outline-thick-symbolic.svg</file>
+
+    <file preprocess="xml-stripblanks">pages/controls/adw-demo-page-controls.ui</file>
+    <file preprocess="xml-stripblanks">pages/lists/adw-demo-page-lists.ui</file>
+    <file preprocess="xml-stripblanks">pages/stub/adw-demo-page-stub.ui</file>
+
+    <file preprocess="xml-stripblanks">adw-demo-page.ui</file>
+    <file preprocess="xml-stripblanks">adw-demo-window.ui</file>
+    <file compressed="true">style.css</file>
+  </gresource>
+</gresources>
diff --git a/demo/icons/scalable/actions/call-start-symbolic.svg 
b/demo/icons/scalable/actions/call-start-symbolic.svg
new file mode 100644
index 0000000..59bc9cf
--- /dev/null
+++ b/demo/icons/scalable/actions/call-start-symbolic.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="16" height="16"><path d="M10.994 2c-.554 0-1 .446-1 1v3c0 
.554.446 1 1 1h.711a6.972 6.972 0 01-4.71 4.71V11c0-.554-.447-1-1-1h-3c-.555 0-1 .446-1 1v1.5a2.5 2.5 0 002.5 
2.5h.5c5.504 0 10-4.495 10-10v-.5a2.5 2.5 0 00-2.5-2.5z" 
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;shape-padding:0;isolation:auto;mix-blend-mode:normal;marker:none"
 color="#000" font-weight="400" font-family="sans-serif" overflow="visible" fill="#2e3436"/></svg>
\ No newline at end of file
diff --git a/demo/icons/scalable/actions/data-movies-symbolic.svg 
b/demo/icons/scalable/actions/data-movies-symbolic.svg
new file mode 100644
index 0000000..3383a92
--- /dev/null
+++ b/demo/icons/scalable/actions/data-movies-symbolic.svg
@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="16" height="16">
+    <g fill="#2e3436">
+        <path d="M6.5 1A3.515 3.515 0 0 0 3 4.5C3 6.421 4.579 8 6.5 8S10 6.421 10 4.5 8.421 1 6.5 1zm0 
2C7.34 3 8 3.66 8 4.5S7.34 6 6.5 6 5 5.34 5 4.5 5.66 3 6.5 3z" 
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1"
 color="#000" font-weight="400" font-family="sans-serif" overflow="visible"/>
+        <path d="M12.5 1A3.515 3.515 0 0 0 9 4.5C9 6.421 10.579 8 12.5 8S16 6.421 16 4.5 14.421 1 12.5 1zm0 
2c.84 0 1.5.66 1.5 1.5S13.34 6 12.5 6 11 5.34 11 4.5 11.66 3 12.5 3z" 
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1"
 color="#000" font-weight="400" font-family="sans-serif" overflow="visible"/>
+        <path d="M4 6v7c0 .833.564 1.525 1.053 1.77.488.244.947.23.947.23h7s.459.014.947-.23C14.436 14.525 
15 13.833 15 13V6h-1zm2 2h7v5H6z" 
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1"
 color="#000" font-weight="400" font-family="sans-serif" overflow="visible" fill-rule="evenodd"/>
+        <path d="M.988 7A1 1 0 0 0 0 8v4a1 1 0 0 0 1.555.832l3-2a1 1 0 0 0 0-1.664l-3-2A1 1 0 0 0 .988 7zM2 
9.87l.197.13-.197.13z" 
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1;marker:none"
 color="#000" font-weight="400" font-family="sans-serif" overflow="visible"/>
+        <path d="M1 12H0v1h1zM1 7H0v1h1zM1 8l3 2-3 2zM14 8h2v2l-1 1h-1z" style="marker:none" color="#000" 
overflow="visible"/>
+        <path d="M14 7v6c0 1-1 1-1 1H6s-1 0-1-1V7z" fill-rule="evenodd"/>
+    </g>
+</svg>
diff --git a/demo/icons/scalable/actions/data-music-symbolic.svg 
b/demo/icons/scalable/actions/data-music-symbolic.svg
new file mode 100644
index 0000000..0fd18d8
--- /dev/null
+++ b/demo/icons/scalable/actions/data-music-symbolic.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="16" height="16">
+    <path d="M5 1v7.344A3.574 3.574 0 003.5 8 3.515 3.515 0 000 11.5C0 13.421 1.579 15 3.5 15A3.517 3.517 0 
007 11.531v-7.53h6v4.343A3.574 3.574 0 0011.5 8 3.515 3.515 0 008 11.5c0 1.921 1.579 3.5 3.5 3.5 1.9 0 
3.465-1.546 3.5-3.437V1z" 
style="line-height:normal;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;marker:none"
 color="#000" font-weight="400" font-family="Sans" overflow="visible" fill="#2e3436"/>
+</svg>
diff --git a/demo/icons/scalable/actions/data-photos-symbolic.svg 
b/demo/icons/scalable/actions/data-photos-symbolic.svg
new file mode 100644
index 0000000..7332133
--- /dev/null
+++ b/demo/icons/scalable/actions/data-photos-symbolic.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="16" height="16">
+    <path d="M6 2c-.55 0-1 .45-1 1v1H2c-.552 0-1 .45-1 1v8c0 .55.448 1 1 1h12c.552 0 1-.45 
1-1V5c0-.55-.448-1-1-1h-3V3c0-.55-.45-1-1-1zm2 3a4 4 0 1 1 0 8 4 4 0 0 1 0-8zm0 2a2 2 0 1 0 0 4 2 2 0 0 0 
0-4z" style="marker:none" color="#bebebe" overflow="visible" fill="#2e3436"/>
+</svg>
diff --git a/demo/icons/scalable/actions/data-podcasts-symbolic.svg 
b/demo/icons/scalable/actions/data-podcasts-symbolic.svg
new file mode 100644
index 0000000..39e834e
--- /dev/null
+++ b/demo/icons/scalable/actions/data-podcasts-symbolic.svg
@@ -0,0 +1,8 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="16.015" height="16">
+    <g font-weight="400" font-family="sans-serif" fill="#2e3436">
+        <path d="M7.446 11.007h1.143c1.9 0 3.428 1.53 3.428 3.429v.803c0 .762-.76.761-.76.761H4.778s-.762 
0-.762-.761v-.803c0-1.9 1.53-3.429 3.429-3.429z" 
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1;marker:none"
 color="#bebebe" overflow="visible"/>
+        <path d="M8.017 3.004a4.99 4.99 0 00-3.324 1.262 5.007 5.007 0 00-.771 6.601.75.75 0 101.228-.86 
3.492 3.492 0 01.541-4.622 3.49 3.49 0 014.653 0 3.492 3.492 0 01.54 4.623.75.75 0 101.23.86 5.007 5.007 0 
00-.772-6.602 4.99 4.99 0 00-3.325-1.262z" 
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1"
 color="#000" overflow="visible" opacity=".35"/>
+        <path d="M8.017 6a2 2 0 110 4 2 2 0 010-4z" 
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1;marker:none"
 color="#bebebe" overflow="visible"/>
+        <path d="M8.017.004A7.98 7.98 0 002.7 2.024a8.008 8.008 0 00-1.234 10.564.75.75 0 101.228-.86 6.491 
6.491 0 011.004-8.583 6.489 6.489 0 018.64 0 6.491 6.491 0 011.005 8.584.75.75 0 101.228.859 8.008 8.008 0 
00-1.234-10.565A7.98 7.98 0 008.017.003z" 
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1"
 color="#000" overflow="visible" opacity=".35"/>
+    </g>
+</svg>
diff --git a/demo/icons/scalable/actions/document-edit-symbolic.svg 
b/demo/icons/scalable/actions/document-edit-symbolic.svg
new file mode 100644
index 0000000..5940959
--- /dev/null
+++ b/demo/icons/scalable/actions/document-edit-symbolic.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="16" height="16"><g fill="#2e3436" fill-rule="evenodd"><path 
d="M2.01 11.014l6.518-6.572 3 3-6.518 6.572h-3z"/><path d="M11.637 1.676c-.2 0-.4.077-.554.23l-1.77 1.768 
3.053 3.053 1.77-1.77a.783.783 0 000-1.109l-1.944-1.941a.782.782 0 00-.555-.23z" 
style="isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1;marker:none" color="#000" 
overflow="visible"/></g></svg>
\ No newline at end of file
diff --git a/demo/icons/scalable/actions/edit-copy-symbolic.svg 
b/demo/icons/scalable/actions/edit-copy-symbolic.svg
new file mode 100644
index 0000000..874ae4e
--- /dev/null
+++ b/demo/icons/scalable/actions/edit-copy-symbolic.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="16" height="16"><g fill="#2e3436"><path d="M6.994 
15h5l2-2V7h-7z"/><path d="M1.994 10h4V6h3V2H2z"/></g></svg>
\ No newline at end of file
diff --git a/demo/icons/scalable/actions/edit-cut-symbolic.svg 
b/demo/icons/scalable/actions/edit-cut-symbolic.svg
new file mode 100644
index 0000000..4393d66
--- /dev/null
+++ b/demo/icons/scalable/actions/edit-cut-symbolic.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="16" height="16"><path d="M4.5 2.007a2.5 2.5 0 000 5c.446 0 
.856-.14 1.218-.344l1.97 1.844-1.97 1.843a2.473 2.473 0 00-1.218-.343 2.5 2.5 0 102.5 
2.5c0-.23-.036-.446-.094-.657L9.03 9.788l4.469 4.219H15v-1L6.906 5.163A2.46 2.46 0 007 4.507a2.5 2.5 0 
00-2.5-2.5zm0 1.5a1 1 0 110 2 1 1 0 010-2zm9-.5L9.562 6.725l1.313 1.282 4.125-4v-1zm-9 8.5a1 1 0 110 2 1 1 0 
010-2z" style="isolation:auto;mix-blend-mode:normal" color="#000" overflow="visible" fill="#474747"/></svg>
\ No newline at end of file
diff --git a/demo/icons/scalable/actions/library-music-symbolic.svg 
b/demo/icons/scalable/actions/library-music-symbolic.svg
new file mode 100644
index 0000000..7096670
--- /dev/null
+++ b/demo/icons/scalable/actions/library-music-symbolic.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="16" height="16">
+    <g color="#bebebe" font-weight="400" font-family="sans-serif" fill="#2e3436">
+        <path d="M5 0C3.91 0 3 .91 3 2v9c0 1.09.91 2 2 2h9c1.09 0 2-.91 2-2V2c0-1.09-.91-2-2-2zm8 2v2h-2v5a2 
2 0 11-1-1.73V2z" 
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1;marker:none"
 overflow="visible"/>
+        <path d="M2 3C.91 3 0 3.91 0 5v9c0 1.09.91 2 2 2h9c1.09 0 2-.91 2-2H2V5z" 
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1;marker:none"
 overflow="visible"/>
+    </g>
+</svg>
diff --git a/demo/icons/scalable/actions/media-playback-start-symbolic.svg 
b/demo/icons/scalable/actions/media-playback-start-symbolic.svg
new file mode 100644
index 0000000..f26678d
--- /dev/null
+++ b/demo/icons/scalable/actions/media-playback-start-symbolic.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="16" height="16"><g color="#000" fill="#474747"><path 
d="M5.022 3a1 1 0 00-1.02 1v8a1 1 0 001.496.87l6.999-4a1 1 0 000-1.74l-6.999-4A1 1 0 005.022 3zm.98 
2.725L9.982 8l-3.98 2.275z" 
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;shape-padding:0;isolation:auto;mix-blend-mode:normal;marker:none"
 font-weight="400" font-family="sans-serif" overflow="visible"/><path d="M5.002 12h-1v1h1zm0-9h-1v1h1zm0 1L12 
8l-6.998 4z" style="marker:none" overflow="visible"/></g></svg>
\ No newline at end of file
diff --git a/demo/icons/scalable/actions/open-link-symbolic.svg 
b/demo/icons/scalable/actions/open-link-symbolic.svg
new file mode 100644
index 0000000..fcb39cb
--- /dev/null
+++ b/demo/icons/scalable/actions/open-link-symbolic.svg
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   width="16px"
+   height="16px"
+   viewBox="0 0 16 16"
+   version="1.1"
+   id="svg13">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs17" />
+  <g
+     id="g11496-6"
+     style="fill:#2e3436;fill-opacity:1"
+     transform="translate(-8981.1032,-2151.2551)">
+    <path
+       id="path11492-4"
+       d="m 8983.1032,2154.248 v 10.9994 h 11.0003 v -3.9994 h -2 v 1.9994 h -7.0003 v -6.9994 h 2.0003 v -2 
z"
+       
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;v
 
ector-effect:none;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
 />
+  </g>
+  <g
+     id="g3142"
+     style="display:inline"
+     transform="translate(-1005.8751,62.24235)">
+    <path
+       id="path12111"
+       
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;v
 
ector-effect:none;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new;stop-color:#000000;stop-opacity:1"
+       d="m 8,1.9921875 v 1 c 0,0.5522847 0.4477153,1 1,1 h 1.574219 L 7.7949219,6.7519531 c 
-0.3915045,0.3894276 -0.3932532,1.0224778 -0.00391,1.4140625 0.3894276,0.3915045 1.0224778,0.3932532 
1.4140625,0.00391 L 12,5.3945312 v 1.5976563 c 0,0.5522847 0.447715,1 1,1 h 1 v -6 z"
+       transform="translate(1005.8751,-62.24235)" />
+  </g>
+</svg>
diff --git a/demo/icons/scalable/actions/page-lists-symbolic.svg 
b/demo/icons/scalable/actions/page-lists-symbolic.svg
new file mode 100644
index 0000000..ad353a4
--- /dev/null
+++ b/demo/icons/scalable/actions/page-lists-symbolic.svg
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   width="16px"
+   height="16px"
+   viewBox="0 0 16 16"
+   version="1.1"
+   id="svg13"
+   sodipodi:docname="list-view-symbolic.svg"
+   inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
+  <sodipodi:namedview
+     pagecolor="#7b7b7b"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1011"
+     id="namedview7"
+     showgrid="false"
+     inkscape:object-paths="true"
+     inkscape:snap-intersection-paths="true"
+     inkscape:snap-smooth-nodes="true"
+     inkscape:snap-midpoints="true"
+     inkscape:zoom="20.377255"
+     inkscape:cx="6.5128986"
+     inkscape:cy="14.575443"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg13"
+     inkscape:document-rotation="0" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs17" />
+  <g
+     id="g862">
+    <path
+       id="path6793"
+       
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;marker:none"
+       d="m 2.999921,1.000281 c -1.0907,0 -2,0.9093 -2,2 v 10 c 0,1.0907 0.9093,2 2,2 h 10 c 1.0907,0 
2,-0.9093 2,-2 v -10 c 0,-1.0907 -0.9093,-2 -2,-2 z m 0,2 h 10 v 10 h -10 z"
+       sodipodi:nodetypes="sssssssssccccc" />
+    <rect
+       
style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-dasharray:8,
 8"
+       id="rect6856"
+       width="12"
+       height="2"
+       x="1.99992"
+       y="5.0002441" />
+    <rect
+       
style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-dasharray:8,
 8"
+       id="rect6858"
+       width="12"
+       height="2"
+       x="1.99992"
+       y="9.0002441" />
+  </g>
+</svg>
diff --git a/demo/icons/scalable/actions/star-outline-thick-symbolic.svg 
b/demo/icons/scalable/actions/star-outline-thick-symbolic.svg
new file mode 100644
index 0000000..a3198a7
--- /dev/null
+++ b/demo/icons/scalable/actions/star-outline-thick-symbolic.svg
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb";
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   width="16"
+   viewBox="0 0 16 16"
+   version="1.1"
+   id="svg7384"
+   height="16">
+  <metadata
+     id="metadata90">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title>Gnome Symbolic Icon Theme</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <title
+     id="title9167">Gnome Symbolic Icon Theme</title>
+  <defs
+     id="defs7386">
+    <linearGradient
+       osb:paint="solid"
+       id="linearGradient7212">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop7214" />
+    </linearGradient>
+  </defs>
+  <g
+     transform="translate(-399.98255,-120.00458)"
+     style="display:inline"
+     id="layer1" />
+  <g
+     transform="translate(-640.98275,246.99542)"
+     style="display:inline"
+     id="layer9">
+    <path
+       id="path2008"
+       d="m 648.9773,-246.83708 -2.45893,4.93192 -5.45829,0.83762 3.93012,3.86385 -0.88998,5.44801 
4.88966,-2.54484 4.90758,2.53215 -0.33054,-1.96945 -0.57882,-3.468 3.92302,-3.88443 -5.45115,-0.81557 z m 
0.009,4.46568 1.15316,2.29127 2.52594,0.3775 -1.82219,1.80466 0.42154,2.52091 -2.28071,-1.17576 
-2.26532,1.17863 0.41256,-2.53114 -1.82244,-1.79075 2.53721,-0.38903 z"
+       
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.
 
00000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
 />
+  </g>
+  <g
+     transform="translate(-640.98275,246.99542)"
+     style="display:inline"
+     id="g7628" />
+  <g
+     transform="translate(-399.98255,-120.00458)"
+     style="display:inline"
+     id="g6387" />
+  <g
+     transform="translate(-399.98255,-120.00458)"
+     style="display:inline"
+     id="layer10" />
+  <g
+     transform="translate(-399.98255,-120.00458)"
+     id="layer12" />
+  <g
+     transform="translate(-399.98255,-120.00458)"
+     style="display:inline"
+     id="layer11" />
+</svg>
diff --git a/demo/meson.build b/demo/meson.build
new file mode 100644
index 0000000..679cdff
--- /dev/null
+++ b/demo/meson.build
@@ -0,0 +1,32 @@
+if get_option('examples')
+
+adwaita_demo_resources = gnome.compile_resources(
+  'adwaita-demo-resources',
+  'adwaita-demo.gresources.xml',
+
+  c_name: 'adw',
+)
+
+adwaita_demo_sources = [
+  adwaita_demo_resources,
+
+  'pages/controls/adw-demo-page-controls.c',
+  'pages/lists/adw-demo-page-lists.c',
+  'pages/stub/adw-demo-page-stub.c',
+
+  'adwaita-demo.c',
+  'adw-demo-page.c',
+  'adw-demo-page-info.c',
+  'adw-demo-window.c',
+
+  libadwaita_generated_headers,
+]
+
+adwaita_demo = executable('adwaita-@0@-demo'.format(apiversion),
+  adwaita_demo_sources,
+  dependencies: libadwaita_dep,
+  gui_app: true,
+  install: true,
+)
+
+endif
diff --git a/demo/org.gnome.Adwaita.Demo.json b/demo/org.gnome.Adwaita.Demo.json
new file mode 100644
index 0000000..06f2d2c
--- /dev/null
+++ b/demo/org.gnome.Adwaita.Demo.json
@@ -0,0 +1,49 @@
+{
+  "app-id": "org.gnome.Adwaita.Demo",
+  "runtime": "org.gnome.Platform",
+  "runtime-version": "master",
+  "sdk": "org.gnome.Sdk",
+  "command": "adwaita-1-demo",
+  "finish-args": [
+    "--share=ipc",
+    "--socket=wayland",
+    "--socket=x11",
+    "--device=dri",
+    "--talk-name=org.a11y.Bus"
+  ],
+  "modules": [
+    {
+      "name" : "libsass",
+      "buildsystem" : "meson",
+      "sources" : [
+        {
+          "type" : "git",
+          "url" : "https://github.com/lazka/libsass.git";,
+          "branch" : "meson"
+        }
+      ]
+    },
+    {
+      "name" : "sassc",
+      "buildsystem" : "meson",
+      "sources" : [
+        {
+          "type" : "git",
+          "url" : "https://github.com/lazka/sassc.git";,
+          "branch" : "meson"
+        }
+      ]
+    },
+    {
+      "name": "libadwaita",
+      "buildsystem": "meson",
+      "builddir": true,
+      "sources": [
+        {
+          "type": "git",
+          "url": "https://gitlab.gnome.org/exalm/libadwaita.git";
+        }
+      ]
+    }
+  ]
+}
diff --git a/demo/pages/controls/adw-demo-page-controls.c b/demo/pages/controls/adw-demo-page-controls.c
new file mode 100644
index 0000000..e77b5f3
--- /dev/null
+++ b/demo/pages/controls/adw-demo-page-controls.c
@@ -0,0 +1,30 @@
+#include "adw-demo-page-controls.h"
+
+struct _AdwDemoPageControls
+{
+  AdwDemoPage parent_instance;
+};
+
+G_DEFINE_TYPE (AdwDemoPageControls, adw_demo_page_controls, ADW_TYPE_DEMO_PAGE)
+
+static double
+progress_to_level (AdwDemoPageControls *self,
+                   double               progress)
+{
+  return progress * 5;
+}
+
+static void
+adw_demo_page_controls_class_init (AdwDemoPageControlsClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/Adwaita/Demo/pages/controls/adw-demo-page-controls.ui");
+  gtk_widget_class_bind_template_callback (widget_class, progress_to_level);
+}
+
+static void
+adw_demo_page_controls_init (AdwDemoPageControls *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/demo/pages/controls/adw-demo-page-controls.h b/demo/pages/controls/adw-demo-page-controls.h
new file mode 100644
index 0000000..a6e1750
--- /dev/null
+++ b/demo/pages/controls/adw-demo-page-controls.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "adw-demo-page.h"
+
+G_BEGIN_DECLS
+
+#define ADW_TYPE_DEMO_PAGE_CONTROLS (adw_demo_page_controls_get_type())
+
+G_DECLARE_FINAL_TYPE (AdwDemoPageControls, adw_demo_page_controls, ADW, DEMO_PAGE_CONTROLS, AdwDemoPage)
+
+G_END_DECLS
diff --git a/demo/pages/controls/adw-demo-page-controls.ui b/demo/pages/controls/adw-demo-page-controls.ui
new file mode 100644
index 0000000..24c732f
--- /dev/null
+++ b/demo/pages/controls/adw-demo-page-controls.ui
@@ -0,0 +1,657 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk" version="4.0"/>
+  <requires lib="libadwaita" version="1.0"/>
+  <template class="AdwDemoPageControls" parent="AdwDemoPage">
+    <property name="title" translatable="yes">Controls</property>
+    <property name="child">
+      <object class="AdwPreferencesPage">
+        <child>
+          <object class="AdwPreferencesGroup">
+            <property name="title" translatable="yes">Buttons</property>
+            <child>
+              <object class="GtkBox">
+                <property name="orientation">vertical</property>
+                <property name="spacing">12</property>
+                <child>
+                  <object class="GtkBox">
+                    <property name="spacing">6</property>
+                    <property name="homogeneous">True</property>
+                    <child>
+                      <object class="GtkButton">
+                        <property name="label" translatable="yes">Regular</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkButton">
+                        <property name="label" translatable="yes">Suggested</property>
+                        <style>
+                          <class name="suggested-action"/>
+                        </style>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkButton">
+                        <property name="label" translatable="yes">Destructive</property>
+                        <style>
+                          <class name="destructive-action"/>
+                        </style>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkFlowBox">
+                    <property name="min-children-per-line">1</property>
+                    <property name="max-children-per-line">2</property>
+                    <property name="column-spacing">6</property>
+                    <property name="row-spacing">12</property>
+                    <property name="selection-mode">none</property>
+                    <style>
+                      <class name="inline"/>
+                    </style>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="spacing">6</property>
+                        <property name="homogeneous">True</property>
+                        <child>
+                          <object class="GtkToggleButton">
+                            <property name="label" translatable="yes">Toggle</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkDropDown">
+                            <property name="model">
+                              <object class="GtkStringList">
+                                <items>
+                                  <item translatable="yes">Dropdown</item>
+                                  <item translatable="yes">Dropdown</item>
+                                  <item translatable="yes">Dropdown</item>
+                                </items>
+                              </object>
+                            </property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="homogeneous">True</property>
+                        <style>
+                          <class name="linked"/>
+                        </style>
+                        <child>
+                          <object class="GtkButton">
+                            <property name="label" translatable="yes">Three</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkButton">
+                            <property name="label" translatable="yes">Linked</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkButton">
+                            <property name="label" translatable="yes">Buttons</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkColorButton"/>
+                        </child>
+                        <child>
+                          <object class="GtkFontButton">
+                            <property name="hexpand">True</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkBox">
+                            <style>
+                              <class name="linked"/>
+                            </style>
+                            <child>
+                              <object class="GtkButton">
+                                <property name="icon-name">document-edit-symbolic</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkButton">
+                                <property name="icon-name">edit-copy-symbolic</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkButton">
+                                <property name="icon-name">edit-cut-symbolic</property>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkButton">
+                            <property name="icon-name">media-playback-start-symbolic</property>
+                            <style>
+                              <class name="circular"/>
+                            </style>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkVolumeButton"/>
+                        </child>
+                        <child>
+                          <object class="GtkLinkButton">
+                            <property name="label" translatable="yes">Link Button</property>
+                            <property name="uri" translatable="yes">https://os.gnome.org/</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwPreferencesGroup">
+            <property name="title" translatable="yes">Labels</property>
+            <child>
+              <object class="GtkFlowBox">
+                <property name="min-children-per-line">1</property>
+                <property name="max-children-per-line">2</property>
+                <property name="column-spacing">12</property>
+                <property name="row-spacing">18</property>
+                <property name="selection-mode">none</property>
+                <style>
+                  <class name="inline"/>
+                </style>
+                <child>
+                  <object class="GtkBox">
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">12</property>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label" translatable="yes">Large Title</property>
+                        <property name="xalign">0</property>
+                        <property name="ellipsize">end</property>
+                        <style>
+                          <class name="large-title"/>
+                        </style>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label" translatable="yes">Title 1</property>
+                        <property name="xalign">0</property>
+                        <property name="ellipsize">end</property>
+                        <style>
+                          <class name="title-1"/>
+                        </style>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label" translatable="yes">Title 2</property>
+                        <property name="xalign">0</property>
+                        <property name="ellipsize">end</property>
+                        <style>
+                          <class name="title-2"/>
+                        </style>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label" translatable="yes">Title 3</property>
+                        <property name="xalign">0</property>
+                        <property name="ellipsize">end</property>
+                        <style>
+                          <class name="title-3"/>
+                        </style>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label" translatable="yes">Title 4</property>
+                        <property name="xalign">0</property>
+                        <property name="ellipsize">end</property>
+                        <style>
+                          <class name="title-4"/>
+                        </style>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox">
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">12</property>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label" translatable="yes">Heading</property>
+                        <property name="xalign">0</property>
+                        <property name="ellipsize">end</property>
+                        <style>
+                          <class name="heading"/>
+                        </style>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label" translatable="yes">This is a paragraph of a body copy. You 
would use this style for most text in interfaces. It can also include &lt;b&gt;styling&lt;/b&gt; or &lt;a 
href="https://os.gnome.org/";>links&lt;/a&gt;.</property>
+                        <property name="use-markup">True</property>
+                        <property name="xalign">0</property>
+                        <property name="wrap">True</property>
+                        <property name="wrap-mode">word-char</property>
+                        <property name="max-width-chars">25</property>
+                        <style>
+                          <class name="body"/>
+                        </style>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label" translatable="yes">This is a paragraph of small body 
copy.</property>
+                        <property name="xalign">0</property>
+                        <property name="wrap">True</property>
+                        <property name="wrap-mode">word-char</property>
+                        <property name="max-width-chars">25</property>
+                        <style>
+                          <class name="body"/>
+                        </style>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label" translatable="yes">This is a dimmed paragraph, mostly used 
for secondary labels or descriptions.</property>
+                        <property name="xalign">0</property>
+                        <property name="wrap">True</property>
+                        <property name="wrap-mode">word-char</property>
+                        <property name="max-width-chars">25</property>
+                        <style>
+                          <class name="body"/>
+                          <class name="dim-label"/>
+                        </style>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label" translatable="yes">Caption Heading</property>
+                        <property name="xalign">0</property>
+                        <property name="ellipsize">end</property>
+                        <style>
+                          <class name="caption-heading"/>
+                        </style>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label" translatable="yes">Caption body text, to be used for body 
copy on image captions and the like.</property>
+                        <property name="xalign">0</property>
+                        <property name="wrap">True</property>
+                        <property name="wrap-mode">word-char</property>
+                        <property name="max-width-chars">25</property>
+                        <style>
+                          <class name="caption"/>
+                        </style>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwPreferencesGroup">
+            <property name="title" translatable="yes">Entries</property>
+            <child>
+              <object class="GtkBox">
+                <property name="orientation">vertical</property>
+                <property name="spacing">12</property>
+                <child>
+                  <object class="GtkFlowBox">
+                    <property name="min-children-per-line">1</property>
+                    <property name="max-children-per-line">2</property>
+                    <property name="column-spacing">6</property>
+                    <property name="row-spacing">12</property>
+                    <property name="selection-mode">none</property>
+                    <style>
+                      <class name="inline"/>
+                    </style>
+                    <child>
+                      <object class="GtkEntry">
+                        <property name="placeholder-text" translatable="yes">Entry with button</property>
+                        <property name="secondary-icon-name">edit-copy-symbolic</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkEntry">
+                        <property name="placeholder-text" translatable="yes">Entry with emoji 
picker</property>
+                        <property name="show-emoji-icon">True</property>
+                        <property name="enable-emoji-completion">True</property>
+                        <binding name="progress-fraction">
+                          <lookup name="value">adj</lookup>
+                        </binding>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkPasswordEntry">
+                        <property name="placeholder-text" translatable="yes">Password entry</property>
+                        <property name="text" translatable="yes">Password entry</property>
+                        <property name="show-peek-icon">True</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkSpinButton">
+                            <property name="hexpand">True</property>
+                            <property name="adjustment">
+                              <object class="GtkAdjustment">
+                                <property name="lower">0</property>
+                                <property name="upper">1000</property>
+                                <property name="step-increment">1</property>
+                                <property name="page-increment">50</property>
+                                <property name="value">342</property>
+                              </object>
+                            </property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox">
+                    <property name="homogeneous">True</property>
+                    <style>
+                      <class name="linked"/>
+                    </style>
+                    <child>
+                      <object class="GtkEntry">
+                        <property name="placeholder-text" translatable="yes">Name</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkEntry">
+                        <property name="placeholder-text" translatable="yes">Address</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkEntry">
+                        <property name="placeholder-text" translatable="yes">Country</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkFrame">
+                    <property name="child">
+                      <object class="GtkScrolledWindow">
+                        <property name="hscrollbar-policy">never</property>
+                        <property name="propagate-natural-height">True</property>
+                        <property name="min-content-height">100</property>
+                        <property name="child">
+                          <object class="GtkTextView">
+                            <property name="top-margin">6</property>
+                            <property name="bottom-margin">6</property>
+                            <property name="left-margin">6</property>
+                            <property name="right-margin">6</property>
+                          </object>
+                        </property>
+                      </object>
+                    </property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwPreferencesGroup">
+            <property name="title" translatable="yes">Choice</property>
+            <child>
+              <object class="GtkBox">
+                <property name="orientation">vertical</property>
+                <property name="spacing">12</property>
+                <child>
+                  <object class="GtkFlowBox">
+                    <property name="min-children-per-line">1</property>
+                    <property name="max-children-per-line">2</property>
+                    <property name="column-spacing">6</property>
+                    <property name="row-spacing">12</property>
+                    <property name="selection-mode">none</property>
+                    <style>
+                      <class name="inline"/>
+                    </style>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="orientation">vertical</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkCheckButton">
+                            <property name="label" translatable="yes">Check Button</property>
+                            <property name="active">True</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton">
+                            <property name="label" translatable="yes">Unchecked Check Button</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton">
+                            <property name="label" translatable="yes">Blocked Check Button</property>
+                            <property name="inconsistent">True</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="orientation">vertical</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkCheckButton" id="radio">
+                            <property name="label" translatable="yes">Radio Button</property>
+                            <property name="active">True</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton">
+                            <property name="label" translatable="yes">Inactive Radio Button</property>
+                            <property name="group">radio</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton">
+                            <property name="label" translatable="yes">Blocked Radio Button</property>
+                            <property name="inconsistent">True</property>
+                            <property name="group">radio</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Switches</property>
+                    <property name="margin-top">6</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox">
+                    <property name="spacing">12</property>
+                    <child>
+                      <object class="GtkSwitch">
+                        <property name="active">True</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkSwitch"/>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwPreferencesGroup">
+            <property name="title" translatable="yes">Progress</property>
+            <child>
+              <object class="GtkBox">
+                <property name="orientation">vertical</property>
+                <property name="spacing">6</property>
+                <child>
+                  <object class="GtkFlowBox">
+                    <property name="min-children-per-line">1</property>
+                    <property name="max-children-per-line">2</property>
+                    <property name="column-spacing">6</property>
+                    <property name="selection-mode">none</property>
+                    <property name="homogeneous">True</property>
+                    <style>
+                      <class name="inline"/>
+                    </style>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="orientation">vertical</property>
+                        <property name="spacing">6</property>
+                        <property name="width-request">240</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="label" translatable="yes">Slider</property>
+                            <property name="xalign">0</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkScale">
+                            <property name="adjustment">adj</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="orientation">vertical</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="label" translatable="yes">Discrete Slider</property>
+                            <property name="xalign">0</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkScale">
+                            <property name="adjustment">adj</property>
+                            <marks>
+                              <mark value="0"/>
+                              <mark value="0.25"/>
+                              <mark value="0.5"/>
+                              <mark value="0.75"/>
+                              <mark value="1"/>
+                            </marks>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="orientation">vertical</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="label" translatable="yes">Level Bar</property>
+                            <property name="xalign">0</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkLevelBar">
+                            <property name="max-value">5</property>
+                            <binding name="value">
+                              <closure function="progress_to_level" type="gdouble">
+                                <lookup name="value">adj</lookup>
+                              </closure>
+                            </binding>
+                            <offsets>
+                              <offset name="low" value="1.25"/>
+                              <offset name="high" value="3.75"/>
+                              <offset name="full" value="5"/>
+                            </offsets>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="orientation">vertical</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="label" translatable="yes">Discrete Level Bar</property>
+                            <property name="xalign">0</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkLevelBar">
+                            <property name="mode">discrete</property>
+                            <property name="max-value">5</property>
+                            <binding name="value">
+                              <closure function="progress_to_level" type="gdouble">
+                                <lookup name="value">adj</lookup>
+                              </closure>
+                            </binding>
+                            <offsets>
+                              <offset name="low" value="1.25"/>
+                              <offset name="high" value="3.75"/>
+                              <offset name="full" value="5"/>
+                            </offsets>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox">
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">6</property>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label" translatable="yes">Progress Bar</property>
+                        <property name="xalign">0</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkProgressBar">
+                        <binding name="fraction">
+                          <lookup name="value">adj</lookup>
+                        </binding>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </property>
+  </template>
+  <object class="GtkAdjustment" id="adj">
+    <property name="lower">0</property>
+    <property name="upper">1</property>
+    <property name="value">0.5</property>
+  </object>
+</interface>
diff --git a/demo/pages/lists/adw-demo-page-lists.c b/demo/pages/lists/adw-demo-page-lists.c
new file mode 100644
index 0000000..1c6a65e
--- /dev/null
+++ b/demo/pages/lists/adw-demo-page-lists.c
@@ -0,0 +1,53 @@
+#include "adw-demo-page-lists.h"
+
+#include <glib/gi18n.h>
+
+struct _AdwDemoPageLists
+{
+  AdwDemoPage parent_instance;
+
+  GtkWindow *sub_view;
+};
+
+G_DEFINE_TYPE (AdwDemoPageLists, adw_demo_page_lists, ADW_TYPE_DEMO_PAGE)
+
+static void
+sub_view_activate_cb (AdwDemoPageLists *self,
+                      const char       *action_name,
+                      GVariant         *parameter)
+{
+  GtkWindow *window = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self)));
+
+  gtk_window_set_transient_for (self->sub_view, window);
+  gtk_window_present (self->sub_view);
+}
+
+static void
+external_link_activate_cb (AdwDemoPageLists *self,
+                           const char       *action_name,
+                           GVariant         *parameter)
+{
+  GtkWindow *window = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self)));
+
+  gtk_show_uri (window, _("https://os.gnome.org";), GDK_CURRENT_TIME);
+}
+
+static void
+adw_demo_page_lists_class_init (AdwDemoPageListsClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gtk_widget_class_install_action (widget_class, "page.sub-view", NULL,
+                                   (GtkWidgetActionActivateFunc) sub_view_activate_cb);
+  gtk_widget_class_install_action (widget_class, "page.external-link", NULL,
+                                   (GtkWidgetActionActivateFunc) external_link_activate_cb);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/Adwaita/Demo/pages/lists/adw-demo-page-lists.ui");
+  gtk_widget_class_bind_template_child (widget_class, AdwDemoPageLists, sub_view);
+}
+
+static void
+adw_demo_page_lists_init (AdwDemoPageLists *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/demo/pages/lists/adw-demo-page-lists.h b/demo/pages/lists/adw-demo-page-lists.h
new file mode 100644
index 0000000..521316a
--- /dev/null
+++ b/demo/pages/lists/adw-demo-page-lists.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "adw-demo-page.h"
+
+G_BEGIN_DECLS
+
+#define ADW_TYPE_DEMO_PAGE_LISTS (adw_demo_page_lists_get_type())
+
+G_DECLARE_FINAL_TYPE (AdwDemoPageLists, adw_demo_page_lists, ADW, DEMO_PAGE_LISTS, AdwDemoPage)
+
+G_END_DECLS
diff --git a/demo/pages/lists/adw-demo-page-lists.ui b/demo/pages/lists/adw-demo-page-lists.ui
new file mode 100644
index 0000000..bc68e0d
--- /dev/null
+++ b/demo/pages/lists/adw-demo-page-lists.ui
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk" version="4.0"/>
+  <requires lib="libadwaita" version="1.0"/>
+  <template class="AdwDemoPageLists" parent="AdwDemoPage">
+    <property name="title" translatable="yes">Lists</property>
+    <property name="child">
+      <object class="AdwPreferencesPage">
+        <child>
+          <object class="AdwPreferencesGroup">
+            <property name="title" translatable="yes">Basic List Rows</property>
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">Row with Buttons</property>
+                <child>
+                  <object class="GtkButton">
+                    <property name="valign">center</property>
+                    <property name="icon-name">call-start-symbolic</property>
+                    <style>
+                      <class name="flat"/>
+                    </style>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkButton">
+                    <property name="valign">center</property>
+                    <property name="icon-name">star-outline-thick-symbolic</property>
+                    <style>
+                      <class name="flat"/>
+                    </style>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">Row with a Subtitle</property>
+                <property name="subtitle" translatable="yes">Can be used to provide more context</property>
+              </object>
+            </child>
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">Row with an Icon</property>
+                <property name="icon-name">library-music-symbolic</property>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="label" translatable="yes">Value displayed in the row</property>
+                    <property name="ellipsize">start</property>
+                    <property name="xalign">1</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwPreferencesGroup">
+            <property name="title" translatable="yes">Navigation</property>
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">Row Opening a Sub-View</property>
+                <property name="subtitle" translatable="yes">Dialog or sub-page, depending on screen 
size</property>
+                <property name="activatable">True</property>
+                <property name="action-name">page.sub-view</property>
+                <child>
+                  <object class="GtkImage">
+                    <property name="icon-name">go-next-symbolic</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">Row Opening an External Link</property>
+                <property name="subtitle" translatable="yes">Could be a different app, or a 
website</property>
+                <property name="activatable">True</property>
+                <property name="action-name">page.external-link</property>
+                <child>
+                  <object class="GtkImage">
+                    <property name="icon-name">open-link-symbolic</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="AdwExpanderRow">
+                <property name="title" translatable="yes">Expanding Row</property>
+                <child>
+                  <object class="AdwActionRow">
+                    <property name="title" translatable="yes">An Option</property>
+                    <property name="activatable-widget">switch1</property>
+                    <child>
+                      <object class="GtkSwitch" id="switch1">
+                        <property name="valign">center</property>
+                        <property name="active">True</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="AdwActionRow">
+                    <property name="title" translatable="yes">Another Option</property>
+                    <property name="activatable-widget">switch2</property>
+                    <child>
+                      <object class="GtkSwitch" id="switch2">
+                        <property name="valign">center</property>
+                        <property name="active">True</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="AdwActionRow">
+                    <property name="title" translatable="yes">A Third Option</property>
+                    <property name="activatable-widget">switch3</property>
+                    <child>
+                      <object class="GtkSwitch" id="switch3">
+                        <property name="valign">center</property>
+                        <property name="active">True</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwPreferencesGroup">
+            <property name="title" translatable="yes">Choice Rows</property>
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">Row with a Switch</property>
+                <property name="activatable-widget">basic_switch</property>
+                <child>
+                  <object class="GtkSwitch" id="basic_switch">
+                    <property name="valign">center</property>
+                    <property name="active">True</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwPreferencesGroup">
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">One Exclusive Option</property>
+                <property name="activatable-widget">check_exclusive1</property>
+                <child type="prefix">
+                  <object class="GtkCheckButton" id="check_exclusive1">
+                    <property name="valign">center</property>
+                    <property name="active">True</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">Another Exclusive Option</property>
+                <property name="activatable-widget">check_exclusive2</property>
+                <child type="prefix">
+                  <object class="GtkCheckButton" id="check_exclusive2">
+                    <property name="valign">center</property>
+                    <property name="group">check_exclusive1</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwPreferencesGroup">
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">One Non-Exclusive Option</property>
+                <property name="activatable-widget">check_non_exclusive1</property>
+                <child>
+                  <object class="GtkCheckButton" id="check_non_exclusive1">
+                    <property name="valign">center</property>
+                    <property name="active">True</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">Another Non-Exclusive Option</property>
+                <property name="activatable-widget">check_non_exclusive2</property>
+                <child>
+                  <object class="GtkCheckButton" id="check_non_exclusive2">
+                    <property name="valign">center</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwPreferencesGroup">
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">Inline Choice</property>
+                <property name="subtitle" translatable="yes">For cases with few options and short 
labels</property>
+                <child>
+                  <object class="GtkBox">
+                    <property name="valign">center</property>
+                    <style>
+                      <class name="linked"/>
+                    </style>
+                    <child>
+                      <object class="GtkToggleButton" id="inline_choice_1">
+                        <property name="label" translatable="yes">AM/PM</property>
+                        <style>
+                          <class name="list-button"/>
+                        </style>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkToggleButton" id="inline_choice_2">
+                        <property name="label" translatable="yes">24 hour</property>
+                        <property name="active">True</property>
+                        <property name="group">inline_choice_1</property>
+                        <style>
+                          <class name="list-button"/>
+                        </style>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">Combo Row</property>
+                <property name="activatable-widget">dropdown</property>
+                <child>
+                  <object class="GtkDropDown" id="dropdown">
+                    <property name="valign">center</property>
+                    <property name="model">
+                      <object class="GtkStringList">
+                        <items>
+                          <item translatable="yes">5 minutes</item>
+                          <item translatable="yes">10 minutes</item>
+                          <item translatable="yes">1 hour</item>
+                        </items>
+                      </object>
+                    </property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwPreferencesGroup">
+            <property name="title" translatable="yes">Re-Orderable Rows</property>
+            <property name="description" translatable="yes">These list rows can be re-ordered using drag and 
drop</property>
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">Under Construction</property>
+                <property name="subtitle" translatable="yes">Nothing to see here</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwPreferencesGroup">
+            <property name="title" translatable="yes">Entry Rows</property>
+            <property name="description" translatable="yes">These list rows do not exist</property>
+            <child>
+              <object class="AdwActionRow">
+                <property name="title" translatable="yes">I'm not here</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwPreferencesGroup">
+            <property name="title" translatable="yes">List Buttons</property>
+            <property name="description" translatable="yes">Standalone buttons for important actions, 
usually right after a list</property>
+            <child>
+              <object class="GtkButton">
+                <property name="label" translatable="yes">Suggested Action</property>
+                <style>
+                  <class name="suggested-action"/>
+                </style>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton">
+                <property name="label" translatable="yes">Other Action</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton">
+                <property name="label" translatable="yes">Destructive Action</property>
+                <style>
+                  <class name="destructive-action"/>
+                </style>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </property>
+  </template>
+  <object class="AdwWindow" id="sub_view">
+    <property name="title" translatable="yes">Sub-View</property>
+    <property name="modal">True</property>
+    <property name="default-width">500</property>
+    <property name="default-height">420</property>
+    <property name="hide-on-close">True</property>
+    <property name="child">
+      <object class="GtkBox">
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkHeaderBar"/>
+        </child>
+        <child>
+          <object class="AdwPreferencesPage">
+            <property name="vexpand">True</property>
+            <child>
+              <object class="AdwPreferencesGroup">
+                <child>
+                  <object class="AdwActionRow">
+                    <property name="icon-name">data-movies-symbolic</property>
+                    <property name="title" translatable="yes">Movies</property>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label">24 GB</property>
+                        <property name="ellipsize">start</property>
+                        <property name="xalign">1</property>
+                        <style>
+                          <class name="dim-label"/>
+                          <class name="numeric"/>
+                        </style>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="AdwActionRow">
+                    <property name="icon-name">data-music-symbolic</property>
+                    <property name="title" translatable="yes">Music</property>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label">17 GB</property>
+                        <property name="ellipsize">start</property>
+                        <property name="xalign">1</property>
+                        <style>
+                          <class name="dim-label"/>
+                          <class name="numeric"/>
+                        </style>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="AdwActionRow">
+                    <property name="icon-name">data-photos-symbolic</property>
+                    <property name="title" translatable="yes">Photos</property>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label">201 GB</property>
+                        <property name="ellipsize">start</property>
+                        <property name="xalign">1</property>
+                        <style>
+                          <class name="dim-label"/>
+                          <class name="numeric"/>
+                        </style>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="AdwActionRow">
+                    <property name="icon-name">data-podcasts-symbolic</property>
+                    <property name="title" translatable="yes">Podcasts</property>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="label">59 GB</property>
+                        <property name="ellipsize">start</property>
+                        <property name="xalign">1</property>
+                        <style>
+                          <class name="dim-label"/>
+                          <class name="numeric"/>
+                        </style>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="AdwPreferencesGroup">
+                <child>
+                  <object class="GtkButton">
+                    <property name="label" translatable="yes">Empty Trash</property>
+                    <style>
+                      <class name="destructive-action"/>
+                    </style>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </property>
+    <child>
+      <object class='GtkShortcutController'>
+        <property name='scope'>managed</property>
+        <child>
+          <object class='GtkShortcut'>
+            <property name='trigger'>Escape</property>
+            <property name='action'>action(window.close)</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/demo/pages/stub/adw-demo-page-stub.c b/demo/pages/stub/adw-demo-page-stub.c
new file mode 100644
index 0000000..2d91503
--- /dev/null
+++ b/demo/pages/stub/adw-demo-page-stub.c
@@ -0,0 +1,22 @@
+#include "adw-demo-page-stub.h"
+
+struct _AdwDemoPageStub
+{
+  AdwDemoPage parent_instance;
+};
+
+G_DEFINE_TYPE (AdwDemoPageStub, adw_demo_page_stub, ADW_TYPE_DEMO_PAGE)
+
+static void
+adw_demo_page_stub_class_init (AdwDemoPageStubClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/Adwaita/Demo/pages/stub/adw-demo-page-stub.ui");
+}
+
+static void
+adw_demo_page_stub_init (AdwDemoPageStub *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/demo/pages/stub/adw-demo-page-stub.h b/demo/pages/stub/adw-demo-page-stub.h
new file mode 100644
index 0000000..65045f6
--- /dev/null
+++ b/demo/pages/stub/adw-demo-page-stub.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "adw-demo-page.h"
+
+G_BEGIN_DECLS
+
+#define ADW_TYPE_DEMO_PAGE_STUB (adw_demo_page_stub_get_type())
+
+G_DECLARE_FINAL_TYPE (AdwDemoPageStub, adw_demo_page_stub, ADW, DEMO_PAGE_STUB, AdwDemoPage)
+
+G_END_DECLS
diff --git a/demo/pages/stub/adw-demo-page-stub.ui b/demo/pages/stub/adw-demo-page-stub.ui
new file mode 100644
index 0000000..048f386
--- /dev/null
+++ b/demo/pages/stub/adw-demo-page-stub.ui
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk" version="4.0"/>
+  <requires lib="libadwaita" version="1.0"/>
+  <template class="AdwDemoPageStub" parent="AdwDemoPage">
+    <property name="child">
+      <object class="AdwStatusPage">
+        <property name="icon-name">dialog-warning-symbolic</property>
+        <property name="title" translatable="yes">Under Construction</property>
+        <property name="description" translatable="yes">This page is not implemented yet</property>
+      </object>
+    </property>
+  </template>
+</interface>
diff --git a/demo/style.css b/demo/style.css
new file mode 100644
index 0000000..7e8b2b9
--- /dev/null
+++ b/demo/style.css
@@ -0,0 +1,9 @@
+.numeric {
+  font-feature-settings: "tnum";
+}
+
+flowbox.inline flowboxchild {
+  padding: 0;
+  background: none;
+  color: inherit;
+}
diff --git a/meson.build b/meson.build
index ca921da..6212711 100644
--- a/meson.build
+++ b/meson.build
@@ -124,7 +124,7 @@ gnome = import('gnome')
 
 subdir('src')
 subdir('po')
-subdir('examples')
+subdir('demo')
 subdir('tests')
 subdir('doc')
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]