forms, fancy checkboxes, more better colors

This commit is contained in:
Luna D. 2024-05-03 20:08:52 +02:00
parent e8841d8cc4
commit 265d73cdf7
No known key found for this signature in database
GPG key ID: 4B1C63448394F688
27 changed files with 274 additions and 96 deletions

View file

@ -25,13 +25,16 @@
@import "elements/base";
@import "elements/block";
@import "elements/button";
@import "elements/checkbox";
@import "elements/dropdown";
@import "elements/flash";
@import "elements/flex";
@import "elements/form";
@import "elements/heading";
@import "elements/input";
@import "elements/interaction";
@import "elements/layout";
@import "elements/list";
@import "elements/media";
@import "elements/mobile";
@import "elements/separator";

View file

@ -32,6 +32,12 @@ $font-family-monospace: "Droid Sans Mono", monospace;
--button-group-tall-height: 2.5rem;
--button-group-small-height: 1.5rem;
--checkbox-width: 3rem;
--checkbox-height: 1.5rem;
--checkbox-border-width: 2px;
--separator-vertical-size: 1.3em;
--tag-height: 2em;
--tag-border-width: 0;
@ -41,6 +47,7 @@ $font-family-monospace: "Droid Sans Mono", monospace;
--border-radius-inner: 0.25rem;
--border-radius-tag: 0.2rem;
--border-radius-avatar: 100%;
--border-radius-checkbox: 1rem;
--media-container-width: 225px;
--media-tiny-container-width: 50px;
@ -79,4 +86,5 @@ $font-family-monospace: "Droid Sans Mono", monospace;
--narrow-layout-width: $narrow-layout-width;
--transition-animation-duration: 0.15s;
--transition-long-animation-duration: 0.3s;
}

View file

@ -30,10 +30,12 @@
}
.block {
margin-bottom: var(--padding-normal);
margin-bottom: var(--padding-large);
overflow: hidden;
}
@mixin even-odd block--alternating;
.block .block {
border-radius: var(--border-radius-inner);
}
@ -43,8 +45,18 @@
}
.block--borderless {
border: 0;
border-radius: 0;
border: 0 !important;
border-radius: 0 !important;
}
.block--borderless:first-of-type {
border-top-left-radius: var(--border-radius-outer) !important;
border-top-right-radius: var(--border-radius-outer) !important;
}
.block--borderless:last-of-type {
border-bottom-left-radius: var(--border-radius-outer) !important;
border-bottom-right-radius: var(--border-radius-outer) !important;
}
.block--borderless .block__header {
@ -52,7 +64,6 @@
}
.block__content, .block__tab {
border: 1px solid var(--primary-border-color);
border-radius: var(--border-radius-outer);
padding: var(--padding-normal);
background: var(--primary-dark-color);
@ -67,8 +78,8 @@
flex-direction: row;
background: var(--primary-muted-color);
padding: var(--padding-normal);
margin: var(--padding-normal);
margin-top: 0;
margin-top: var(--padding-normal);
border-radius: var(--border-radius-outer);
}
.block__footer--small {
@ -118,6 +129,7 @@
padding: var(--padding-normal);
border-radius: var(--border-radius-inner);
background: var(--primary-muted-color);
margin-bottom: var(--padding-normal);
}
.block__content > *:last-child, .block--fixed > *:last-child {

View file

@ -40,7 +40,7 @@
font-size: var(--font-size);
background: var(--primary-dark-color);
color: var(--text-color);
border: 1px solid var(--primary-border-color);
border: 0;
border-radius: var(--border-radius-inner);
padding: 0 var(--padding-small);
overflow: hidden;
@ -85,7 +85,7 @@
.button__group, .button__group--single, .button__group--standalone {
display: flex;
flex-direction: row;
border: 1px solid var(--secondary-color);
border: 0;
border-radius: var(--border-radius-inner);
margin-right: var(--padding-normal);
background: var(--secondary-dark-color);
@ -135,7 +135,6 @@
.block__header__buttons .button {
color: var(--link-color);
border-width: 0 !important;
background: 0;
}
.block__header__buttons .button:hover {

View file

@ -0,0 +1,44 @@
input[type=checkbox].checkbox {
appearance: none;
}
.checkbox {
display: inline-block;
align-self: center;
width: var(--checkbox-width);
height: var(--checkbox-height);
background: var(--danger-color);
border: var(--checkbox-border-width) solid var(--danger-border-color);
border-radius: var(--border-radius-checkbox);
transition: background var(--transition-long-animation-duration) ease,
border-color var(--transition-long-animation-duration) ease;
}
.checkbox::after {
content: '';
font-family: var(--fa-style-family, "Font Awesome 6 Free");
font-weight: var(--fa-style, 900);
text-align: center;
line-height: calc(var(--checkbox-height) - var(--checkbox-border-width) * 2);
display: block;
position: relative;
background: var(--text-color);
width: calc(var(--checkbox-height) - var(--checkbox-border-width) * 2);
height: calc(var(--checkbox-height) - var(--checkbox-border-width) * 2);
border-radius: 100%;
left: 0px;
transition: left var(--transition-long-animation-duration) ease;
}
.checkbox:checked {
background: var(--success-color);
border-color: var(--success-border-color);
transition: background var(--transition-long-animation-duration) ease,
border-color var(--transition-long-animation-duration) ease;
}
.checkbox:checked::after {
content: '';
left: calc(var(--checkbox-width) - var(--checkbox-height));
transition: left var(--transition-long-animation-duration) ease;
}

View file

@ -1,6 +1,6 @@
@define-mixin flash-type $type {
.flash--$(type) {
border: 1px solid var(--$(type)-border-color);
border: 0;
background: var(--$(type)-color);
}

View file

@ -0,0 +1,28 @@
form .field {
display: flex;
gap: var(--padding-normal);
margin-bottom: var(--padding-normal);
}
form .form--two_column {
display: grid;
grid: inherit;
grid-template-columns: 1 / -1;
gap: var(--padding-normal);
}
form .form--two_column > .field, form .form--two_column > li {
display: grid;
grid-template-columns: auto 1fr;
gap: var(--padding-normal);
}
form .field > .with_error {
display: block;
}
form label {
display: flex;
flex: 1 0 auto;
align-self: center;
}

View file

@ -1,12 +1,17 @@
.input {
border: 1px solid var(--secondary-border-color);
box-shadow: 0 -1px var(--secondary-dark-color) inset;
border-radius: var(--border-radius-inner);
background: var(--secondary-dark-color);
color: var(--text-color);
padding: var(--padding-small);
box-sizing: border-box;
font-family: var(--font-family-monospace);
}
.input:hover, .input:focus {
background: var(--secondary-muted-color);
}
.input:focus {
outline: none;
}
@ -24,3 +29,7 @@
padding: var(--padding-normal) var(--padding-small);
cursor: text;
}
input[type=file] {
padding-top: var(--padding-small);
}

View file

@ -0,0 +1,3 @@
ul, ol {
list-style-type: none;
}

View file

@ -23,7 +23,8 @@
.separator--vertical {
width: 1px;
height: inherit;
height: var(--separator-vertical-size);
align-self: center;
margin: 0 var(--padding-small);
background: var(--primary-border-color);
}

View file

@ -0,0 +1,27 @@
@define-mixin border-for-flash-type $type {
.flash--$(type) {
border: 1px solid var(--$(type)-border-color);
}
}
:root {
--separator-vertical-size: inherit;
}
.block__content, .block__tab {
border: 1px solid var(--primary-border-color);
}
.button {
border: 1px solid var(--primary-border-color);
}
.button__group, .button__group--single, .button__group--standalone {
border: 1px solid var(--secondary-color);
}
@mixin border-for-flash-type success;
@mixin border-for-flash-type warning;
@mixin border-for-flash-type danger;
@mixin border-for-flash-type information;
@mixin border-for-flash-type special;

View file

@ -0,0 +1,7 @@
.checkbox::after {
content: '\f00d';
}
.checkbox:checked::after {
content: '\f00c';
}

View file

@ -1,8 +1,8 @@
$background-color: #131a22;
$background-color: #0f161e;
$text-color: #e0e0e0;
$primary-color: #2e4c80;
$secondary-color: #434f69;
$primary-color: #284371;
$secondary-color: #546c99;
$danger-color: #672a21;
$warning-color: #684f2c;
$success-color: #25603e;
@ -38,27 +38,29 @@ $spoiler-color: #0f0f0f;
@define-mixin type-color $type, $color {
--$(type)-color: $color;
--$(type)-border-color: hsl(from $color h calc(s - 20) calc(l + 10));
--$(type)-dark-color: hsl(from $color h calc(s - 25) calc(l - 12));
--$(type)-muted-color: hsl(from $color h calc(s - 10) calc(l - 7));
--$(type)-dark-color: hsl(from $color h calc(s - 30) calc(l - 11));
--$(type)-link-color: hsl(from $color h calc(s + 10) calc(l + 45));
}
:root {
--background-color: $background-color;
--text-color: $text-color;
--text-light-color: $text-color;
--link-color: hsl(from $primary-color h calc(s + 7) calc(l + 35));
--link-color: hsl(from $primary-color h calc(s + 10) calc(l + 40));
--link-hover-color: $text-color;
--primary-color: $primary-color;
--primary-border-color: hsl(from $primary-color h calc(s - 20) calc(l + 10));
--primary-border-color: hsl(from $primary-color h calc(s - 20) calc(l + 5));
--primary-muted-color: hsl(from $primary-color h calc(s - 10) calc(l - 10));
--primary-dark-color: hsl(from $primary-color h calc(s - 15) calc(l - 20));
--primary-dark-color: hsl(from $primary-color h calc(s - 15) calc(l - 15));
--primary-link-color: var(--link-color); /* for consistency */
--secondary-color: $secondary-color;
--secondary-border-color: hsl(from $secondary-color h s calc(l + 10));
--secondary-muted-color: hsl(from $secondary-color h calc(s - 5) calc(l - 10));
--secondary-dark-color: hsl(from $secondary-color h s calc(l - 15));
--secondary-border-color: hsl(from $secondary-color h s calc(l + 5));
--secondary-muted-color: hsl(from $secondary-color h s calc(l - 17));
--secondary-dark-color: hsl(from $secondary-color h calc(s - 5) calc(l - 25));
--secondary-link-color: hsl(from $secondary-color h s calc(l + 55));
--upvote-color: $upvote-color;

View file

@ -1,19 +1,19 @@
$background-color: #f7f7f7;
$text-color: #171717;
$text-color: #121212;
$primary-color: #62a7d9;
$secondary-color: #c1e4f9;
$primary-color: #4b9ad3;
$secondary-color: #62a7d9;
$danger-color: #e78f82;
$warning-color: #f0c180;
$warning-color: #edb76c;
$success-color: #8de3b1;
$information-color: #90dce7;
$special-color: #dc77e9;
$upvote-color: #5b9b26;
$downvote-color: #da3412;
$fave-color: #a18e27;
$comment-color: #b099dd;
$hide-color: #da3412;
$upvote-color: #67af2b;
$downvote-color: #cf0001;
$fave-color: #c4b246;
$comment-color: #9273d0;
$hide-color: #cf0001;
$tag-default-color: #84dd96;
$tag-error-color: #eb848c;
@ -37,28 +37,30 @@ $spoiler-color: #0f0f0f;
@define-mixin type-color $type, $color {
--$(type)-color: $color;
--$(type)-border-color: hsl(from $color h calc(s - 20) calc(l - 10));
--$(type)-dark-color: hsl(from $color h calc(s - 25) calc(l + 12));
--$(type)-border-color: hsl(from $color h calc(s - 20) calc(l + 5));
--$(type)-muted-color: hsl(from $color h calc(s - 7) calc(l - 12));
--$(type)-dark-color: hsl(from $color h calc(s - 25) calc(l + 20));
--$(type)-link-color: hsl(from $color h calc(s + 50) calc(l - 47));
}
:root {
--background-color: $background-color;
--text-color: $text-color;
--text-light-color: $background-color;
--link-color: hsl(from $primary-color h calc(s + 25) calc(l - 25));
--link-hover-color: $text-color;
--primary-color: $primary-color;
--primary-border-color: hsl(from $primary-color h calc(s + 20) calc(l - 30));
--primary-muted-color: hsl(from $primary-color h calc(s + 7) calc(l + 10));
--primary-dark-color: hsl(from $primary-color h calc(s - 10) calc(l + 30));
--primary-border-color: hsl(from $primary-color h calc(s + 5) calc(l - 5));
--primary-muted-color: hsl(from $primary-color h calc(s + 7) calc(l + 20));
--primary-dark-color: hsl(from $primary-color h calc(s + 20) calc(l + 35));
--primary-link-color: var(--link-color); /* for consistency */
--secondary-color: $secondary-color;
--secondary-border-color: hsl(from $secondary-color h s calc(l - 45));
--secondary-muted-color: hsl(from $secondary-color h calc(s + 5) calc(l - 15));
--secondary-dark-color: hsl(from $secondary-color h calc(s - 5) calc(l + 5));
--secondary-muted-color: hsl(from $secondary-color h calc(s + 5) calc(l + 18));
--secondary-dark-color: hsl(from $secondary-color h calc(s - 5) calc(l + 25));
--secondary-link-color: hsl(from $secondary-color h s calc(l - 55));
--upvote-color: $upvote-color;
@ -88,3 +90,22 @@ $spoiler-color: #0f0f0f;
@mixin tag-color content-official, $tag-content-official-color;
@mixin tag-color spoiler, $tag-spoiler-color;
}
header {
/* Apparently people will put me on a cross if
I don't use Trixie colors, so here you go! */
background-color: #e2ebf2;
}
/* Sigh... my poor poor pretty CSS... */
.header__search {
background-color: var(--primary-color);
}
.header__search * {
color: var(--text-light-color) !important;
}
.header__search > .input:hover, .input:focus {
color: var(--text-color) !important;
}

View file

@ -42,7 +42,6 @@ header {
font-size: var(--font-size);
background: 0;
border: 0;
box-shadow: 0;
}
.header__input--text {
@ -74,7 +73,11 @@ nav.header__secondary {
font-size: var(--font-header-size);
gap: var(--padding-large);
align-items: center;
background: var(--primary-muted-color);
background: var(--primary-color);
}
nav.header__secondary .header__link {
color: var(--text-light-color) !important;
}
nav.dropdown__content {

View file

@ -1,4 +1,4 @@
.block__content.flex.alternating-color
.block__content.block--borderless.block--alternating.flex
.flex__shrink.spacing--right
= render PhilomenaWeb.ImageView, "_image_container.html", image: @comment.image, size: :thumb_tiny, conn: @conn
.flex__grow

View file

@ -1,4 +1,4 @@
.block__content.alternating-color
.block__content.block--borderless.block--alternating
= if @topic.sticky do
i.fa.fa-thumbtack>
= if @topic.last_post do

View file

@ -23,7 +23,7 @@
br
.field
=> checkbox f, :enabled
=> checkbox f, :enabled, class: "checkbox"
= label f, :enabled
br

View file

@ -23,7 +23,7 @@
br
.field
=> checkbox f, :enabled
=> checkbox f, :enabled, class: "checkbox"
= label f, :enabled
br

View file

@ -5,54 +5,62 @@
.block
.block__header
i.fa.fa-user
span Essential user details
label.table-list__label
.table-list__label__text Name:
.table-list__label__input
.block__content.form--two_column
.field
label Name:
.with_error
= error_tag f, :name
= text_input f, :name, class: "input"
label.table-list__label
.table-list__label__text Email:
.table-list__label__input
.field
label Email:
.with_error
= error_tag f, :email
= text_input f, :email, class: "input"
label.table-list__label
.table-list__label__text Role:
.table-list__label__input = select f, :role, ["user", "assistant", "moderator", "admin"], class: "input"
label.table-list__label
.table-list__label__text Secondary banner:
.table-list__label__input = select f, :secondary_role, [[key: "-", value: ""], "Site Developer", "Devops", "Philomena Contributor", "Public Relations"], class: "input"
label.table-list__label
.table-list__label__text Hide staff banner:
.table-list__label__input = checkbox f, :hide_default_role, class: "checkbox"
label.table-list__label
.table-list__label__text Senior staff:
.table-list__label__input = checkbox f, :senior_staff, class: "checkbox"
label.table-list__label
.table-list__label__text Bypass rate limits:
.table-list__label__input = checkbox f, :bypass_rate_limits, class: "checkbox"
.table-list__label
.table-list__label__text Avatar
.table-list__label__input
.field
label Role:
.with_error = select f, :role, ["user", "assistant", "moderator", "admin"], class: "input"
.field
label Secondary banner:
.with_error = select f, :secondary_role, [[key: "-", value: ""], "Site Developer", "Devops", "Philomena Contributor", "Public Relations"], class: "input"
.field
label Hide staff banner:
.with_error = checkbox f, :hide_default_role, class: "checkbox"
.field
label Senior staff:
.with_error = checkbox f, :senior_staff, class: "checkbox"
.field
label Bypass rate limits:
.with_error = checkbox f, :bypass_rate_limits, class: "checkbox"
.field
label Avatar
.with_error
= link "Remove avatar", to: Routes.admin_user_avatar_path(@conn, :delete, @user), class: "button", data: [method: "delete", confirm: "Are you really, really sure?"]
.block
.block__header
i.fa.fa-user-check
span General user flags
.block__content
ul
p
strong> Be careful when issuing these permissions to staff members!
| Staff members with relevant roles may have these permissions anyway. Issuing them may break things, such as tag aliasing.
ul = collection_checkboxes f, :roles, filtered_roles(general_permissions(), @roles), mapper: &checkbox_mapper/6
ul.form--two_column = collection_checkboxes f, :roles, filtered_roles(general_permissions(), @roles), mapper: &checkbox_mapper/6
.block
.block__header.warning
i.fa.fa-handshake-angle
span Special roles for assistants
ul = collection_checkboxes f, :roles, filtered_roles(assistant_permissions(), @roles), mapper: &checkbox_mapper/6
.block__content
ul.form--two_column = collection_checkboxes f, :roles, filtered_roles(assistant_permissions(), @roles), mapper: &checkbox_mapper/6
.block
.block__header.danger
i.fa.fa-gavel
span Special roles for moderators
ul = collection_checkboxes f, :roles, filtered_roles(moderator_permissions(), @roles), mapper: &checkbox_mapper/6
.block__content
ul.form--two_column = collection_checkboxes f, :roles, filtered_roles(moderator_permissions(), @roles), mapper: &checkbox_mapper/6
= submit "Save User", class: "button"

View file

@ -6,6 +6,7 @@
i.fa.fa-plus
i.fa.fa-exclamation>
span.hidden--mobile Show Deleted
.separator--vertical.separator--warning
= if del != "only" do
a.js-staff-action href=@route.(Keyword.put(@params, :del, "only")) title="Only Deleted/Merged Images"
@ -19,11 +20,15 @@
i.fa.fa-check>
span.hidden--mobile Show Non-Deleted
= if present?(del) do
.separator--vertical.separator--warning
= if present?(del) do
a.js-staff-action href=@route.(Keyword.delete(@params, :del)) title="Hide Deleted/Merged Images"
i.fa.fa-minus
i.fa.fa-exclamation>
span.hidden--mobile Hide Deleted
.separator--vertical.separator--warning
= if present?(del) and del != "deleted" do
a.js-staff-action href=@route.(Keyword.put(@params, :del, "deleted")) title="Only Deleted (Strict)"

View file

@ -5,7 +5,7 @@
' Description
= if can?(@conn, :edit_description, @image) do
.block__header__buttons
a.button.button--inline#edit-description href="#" data-click-focus="#description" data-click-hide=".image-description" data-click-show="#description-form" title="Edit description" accessKey="d"
a.button#edit-description href="#" data-click-focus="#description" data-click-hide=".image-description" data-click-show="#description-form" title="Edit description" accessKey="d"
i.fas.fa-edit>
' Edit
.block__content

View file

@ -47,14 +47,14 @@
' Sources
.block__header__buttons
a.button.button--inline#edit-source data-click-focus=".js-image-source" data-click-hide="#image-source" data-click-show="#source-form" title="Edit source" accessKey="s"
a.button#edit-source data-click-focus=".js-image-source" data-click-hide="#image-source" data-click-show="#source-form" title="Edit source" accessKey="s"
i.fas.fa-edit
= if has_sources do
' Add/Edit
- else
' Add
= if @source_change_count > 0 do
a.button.button--link.button--inline href=Routes.image_source_change_path(@conn, :index, @image) title="Source history"
a.button.button--link href=Routes.image_source_change_path(@conn, :index, @image) title="Source history"
i.fa.fa-history>
spanspan.hide-mobile> History
| (
@ -62,7 +62,7 @@
| )
= if can?(@conn, :hide, @image) and not hide_staff_tools?(@conn) do
= form_for @changeset, Routes.image_source_history_path(@conn, :delete, @image), [method: "delete"], fn _f ->
a.button.button--danger.button--inline type="submit" data-confirm="Are you really, really sure?" title="Wipe sources"
a.button.button--warning type="submit" data-confirm="Are you really, really sure?" title="Wipe sources"
i.fas.fa-eraser>
' Wipe
.block__content.flex.flex--wrap.flex--column

View file

@ -62,11 +62,11 @@
i.fas.fa-tag>
' Tags
.block__header__buttons
a.button.button--inline.js-tag-sauce-toggle#edit-tags data-click-toggle=".tagsauce, .js-imageform" data-click-focus=".js-taginput-plain:not(.hidden), .js-taginput-input" title="Edit tags" accessKey="t"
a.button.js-tag-sauce-toggle#edit-tags data-click-toggle=".tagsauce, .js-imageform" data-click-focus=".js-taginput-plain:not(.hidden), .js-taginput-input" title="Edit tags" accessKey="t"
i.fas.fa-edit>
' Edit
= if @tag_change_count > 0 do
a.button.button--link.button--inline href=Routes.image_tag_change_path(@conn, :index, @image) title="Tag history"
a.button.button--link href=Routes.image_tag_change_path(@conn, :index, @image) title="Tag history"
i.fa.fa-history>
| History (
= @tag_change_count

View file

@ -1,5 +1,5 @@
- f = assigns[:f]
- label_lext = assigns[:label] || "Anonymous"
= if @conn.assigns.current_user do
=> checkbox f, :anonymous, value: anonymous_by_default?(@conn), class: "js-preview-anonymous"
=> checkbox f, :anonymous, value: anonymous_by_default?(@conn), class: "checkbox js-preview-anonymous"
= label f, :anonymous, label_lext

View file

@ -18,7 +18,7 @@ h1 Sign in
= error_tag f, :password
.field
=> checkbox f, :remember_me
=> checkbox f, :remember_me, class: "checkbox"
= label f, :remember_me, "Remember me"
.actions

View file

@ -29,8 +29,7 @@ defmodule PhilomenaWeb.Admin.UserView do
checked: Enum.member?(Enum.map(Map.get(form.data, field), & &1.id), role.id)
)
content_tag(:li, class: "table-list__label") do
content_tag(:div) do
content_tag(:li) do
[
checkbox(form, field, input_opts),
" ",
@ -38,7 +37,6 @@ defmodule PhilomenaWeb.Admin.UserView do
]
end
end
end
def description("moderator", "Image"), do: "Manage images"
def description("moderator", "DuplicateReport"), do: "Manage duplicates"