Browse Source

style: Use SASS to organize styles

We now require a SASS compiler at build time.
pipelines/767384
Kévin Commaille 1 year ago
parent
commit
55724695ce
No known key found for this signature in database
GPG Key ID: C971D9DBC9D678D
  1. 25
      build-aux/org.gnome.Fractal.Devel.json
  2. 46
      data/resources/meson.build
  3. 1
      data/resources/resources.gresource.xml
  4. 11
      data/resources/style-hc.scss
  5. 1071
      data/resources/style.css
  6. 5
      data/resources/style.scss
  7. 117
      data/resources/stylesheet/_common.scss
  8. 163
      data/resources/stylesheet/_components.scss
  9. 3
      data/resources/stylesheet/_config.scss
  10. 26
      data/resources/stylesheet/_login.scss
  11. 111
      data/resources/stylesheet/_room_details.scss
  12. 350
      data/resources/stylesheet/_room_history.scss
  13. 230
      data/resources/stylesheet/_session_view.scss
  14. 41
      data/resources/stylesheet/_vendor.scss

25
build-aux/org.gnome.Fractal.Devel.json

@ -48,7 +48,32 @@
"cleanup-commands": [
"mkdir -p ${FLATPAK_DEST}/lib/ffmpeg"
],
"cleanup": [
"bin/grass"
],
"modules": [
{
"name": "grass",
"buildsystem": "simple",
"build-options": {
"env": {
"CARGO_HOME": "/run/build/grass/cargo"
}
},
"build-commands": [
"cargo build --release --locked",
"mkdir -p /app/bin",
"install -D ./target/release/grass /app/bin/"
],
"sources": [
{
"type": "git",
"url": "https://github.com/connorskees/grass",
"tag": "0.13.4",
"commit": "e0bb9e2eabfc3a58e42b03089cd7b22c68d09d0b"
}
]
},
{
"name": "protobuf-c",
"buildsystem": "autotools",

46
data/resources/meson.build

@ -1,3 +1,48 @@
# Stylesheets
# We accept grass (a Rust SASS compiler) or sass (the official dart SASS compiler).
sass_bin = find_program('grass', required: false)
sass_options = []
if not sass_bin.found()
# Require SASS as we need at least one compiler.
sass_bin = find_program('sass')
if sass_bin.found()
# these options are not supported by grass.
sass_options += ['--no-error-css', '--no-source-map']
endif
endif
scss_files = [
'style',
'style-hc',
]
# Keep ordered alphabetically.
scss_deps = files([
'stylesheet/_common.scss',
'stylesheet/_components.scss',
'stylesheet/_config.scss',
'stylesheet/_login.scss',
'stylesheet/_room_details.scss',
'stylesheet/_room_history.scss',
'stylesheet/_session_view.scss',
'stylesheet/_vendor.scss',
])
stylesheet_deps = []
foreach scss: scss_files
stylesheet_deps += custom_target('@0@.scss'.format(scss),
input: '@0@.scss'.format(scss),
output: '@0@.css'.format(scss),
command: [
sass_bin, sass_options, '@INPUT@', '@OUTPUT@',
],
depend_files: scss_deps,
)
endforeach
# Resources
resources = gnome.compile_resources(
'resources',
@ -5,4 +50,5 @@ resources = gnome.compile_resources(
gresource_bundle: true,
install: true,
install_dir: pkgdatadir,
dependencies: stylesheet_deps,
)

1
data/resources/resources.gresource.xml

@ -98,6 +98,7 @@
<file compressed="true">sas-emoji/uk.json</file>
<file compressed="true">sas-emoji/vi.json</file>
<file compressed="true">sas-emoji/zh_Hans.json</file>
<file compressed="true">style-hc.css</file>
<file compressed="true">style.css</file>
</gresource>
</gresources>

11
data/resources/style-hc.scss

@ -0,0 +1,11 @@
// High contrast variant.
// Initialize contrast variable.
@use 'stylesheet/config' with (
$contrast: 'high',
);
@use 'stylesheet/common';
@use 'stylesheet/components';
@use 'stylesheet/login';
@use 'stylesheet/session_view';

1071
data/resources/style.css

File diff suppressed because it is too large Load Diff

5
data/resources/style.scss

@ -0,0 +1,5 @@
@use 'stylesheet/common';
@use 'stylesheet/components';
@use 'stylesheet/login';
@use 'stylesheet/session_view';

117
data/resources/stylesheet/_common.scss

@ -0,0 +1,117 @@
// Global selectors.
@use 'vendor';
:root {
--focus-outline-color: color-mix(in srgb, var(--accent-color) 50%, transparent);
}
textview, text {
color: inherit;
background: none;
}
.bold {
font-weight: bold;
}
button.pill.large {
padding: 12px 40px;
}
.emoji {
font-size: 2em;
}
headerbar .suggested-action, .standalone-button {
min-width: 70px;
}
.extra-large-icon {
-gtk-icon-size: 128px;
}
.form-page {
scrolledwindow > viewport > clamp > box {
margin: 42px 12px;
border-spacing: 24px;
}
levelbar.discrete block {
min-height: 5px;
}
}
box.paragraphs {
// Set the spacing between paragraphs.
border-spacing: 12px;
}
.content .label-button {
min-width: 86px;
}
button.overlaid {
// Make sure the outline is fully visible.
margin: 3px;
}
.avatar-row-list, .string-row-list {
contents {
padding: 0;
}
viewport, listview {
padding: 8px;
}
list, listview {
background-color: transparent;
}
row {
border-radius: vendor.$menu_radius;
margin: 3px 0px;
padding: 6px;
}
}
.avatar-row-list {
row {
&:first-child {
margin-top: 0px;
}
&:last-child {
margin-bottom: 0px;
}
}
}
.string-row-list row {
margin: 0px;
}
.entry-row-error-revealer {
margin-top: 6px;
}
.card-icon {
padding: 12px;
border-radius: 100%;
-gtk-icon-size: 20px;
background-color: color-mix(in srgb, var(--accent-bg-color) 30%, transparent);
}
.card.command {
border-radius: vendor.$menu_radius;
font-size: 90%;
}
scrolledwindow.card {
@include vendor.focus-ring($offset: -1px, $focus-state: ':focus-within');
> textview {
padding: 12px;
}
}

163
data/resources/stylesheet/_components.scss

@ -0,0 +1,163 @@
// Components.
@use "sass:math";
@use 'vendor';
inline-pill {
border-radius: 9999px;
background-color: vendor.$button_color;
@include vendor.focus-ring();
&.activatable {
&:hover {
background-color: vendor.$button_hover_color;
image {
filter: brightness(1.07) ;
}
}
&:active {
background-color: vendor.$button_active_color;
image {
filter: brightness(1.16) ;
}
}
}
}
.selected-avatar avatar {
border: 2px solid var(--accent-bg-color);
}
.blue-checkmark {
color: var(--accent-fg-color);
border-radius: 9999px;
border: solid var(--accent-bg-color) 2px;
background-color: var(--accent-bg-color);
}
role-badge {
color: var(--dark-5);
background-color: var(--light-3);
border-radius: 0.4em;
padding: 0.1em 0.5em;
font-size: 0.8em;
&.admin {
color: var(--error-fg-color);
background-color: var(--error-bg-color);
}
&.mod {
color: var(--warning-fg-color);
background-color: var(--warning-bg-color);
}
&.muted {
color: var(--light-1);
background-color: var(--dark-2);
}
}
media-viewer toolbarview headerbar {
background: black;
color: white;
}
media-content-viewer controls {
min-width: 300px;
}
location-viewer .map-marker {
color: var(--accent-color);
}
entry inline-pill {
margin-bottom: -0.5em;
}
editable-avatar {
.cutout {
background-color: var(--window-bg-color);
border-radius: 9999px;
padding: 2px;
}
.osd.circular {
$size: 64px;
min-width: $size;
min-height: $size;
border-radius: math.div($size, 2);
}
}
.substring-entry-row .header {
.subtitle {
margin-top: 4px;
margin-bottom: -4px;
}
text placeholder {
opacity: var(--dim-opacity);
}
}
.role-selection-popover {
viewport > box {
padding: 6px;
}
list row {
margin: 0;
padding: 2px 6px;
border-radius: vendor.$menu_radius;
&.spin {
padding: 0;
> box {
min-height: 30px;
}
spinbutton > button {
margin-top: 6px;
margin-bottom: 6px;
}
button.spin-confirm {
min-height: 22px;
min-width: 22px;
padding: 0;
margin-left: 2px;
&:dir(rtl) {
margin-left: 0;
margin-right: 2px;
}
image {
padding: 7px;
}
}
}
}
}
row.button loading-bin label.title {
margin-left: 12px;
margin-right: 12px;
min-height: 40px;
}
crop-circle > .mask {
background: black;
border-radius: 9999px;
}
user-page scrolledwindow > viewport > clamp > box {
margin: 12px;
border-spacing: 24px;
}

3
data/resources/stylesheet/_config.scss

@ -0,0 +1,3 @@
// Configuration file with global variable.
$contrast: 'default' !default;

26
data/resources/stylesheet/_login.scss

@ -0,0 +1,26 @@
// Login and setup.
login {
min-width: 250px;
}
qrcode {
background-color: white;
padding: 12px;
}
.sso-button {
padding: 4px;
-gtk-icon-size: 26px;
min-height: 34px;
}
setup-view {
clamp {
margin: 12px;
}
.text-button {
min-width: 200px;
}
}

111
data/resources/stylesheet/_room_details.scss

@ -0,0 +1,111 @@
// Room details.
@use 'vendor';
// Visual media history viewer
visual-media-history-viewer {
background: black;
color: white;
headerbar {
background: none;
box-shadow: none;
}
gridview {
background: none;
padding: 2px;
}
}
visual-media-history-viewer-item {
background: none;
transition: vendor.$ease-out-quad;
&:hover, &:focus {
transform: scale(1.03);
}
&:active {
transform: scale(0.98);
}
> overlay > image {
border-radius: 100%;
padding: 12px;
-gtk-icon-size: 24px;
}
}
file-history-viewer, audio-history-viewer {
listview > row {
border-radius: 0;
padding: 6px;
&:last-child {
border-bottom-width: 0;
}
}
}
// Room details
.room-details listview {
background: transparent;
}
members-list {
listview > row, members-list list > row {
padding: 8px 12px;
min-height: 32px;
}
listview > row {
margin-bottom: 6px;
border-radius: vendor.$card_radius;
}
row .icon {
&:dir(ltr) {
margin-right: 6px;
}
&:dir(rtl) {
margin-left: 6px;
}
}
}
dragoverlay statuspage {
background-color: color-mix(in srgb, var(--accent-bg-color) var(--dim-opacity), transparent);
color: var(--accent-fg-color);
}
.public-address-tag {
color: var(--accent-fg-color);
background-color: var(--accent-bg-color);
border-radius: 0.4em;
padding: 0.3em 0.5em;
margin-left: 0.5em;
}
.permissions-member-list > row {
min-height: 0;
padding: 0;
border-radius: 0;
margin: 6px;
}
permissions-member-row {
padding: 8px;
border-radius: vendor.$card_radius;
@include vendor.focus-ring();
&:hover, &.has-open-popup {
background-color: vendor.$hover_color;
}
&:active {
background-color: vendor.$active_color;
}
}

350
data/resources/stylesheet/_room_history.scss

@ -0,0 +1,350 @@
// Room history.
@use 'config';
@use 'vendor';
.room-history .room-history-list {
padding-bottom: 0;
> row {
min-height: 0;
padding: 0;
border-radius: 0;
}
}
room-history-row {
padding-top: 2px;
padding-bottom: 2px;
padding-left: 8px;
padding-right: 8px;
border-radius: vendor.$menu_radius;
@include vendor.focus-ring();
&.has-header {
margin-top: 6px;
}
&:not(.has-header) {
.event-content, message-reactions {
&:dir(ltr) {
margin-left: 54px;
}
&:dir(rtl) {
margin-right: 54px;
}
}
}
&.has-open-popup {
background-color: vendor.$hover_color;
}
&.selected {
background-color: vendor.$selected_color;
&.has-open-popup {
background-color: vendor.$selected_hover_color;
}
}
&.highlight {
background-color: color-mix(in srgb, var(--accent-bg-color) 20%, transparent);
&.has-open-popup {
background-color: color-mix(in srgb, var(--accent-bg-color) 25%, transparent);
}
&.selected {
background-color: color-mix(in srgb, var(--accent-bg-color) 30%, transparent);
&.has-open-popup {
background-color: color-mix(in srgb, var(--accent-bg-color) 33%, transparent);
}
}
}
.event-content {
.emoji {
font-size: 3em;
}
.emote {
color: var(--accent-color);
}
}
}
.visual-content {
&.opaque-bg {
border-radius: vendor.$menu_radius;
background-color: var(--border-color);
}
.spinner {
min-width: 32px;
min-height: 32px;
}
image.osd.circular {
min-width: 64px;
min-height: 64px;
border-radius: 32px;
-gtk-icon-size: 32px;
}
.timestamp {
border-radius: 4px;
padding: 2px 5px;
}
&.compact {
.spinner {
min-width: 16px;
min-height: 16px;
}
image.osd.circular {
min-width: 32px;
min-height: 32px;
-gtk-icon-size: 16px;
}
}
}
room-history-row .event-content .quote,
.related-event-content {
border-left: 2px solid var(--accent-bg-color);
padding-left: 6px;
opacity: if(config.$contrast == 'high', 90%, 70%);;
}
message-reactions flowboxchild {
&:hover, &:active {
// Cancel effect under .navigation-sidebar from libadwaita
background-color: transparent;
}
}
message-reactions {
&:dir(ltr) .toggle {
padding: 1px 0 1px 6px;
}
&:dir(rtl) .toggle {
padding: 1px 6px 1px 0;
}
.reaction-key {
font-size: 0.8em;
}
.reaction-key.emoji {
font-size: 1.1em;
padding-right: 2px;
padding-left: 2px;
}
.reaction-count {
font-size: 0.8em;
}
}
.reaction-chooser {
margin: 6px;
button {
font-size: 1.3em;
-gtk-icon-size: 1.3em;
padding: 2px;
}
}
read-receipts-list {
min-height: 20px;
min-width: 20px;
padding: 6px;
border-radius: 9999px;
@include vendor.focus-ring();
&:hover {
background-color: vendor.$hover_color;
}
&:active {
background-color: vendor.$active_color;
}
&:checked {
background-color: vendor.$selected_color;
}
}
divider-row {
font-size: 0.9em;
font-weight: bold;
label {
opacity: var(--dim-opacity);
}
&.new-messages {
color: var(--accent-color);
label {
opacity: 1;
}
separator {
min-height: 2px;
background-color: var(--accent-color);
}
}
}
.timestamp {
min-width: 36px;
font-weight: normal;
}
.codeview {
border-radius: vendor.$menu_radius;
padding: 6px;
font-family: monospace;
background-color: var(--text-view-bg);
color: var(--view-fg-color);
}
.related-event-toolbar {
padding: 0 6px 0 12px;
button {
margin: 12px 6px;
min-height: 24px;
min-width: 24px;
}
}
.related-event-content {
padding-top: 2px;
padding-bottom: 2px;
}
typing-row {
padding: 0 6px;
min-height: 30px;
}
room-history-row, .related-event-content {
.h1 {
font-weight: 800;
font-size: 15pt;
}
.h2 {
font-weight: 800;
font-size: 14pt;
}
.h3 {
font-weight: 700;
font-size: 14pt;
}
.h4 {
font-weight: 700;
font-size: 13pt;
}
.h5 {
font-weight: 700;
font-size: 12pt;
}
.h6 {
font-weight: 700;
font-size: 11pt;
}
}
room-history-row expander-widget > box > {
title {
border-spacing: 6px;
}
:not(title) {
padding: 12px;
}
}
room-title {
margin-top: -6px;
margin-bottom: -6px;
min-height: 12px;
padding: 3px 0;
.title {
padding: 0;
font-weight: bold;
}
.subtitle {
padding: 0;
font-weight: normal;
}
&.with-subtitle {
button {
padding-top: 0;
padding-bottom: 0;
}
.title, .subtitle {
margin-top: -0.2rem;
}
}
}
sender-avatar {
padding: 3px;
border-radius: 100%;
@include vendor.focus-ring();
&:hover {
background-color: vendor.$hover_color;
image {
filter: brightness(1.07) ;
}
}
&:active {
background-color: vendor.$active_color;
image {
filter: brightness(1.16) ;
}
}
&:checked {
background-color: vendor.$selected_color;
image {
filter: brightness(1.1) ;
}
}
popover button.text-button {
padding-left: 10px;
padding-right: 10px;
font-weight: 400;
}
}
button.send-text-message-button image {
transform: translateX(2px);
}

230
data/resources/stylesheet/_session_view.scss

@ -0,0 +1,230 @@
// Session view.
@use 'vendor';
@use 'room_history';
@use 'room_details';
// Account switcher
.account-switcher {
list {
background-color: transparent;
}
.account-switcher-row {
border-radius: vendor.$menu_radius;
margin: 3px 0px;
padding: 6px 12px;
&:first-child {
margin-top: 0px;
}
}
button.account-switcher-row {
font-weight: normal;
margin-bottom: 0;
}
}
#new-login-icon {
padding: 12px; // 2 * padding + pixel-size = size (of avatar)
background-color: vendor.$button_color;
border-radius: 9999px;
}
// Sidebar
sidebar {
.collapse-spacing {
padding: 0;
}
searchbar > revealer > box {
padding-top: 0;
padding-bottom: 6px;
}
.sidebar-list row {
margin: 0;
padding: 0;
border-radius: 0;
// Reset focus effect.
&:focus-within {
outline: 0;
}
&:hover, &:selected {
background: none;
}
&:active sidebar-row > *:not(popover) {
background-color: vendor.$active_color;
}
&:selected sidebar-row > *:not(popover) {
background-color: vendor.$selected_color;
}
&:selected sidebar-row:not(.drop-mode) > *:not(popover):hover {
background-color: vendor.$selected_hover_color;
}
&:selected:active sidebar-row > *:not(popover) {
background-color: vendor.$selected_active_color;
}
}
sidebar-row {
> *:not(popover) {
margin: 2px 6px 0;
padding: 9px;
border-radius: vendor.$menu_radius;
}
@include vendor.focus-ring($target: '> *:not(popover)');
&:not(.drop-mode) > *:not(popover):hover {
background-color: vendor.$hover_color;
}
icon-item {
background: none;
font-weight: bold;
image {
min-width: 24px; /* Same width as avatars, so the text is aligned */
}
}
sidebar-section {
margin-top: 6px;
font-size: 0.8em;
font-weight: bold;
image.arrow {
transition: 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
&:not(:checked) image.arrow {
&:dir(ltr) {
transform: rotate(-0.5turn);
}
&:dir(rtl) {
transform: rotate(0.5turn);
}
}
}
.notification-count {
font-weight: bold;
font-size: 0.8em;
border-radius: 9999px;
min-width: 0.7em;
padding: 2px 5px;
color: currentColor;
background-color: color-mix(in srgb, currentColor 15%, transparent);
}
.highlight {
color: var(--accent-fg-color);
background-color: var(--accent-bg-color);
}
&.drag > * {
color: var(--accent-fg-color);
background-color: var(--accent-bg-color);
opacity: var(--disabled-opacity);
}
&.drop-disabled > *:not(popover) {
opacity: var(--disabled-opacity);
}
&.drop-empty > *:not(popover) {
color: var(--accent--color);
}
icon-item.forget {
color: var(--error-color);
background: none;
}
&.drop-active {
background-color: color-mix(in srgb, var(--accent-color) 10%, transparent);
category {
color: var(--accent-color);
}
.dim-label, &.drop-empty .dim-label {
opacity: 1;
}
}
}
}
// Explore
.explore {
.padded-button {
min-width: 64px;
}
.public-rooms row {
border-radius: vendor.$menu_radius;
margin: 6px 0;
padding: 12px;
}
}
.explore-servers-popover list {
background-color: transparent;
color: inherit;
row {
min-height: 36px;
padding: 0 8px;
border-radius: vendor.$menu_radius;
margin: 0 0 2px;
button {
min-height: 24px;
min-width: 24px;
}
}
}
// Invite
.invite-room-name {
font-size: 1.6em;
}
.invite-search-results {
padding: 12px 0px;
> row {
border-radius: vendor.$menu_radius;
}
}
// Event details dialog
.event-details-dialog .sourceview {
font-family: monospace;
}
// Account settings
.account-settings listview {
background: transparent;
}
// Account chooser dialog
.account-chooser list {
background: transparent;
row {
margin-bottom: 6px;
padding: 8px 12px;
min-height: 32px;
border-radius: vendor.$card_radius;
}
}

41
data/resources/stylesheet/_vendor.scss

@ -0,0 +1,41 @@
// SCSS reused directly from other projects.
@use 'config';
// https://gitlab.gnome.org/GNOME/libadwaita/-/blob/1.6.1/src/stylesheet/_colors.scss
$focus_border_opacity: if(config.$contrast == 'high', 80%, 50%);
$focus_border_color: color-mix(in srgb, var(--accent-color) $focus_border_opacity, transparent);
$hover_color: color-mix(in srgb, currentColor 7%, transparent);
$active_color: color-mix(in srgb, currentColor 16%, transparent);
$selected_color: color-mix(in srgb, currentColor 10%, transparent);
$selected_hover_color: color-mix(in srgb, currentColor 13%, transparent);
$selected_active_color: color-mix(in srgb, currentColor 19%, transparent);
// https://gitlab.gnome.org/GNOME/libadwaita/-/blob/1.6.1/src/stylesheet/widgets/_buttons.scss
$button_color: color-mix(in srgb, currentColor 10%, transparent);
$button_hover_color: color-mix(in srgb, currentColor 15%, transparent);
$button_active_color: color-mix(in srgb, currentColor 30%, transparent);
// https://gitlab.gnome.org/GNOME/libadwaita/-/blob/1.6.1/src/stylesheet/_common.scss
$ease-out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94);
$focus_transition: outline-color 200ms $ease-out-quad,
outline-width 200ms $ease-out-quad,
outline-offset 200ms $ease-out-quad;
$button_radius: 6px;
$card_radius: $button_radius + 6;
$menu_radius: 6px;
// https://gitlab.gnome.org/GNOME/libadwaita/-/blob/1.6.1/src/stylesheet/_drawing.scss
@mixin focus-ring($target: null, $width: 2px, $offset: -$width, $outer: false, $focus-state: ':focus:focus-visible', $transition: null) {
& #{$target} {
outline: 0 solid transparent;
outline-offset: if($outer, $offset + 4px, $offset + $width + 4px);
transition: $focus_transition, $transition;
}
&#{$focus-state} #{$target} {
outline-color: $focus_border_color;
outline-width: $width;
outline-offset: $offset;
}
}
Loading…
Cancel
Save