diff --git a/demo/GraniteDemo.vala b/demo/GraniteDemo.vala
index bbaf4a510..e67fd53c5 100644
--- a/demo/GraniteDemo.vala
+++ b/demo/GraniteDemo.vala
@@ -10,8 +10,19 @@ public class Granite.Demo : Gtk.Application {
}
public override void startup () {
- Granite.init ();
base.startup ();
+
+ Granite.init ();
+
+ var gtk_settings = Gtk.Settings.get_default ();
+ gtk_settings.gtk_theme_name = "Granite";
+
+ var granite_settings = Granite.Settings.get_default ();
+ gtk_settings.gtk_application_prefer_dark_theme = granite_settings.prefers_color_scheme == DARK;
+
+ granite_settings.notify["prefers-color-scheme"].connect (() => {
+ gtk_settings.gtk_application_prefer_dark_theme = granite_settings.prefers_color_scheme == DARK;
+ });
}
public override void activate () {
@@ -96,9 +107,6 @@ public class Granite.Demo : Gtk.Application {
shrink_start_child = false
};
- var granite_settings = Granite.Settings.get_default ();
- gtk_settings.gtk_application_prefer_dark_theme = granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK;
-
window.child = paned;
window.set_default_size (900, 600);
window.set_size_request (750, 500);
@@ -107,10 +115,6 @@ public class Granite.Demo : Gtk.Application {
add_window (window);
window.show ();
-
- granite_settings.notify["prefers-color-scheme"].connect (() => {
- gtk_settings.gtk_application_prefer_dark_theme = granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK;
- });
}
public static int main (string[] args) {
diff --git a/demo/Views/CSSView.vala b/demo/Views/CSSView.vala
index f5ed52ec5..c9c2619a2 100644
--- a/demo/Views/CSSView.vala
+++ b/demo/Views/CSSView.vala
@@ -43,17 +43,22 @@ public class CSSView : Gtk.Box {
card.append (header4);
var richlist_label = new Granite.HeaderLabel ("Lists") {
- secondary_text = "\"rich-list\" and \"frame\" style classes"
+ secondary_text = "\"rich-list\" and \"card\" style classes"
};
- var rich_listbox = new Gtk.ListBox () {
- show_separators = true
+ var separators_modelbutton = new Granite.SwitchModelButton ("Show Separators") {
+ active = true,
+ description = "SwitchModelButton works great here too!"
};
+
+ var rich_listbox = new Gtk.ListBox ();
rich_listbox.add_css_class (Granite.STYLE_CLASS_RICH_LIST);
- rich_listbox.add_css_class (Granite.STYLE_CLASS_FRAME);
+ rich_listbox.add_css_class (Granite.STYLE_CLASS_CARD);
rich_listbox.append (new Gtk.Label ("Row 1"));
rich_listbox.append (new Gtk.Label ("Row 2"));
- rich_listbox.append (new Gtk.Label ("Row 3"));
+ rich_listbox.append (separators_modelbutton);
+
+ separators_modelbutton.bind_property ("active", rich_listbox, "show-separators", SYNC_CREATE | DEFAULT);
var terminal_label = new Granite.HeaderLabel ("\"terminal\" style class");
diff --git a/lib/Constants.vala b/lib/Constants.vala
index 7365e8c7f..141633689 100644
--- a/lib/Constants.vala
+++ b/lib/Constants.vala
@@ -21,6 +21,7 @@ namespace Granite {
* Style class for numbered badges
*/
public const string STYLE_CLASS_BADGE = "badge";
+
/**
* Style class for adding a small shadow to a container such as for image thumbnails
*
diff --git a/lib/Icons/icons.gresource.xml b/lib/Icons/icons.gresource.xml
index 62f5a346a..bc0008839 100644
--- a/lib/Icons/icons.gresource.xml
+++ b/lib/Icons/icons.gresource.xml
@@ -25,8 +25,8 @@
scalable/adw-tab-icon-missing-symbolic.svg
scalable/adw-tab-overflow-symbolic.svg
- scalable/check-active-symbolic.svg
- scalable/check-mixed-symbolic.svg
+ scalable/check-checked.svg
+ scalable/check-indeterminate.svg
scalable/pager-checked-symbolic.svg
diff --git a/lib/Icons/scalable/check-active-symbolic.svg b/lib/Icons/scalable/check-active-symbolic.svg
deleted file mode 100644
index fb711dbb3..000000000
--- a/lib/Icons/scalable/check-active-symbolic.svg
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
diff --git a/lib/Icons/scalable/check-checked.svg b/lib/Icons/scalable/check-checked.svg
new file mode 100644
index 000000000..7647fb890
--- /dev/null
+++ b/lib/Icons/scalable/check-checked.svg
@@ -0,0 +1,30 @@
+
+
diff --git a/lib/Icons/scalable/check-indeterminate.svg b/lib/Icons/scalable/check-indeterminate.svg
new file mode 100644
index 000000000..014197d67
--- /dev/null
+++ b/lib/Icons/scalable/check-indeterminate.svg
@@ -0,0 +1,25 @@
+
+
diff --git a/lib/Icons/scalable/check-mixed-symbolic.svg b/lib/Icons/scalable/check-mixed-symbolic.svg
deleted file mode 100644
index 745126524..000000000
--- a/lib/Icons/scalable/check-mixed-symbolic.svg
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
diff --git a/lib/Styles/Granite/Index.scss b/lib/Styles/Granite/Index.scss
index c7eed0964..18df447a7 100644
--- a/lib/Styles/Granite/Index.scss
+++ b/lib/Styles/Granite/Index.scss
@@ -1,4 +1,5 @@
@import '_card.scss';
+@import '_sidebar.scss';
@import 'Dialog.scss';
@import 'Header.scss';
@import 'MessageDialog.scss';
diff --git a/lib/Styles/Granite/OverlayBar.scss b/lib/Styles/Granite/OverlayBar.scss
index da18d9709..2ca0f536f 100644
--- a/lib/Styles/Granite/OverlayBar.scss
+++ b/lib/Styles/Granite/OverlayBar.scss
@@ -1,5 +1,5 @@
overlaybar .osd {
- padding: rem(6px) rem(12px);
+ padding: $button-spacing rem(12px);
text-shadow: 0 rem(1px) rem(2px) rgba($fg_color, 0.6);
spinner {
diff --git a/lib/Styles/Granite/_sidebar.scss b/lib/Styles/Granite/_sidebar.scss
new file mode 100644
index 000000000..8b533ad7e
--- /dev/null
+++ b/lib/Styles/Granite/_sidebar.scss
@@ -0,0 +1,12 @@
+.sidebar {
+ background-color: bg_color(3);
+ box-shadow: highlight();
+ min-width: rem(200px);
+
+ // Clear nested sidebar
+ .sidebar {
+ background: transparent;
+ box-shadow: none;
+ min-width: 0;
+ }
+}
diff --git a/lib/Styles/Gtk/Arrow.scss b/lib/Styles/Gtk/Arrow.scss
new file mode 100644
index 000000000..eceefa7a1
--- /dev/null
+++ b/lib/Styles/Gtk/Arrow.scss
@@ -0,0 +1,21 @@
+arrow {
+ -gtk-icon-source: -gtk-icontheme("pan-down-symbolic");
+ min-height: rem(16px);
+ min-width: rem(16px);
+
+ &.down {
+ -gtk-icon-source: -gtk-icontheme("pan-down-symbolic");
+ }
+
+ &.left {
+ -gtk-icon-source: -gtk-icontheme("pan-start-symbolic");
+ }
+
+ &.right {
+ -gtk-icon-source: -gtk-icontheme("pan-end-symbolic");
+ }
+
+ &.up {
+ -gtk-icon-source: -gtk-icontheme("pan-up-symbolic");
+ }
+}
diff --git a/lib/Styles/Gtk/CheckRadio.scss b/lib/Styles/Gtk/CheckRadio.scss
new file mode 100644
index 000000000..e1d3912e5
--- /dev/null
+++ b/lib/Styles/Gtk/CheckRadio.scss
@@ -0,0 +1,40 @@
+check,
+radio {
+ background-color: scale-color($toplevel-border-color, $alpha: -50%); // FIXME: abstract as trough color?
+ -gtk-icon-size: 1em;
+ min-height: 1em;
+ min-width: 1em;
+ padding: 1px;
+
+ &:checked {
+ background-color: $BLUEBERRY_500; // FIXME: use accent color
+ color: white;
+ -gtk-icon-source: -gtk-icontheme("check-checked-symbolic");
+ }
+
+ &:indeterminate {
+ color: rgba($fg-color, 0.5);
+ -gtk-icon-source: -gtk-icontheme("check-indeterminate-symbolic");
+ }
+}
+
+check {
+ border-radius: rem($window_radius / 3);
+
+ &:checked {
+ -gtk-icon-source: -gtk-icontheme("check-checked-symbolic");
+ }
+}
+
+radio {
+ border-radius: 50%;
+
+ &:checked {
+ -gtk-icon-source: -gtk-icontheme("pager-checked-symbolic");
+ }
+}
+
+radiobutton,
+checkbutton {
+ border-spacing: 0.5em; // FIXME: abstract button spacing?
+}
diff --git a/lib/Styles/Gtk/HeaderBar.scss b/lib/Styles/Gtk/HeaderBar.scss
index 7413a7354..f9d2c82db 100644
--- a/lib/Styles/Gtk/HeaderBar.scss
+++ b/lib/Styles/Gtk/HeaderBar.scss
@@ -29,6 +29,6 @@ headerbar {
}
.csd & {
- padding: rem(6px);
+ padding: $button-spacing;
}
}
diff --git a/lib/Styles/Gtk/Index.scss b/lib/Styles/Gtk/Index.scss
index 9f3dc5f5e..c8942721d 100644
--- a/lib/Styles/Gtk/Index.scss
+++ b/lib/Styles/Gtk/Index.scss
@@ -1,6 +1,9 @@
+@import 'Arrow.scss';
@import 'Button.scss';
+@import 'CheckRadio.scss';
@import 'HeaderBar.scss';
@import 'Image.scss';
+@import 'List.scss';
@import 'Popover.scss';
@import 'Scrollbar.scss';
@import 'ShortcutsWindow.scss';
diff --git a/lib/Styles/Gtk/List.scss b/lib/Styles/Gtk/List.scss
new file mode 100644
index 000000000..276e5d809
--- /dev/null
+++ b/lib/Styles/Gtk/List.scss
@@ -0,0 +1,40 @@
+list {
+ &.rich-list > row {
+ padding: rem(6px);
+ min-height: rem(32px); //Try to force homogeneous row height
+ }
+
+ &.card,
+ &.boxed-list {
+ @extend .rounded;
+
+ > row {
+ // Rounded top
+ &:first-child {
+ &, &.expander row.header {
+ border-top-left-radius: rem($window_radius / 2);
+ border-top-right-radius: rem($window_radius / 2);
+ }
+ }
+
+ // Rounded bottom
+ &:last-child {
+ &,
+ &.expander:not(:checked),
+ &.expander:not(:checked) row.header,
+ &.expander:checked list.nested,
+ &.expander:checked list.nested > row:last-child {
+ border-bottom-left-radius: rem($window_radius / 2);
+ border-bottom-right-radius: rem($window_radius / 2);
+ border-bottom-width: 0;
+ }
+ }
+ }
+ }
+
+
+ &.separators > row + row {
+ border-top: 1px solid $border-color;
+ box-shadow: inset 0 1px 0 0 scale-color($highlight_color, $alpha: -93%);
+ }
+}
diff --git a/lib/Styles/Gtk/Popover.scss b/lib/Styles/Gtk/Popover.scss
index 9496386ac..9610df035 100644
--- a/lib/Styles/Gtk/Popover.scss
+++ b/lib/Styles/Gtk/Popover.scss
@@ -21,31 +21,70 @@ popover {
highlight(),
0 0 0 1px $toplevel-border-color,
shadow(2);
- padding: rem(6px);
+ padding: $button-spacing;
}
}
-.menuitem,
-modelbutton {
+.model {
border-radius: rem($window_radius / 2);
- border-spacing: rem(6px);
- min-width: rem(150px);
+ padding: $button-spacing;
transition:
background duration("expand") easing(),
transform duration("expand") easing("ease-out-back");
- padding: rem(6px);
- &:hover {
+ &.image-button {
+ background: rgba($fg_color, 0.05);
+ }
+
+ &.circular {
+ padding: rem(9px);
+ }
+
+ // Focus and hover are synonymous in Popovers
+ &:hover,
+ &:focus {
background: rgba($fg_color, 0.1);
}
&:active {
background: rgba($fg-color, 0.15);
- // There's an optical illusion because items are wider than
- // they are tall, so compensate by scaling y a little extra
- transform: scale(0.98, 0.96);
+ transform: scale(0.95);
transition:
background duration("collapse") easing(),
transform duration("collapse") easing();
}
}
+
+.menuitem,
+modelbutton {
+ @extend .model;
+
+ border-spacing: rem(6px);
+ min-width: rem(150px);
+
+ &:active {
+ // There's an optical illusion because items are wider than
+ // they are tall, so compensate by scaling y a little extra
+ transform: scale(0.98, 0.96);
+ }
+}
+
+.menu {
+ .circular-buttons,
+ .inline-buttons {
+ border-spacing: rem(6px);
+ padding: $button-spacing;
+
+ > box {
+ border-spacing: rem(6px);
+ }
+ }
+
+ .title {
+ @extend .title-4;
+
+ &.separator {
+ padding: $button-spacing;
+ }
+ }
+}
diff --git a/lib/Styles/Gtk/ShortcutsWindow.scss b/lib/Styles/Gtk/ShortcutsWindow.scss
index a722ca230..2865fa38b 100644
--- a/lib/Styles/Gtk/ShortcutsWindow.scss
+++ b/lib/Styles/Gtk/ShortcutsWindow.scss
@@ -11,7 +11,7 @@ accelerator,
color: rgba($fg_color, 0.9);
font-size: 85%;
min-width: rem(12px);
- padding: rem(3px) rem(6px);
+ padding: rem(3px) $button-spacing;
}
// Characters between keys in Gtk.ShortcutLabel, like + or /
diff --git a/lib/Styles/Index-dark.scss b/lib/Styles/Index-dark.scss
index 9cbe6fe73..57047e17e 100644
--- a/lib/Styles/Index-dark.scss
+++ b/lib/Styles/Index-dark.scss
@@ -20,7 +20,7 @@ $toplevel-border-color: rgba(black, 0.75);
@return $BLACK_500;
// Sidebars and inline toolbars
} @else if $level == 3 {
- @return mix($BLACK_500, $BLACK_700, $weight: 90%);
+ @return mix($BLACK_500, $BLACK_700, $weight: 80%);
// Titlebars and toolbars
} @else if $level == 4 {
@return mix($BLACK_500, $BLACK_700, $weight: 45%);
diff --git a/lib/Styles/_common.scss b/lib/Styles/_common.scss
index 3043b7a33..c423fa749 100644
--- a/lib/Styles/_common.scss
+++ b/lib/Styles/_common.scss
@@ -80,5 +80,6 @@
@return $highlight;
}
+$button-spacing: rem(6px);
$disabled-opacity: 0.5;
$window_radius: 9px;
diff --git a/lib/Styles/_osd.scss b/lib/Styles/_osd.scss
index 33d3c1f92..ef2d04532 100644
--- a/lib/Styles/_osd.scss
+++ b/lib/Styles/_osd.scss
@@ -3,6 +3,6 @@
border-radius: rem($window_radius / 2);
box-shadow: shadow(1);
color: bg-color(1);
- margin: rem(6px);
- padding: rem(6px);
+ margin: $button-spacing;
+ padding: $button-spacing;
}