[TWIG] Form layout is all new, since extending form_div_layout.html.twig was quite limiting

[COMPONENTS][Posting] It is now visible on Actor profiles [COMPONENTS][Search] Overall rework of search results template, there's also additional help text added [CSS] Header no longer translucent, font sizes yet more consistent, replies marker less pronounced, and font hierarchy is now applied in both weight and size
This commit is contained in:
Eliseu Amaro 2022-02-16 21:17:13 +00:00 committed by Diogo Peralta Cordeiro
parent b69f4a46c5
commit 03a475b642
No known key found for this signature in database
GPG Key ID: 18D2D35001FBFAB0
11 changed files with 800 additions and 292 deletions

View File

@ -75,7 +75,7 @@ class Posting extends Component
*/
public function onAddMainRightPanelBlock(Request $request, array &$res): bool
{
if (\is_null($user = Common::user()) || preg_match('(feed|conversation|group)', $request->get('_route')) === 0) {
if (\is_null($user = Common::user()) || preg_match('(feed|conversation|group|view)', $request->get('_route')) === 0) {
return Event::next;
}

View File

@ -10,7 +10,7 @@
{{ form_row(form.content) }}
{{ form_row(form.attachments) }}
<details class="section-details-subtitle">
<details class="section-details-subtitle frame-section">
<summary class="details-summary-subtitle">
<strong>
{{ "Additional options" | trans }}
@ -53,7 +53,7 @@
</summary>
{% for block in extra %}
<section class="posting-extra frame-section-padding">
<section class="posting-extra">
{{ block | raw }}
</section>
{% endfor %}

View File

@ -63,13 +63,22 @@ class Search extends Component
if ($add_subscribe) {
$form_definition[] = [
'title', TextType::class, ['label' => _m('Title'), 'required' => false, 'attr' => ['title' => _m('Title for this new feed in your left panel')]],
'title', TextType::class,
[
'label' => _m('Subscribe to search query'),
'help' => _m('By subscribing to a search query, a new feed link will be added to left panel\'s feed navigation menu'),
'required' => false,
'attr' => [
'title' => _m('Title for this new feed in your left panel'),
'placeholder' => _m('Input desired title...'),
],
],
];
$form_definition[] = [
'subscribe_to_search',
SubmitType::class,
[
'label' => _m('Subscribe to this search'),
'label' => _m('Subscribe'),
'attr' => [
'title' => _m('Add this search as a feed in your feeds section of the left panel'),
],

View File

@ -1,63 +1,45 @@
{% extends 'collection/notes.html.twig' %}
{% block search_query_simple %}
<section>
<h1 class="section-title">{% trans %}Search{% endtrans %}</h1>
{% block body %}
{% if error is defined %}
<label class="alert alert-danger">
{{ error.getMessage() }}
</label>
{% endif %}
<h1>{% trans %}Search{% endtrans %}</h1>
<section class="frame-section frame-section-padding">
{{ form_start(search_form) }}
{{ form_errors(search_form) }}
<div class="section-title">
{{ form_row(search_form.search_query) }}
</div>
{{ form_row(search_form.search_query) }}
{% if actor is not null %}
<details class="frame-section section-details-subtitle">
<details class="section-details-subtitle frame-section">
<summary class="details-summary-subtitle">
<strong>{% trans %}Other options{% endtrans %}</strong>
<strong>
{% trans %}Extra options{% endtrans %}
</strong>
</summary>
<div class="section-form">
<details class="section-details-subtitle">
<summary class="details-summary-subtitle">
<strong>
{% trans %}Save query as a feed{% endtrans %}
</strong>
</summary>
<div class="section-form">
{{ form_row(search_form.title) }}
{{ form_row(search_form.subscribe_to_search) }}
</div>
<hr>
</details>
{{ form_row(search_form.title) }}
{{ form_row(search_form.subscribe_to_search) }}
</div>
</details>
{% endif %}
{{ form_row(search_form.submit_search) }}
{{ form_rest(search_form) }}
{{ form_end(search_form)}}
</section>
{% endblock search_query_simple %}
<hr>
{% block search_query_advanced %}
{{ form_start(search_builder_form) }}
<details class="section-details section-details-title frame-section">
<summary class="details-summary-title">
<span>{% trans %}Advanced search{% endtrans %}</span>
</summary>
<section class="frame-section">
<details class="section-details-subtitle">
<summary class="details-summary-subtitle">
<strong>{% trans %}Build a search query{% endtrans %}</strong>
</summary>
<div class="section-form">
{{ form_start(search_builder_form) }}
{# actor options, display if first checked, with checkbox trick #}
<details class="section-details-subtitle">
<summary class="details-summary-subtitle">
<strong>{% trans %}People search options{% endtrans %}</strong>
</summary>
<div class="section-form">
<section class="frame-section-padding">
<details class="section-details-subtitle frame-section">
<summary class="details-summary-subtitle">
<strong>{% trans %}People search options{% endtrans %}</strong>
</summary>
<div class="section-form">
<div class="section-checkbox-flex">
{{ form_row(search_builder_form.include_actors) }}
{{ form_row(search_builder_form.include_actors_people) }}
{{ form_row(search_builder_form.include_actors_groups) }}
@ -65,61 +47,84 @@
{{ form_row(search_builder_form.include_actors_businesses) }}
{{ form_row(search_builder_form.include_actors_organizations) }}
{{ form_row(search_builder_form.include_actors_bots) }}
{{ form_row(search_builder_form.actor_langs) }}
{{ form_row(search_builder_form.actor_tags) }}
</div>
<hr>
</details>
{{ form_row(search_builder_form.actor_tags) }}
<hr>
{{ form_row(search_builder_form.actor_langs) }}
</div>
</details>
<details class="section-details-subtitle">
<summary class="details-summary-subtitle">
<strong>{% trans %}Note search options{% endtrans %}</strong>
</summary>
<div class="section-form">
<details class="section-details-subtitle frame-section">
<summary class="details-summary-subtitle">
<strong>{% trans %}Note search options{% endtrans %}</strong>
</summary>
<div class="section-form">
<div class="section-checkbox-flex">
{{ form_row(search_builder_form.include_notes) }}
{{ form_row(search_builder_form.include_notes_text) }}
{{ form_row(search_builder_form.include_notes_media) }}
{{ form_row(search_builder_form.include_notes_polls) }}
{{ form_row(search_builder_form.include_notes_bookmarks) }}
{{ form_row(search_builder_form.note_langs) }}
{{ form_row(search_builder_form.note_tags) }}
{{ form_row(search_builder_form.note_actor_langs) }}
{{ form_row(search_builder_form.note_actor_tags) }}
</div>
<hr>
</details>
{{ form_rest(search_builder_form) }}
{{ form_end(search_builder_form) }}
</div>
</details>
{{ form_row(search_builder_form.note_tags) }}
<hr>
{{ form_row(search_builder_form.note_langs) }}
<hr>
{{ form_row(search_builder_form.note_actor_tags) }}
<hr>
{{ form_row(search_builder_form.note_actor_langs) }}
</div>
</details>
{{ form_rest(search_builder_form) }}
</section>
</details>
{{ form_end(search_builder_form) }}
{% endblock search_query_advanced %}
{% block search %}
<section class="frame-section frame-section-padding">
{% if error is defined %}
<label class="alert alert-danger">
{{ error.getMessage() }}
</label>
{% endif %}
{{ block('search_query_simple') }}
<hr>
{{ block('search_query_advanced') }}
</section>
</section>
{% endblock search %}
<section class="frame-section frame-section-padding">
<h2>{% trans %}Results{% endtrans %}</h2>
<div class="frame-section frame-section-padding feed-empty">
{% if notes is defined and notes is not empty %}
{{ parent() }}
{% else %}
<h3>{% trans %}No notes found{% endtrans %}</h3>
<em>{% trans %}No notes were found for the specified query...{% endtrans %}</em>
{% endif %}
{% block body %}
{{ block('search') }}
<div class="frame-section frame-section-padding">
<h1 class="section-title">{% trans %}Results{% endtrans %}</h1>
<section>
{% if notes is defined and notes is not empty %}
{{ parent() }}
{% else %}
<h3>{% trans %}No notes found{% endtrans %}</h3>
<em>{% trans %}No notes were found for the specified query...{% endtrans %}</em>
{% endif %}
</section>
<hr>
<section>
<h3>{% trans %}Actors found{% endtrans %}</h3>
{% if actors is defined and actors is not empty %}
{% for actor in actors %}
{% include 'cards/blocks/profile.html.twig' with {'actor': actor} %}
{% endfor %}
{% else %}
<em>{% trans %}No Actors were found for the specified query...{% endtrans %}</em>
{% endif %}
</section>
<div class="frame-section-button-like">
{{ "Page: " ~ page }}
</div>
</div>
<div class="frame-section frame-section-padding feed-empty">
<h3>{% trans %}Actors found{% endtrans %}</h3>
{% if actors is defined and actors is not empty %}
{% for actor in actors %}
{% include 'cards/blocks/profile.html.twig' with {'actor': actor} %}
{% endfor %}
{% else %}
<em>{% trans %}No Actors were found for the specified query...{% endtrans %}</em>
{% endif %}
</div>
</section>
<div class="frame-section-button-like">
{{ "Page: " ~ page }}
</div>
{% endblock body %}

View File

@ -1,15 +1,17 @@
@import url(root.css);
@import url(reset.css);
@import url(widgets/buttons.css);
@import url(widgets/sections.css);
html {
font-family: 'Open Sans', sans-serif;
font-family: 'Open Sans',sans-serif;
scroll-margin-top: var(--xxl);
}
html,
html > * {
html,html>* {
background-image: url('images/noise.png');
background-blend-mode: overlay;
}
@ -27,7 +29,7 @@ hr {
}
.active {
font: 600 1em Poppins, sans-serif;
font: 600 1em Poppins,sans-serif;
}
.anchor-hidden {
@ -61,8 +63,9 @@ hr {
}
.page-header {
width: 100%;
align-items: center;
background: var(--gradient) !important;
background: var(--background-hard);
box-shadow: var(--shadow);
display: flex;
height: var(--xxl);
@ -138,7 +141,7 @@ hr {
right: 0;
}
.panel-left-icon, .panel-right-icon {
.panel-left-icon,.panel-right-icon {
display: inherit;
}
@ -148,11 +151,13 @@ hr {
overflow: auto;
}
@media only screen and (max-width: 512px) {
html {font-size: 75%;} /*12px*/
@media only screen and (max-width:512px) {
html {
font-size: 85%;
}
}
@media only screen and (max-width: 1280px) {
@media only screen and (max-width:1280px) {
.page-header {
width: 100%;
}
@ -174,11 +179,11 @@ hr {
top: -100%;
}
#toggle-panel-left:not(:checked) ~ .section-panel-left, #toggle-panel-right:not(:checked) ~ .section-panel-right {
#toggle-panel-left:not(:checked) ~ .section-panel-left,#toggle-panel-right:not(:checked) ~ .section-panel-right {
display: none;
}
#toggle-panel-left:checked ~ .section-panel-left, #toggle-panel-right:checked ~ .section-panel-right {
#toggle-panel-left:checked ~ .section-panel-left,#toggle-panel-right:checked ~ .section-panel-right {
left: 0;
width: 100vw;
z-index: auto;
@ -187,12 +192,12 @@ hr {
}
}
@media only screen and (min-width: 1281px) {
@media only screen and (min-width:1281px) {
.page-header {
width: 100%;
}
label[for|="toggle-panel"], input[id|="toggle-panel"] {
label[for|="toggle-panel"],input[id|="toggle-panel"] {
display: none !important;
}
@ -204,20 +209,20 @@ hr {
width: 66vw;
}
a[id|="anchor"]:target + .accessibility-target {
a[id|="anchor"]:target+.accessibility-target {
animation-duration: 600ms;
animation-name: highlight;
animation-timing-function: ease-in-out;
}
}
@media only screen and (min-width: 1921px) {
@media only screen and (min-width:1921px) {
.page-header {
align-self: center;
width: 66vw;
}
label[for|="toggle-panel"], input[id|="toggle-panel"] {
label[for|="toggle-panel"],input[id|="toggle-panel"] {
display: none !important;
}
@ -243,6 +248,7 @@ hr {
opacity: 0;
transform: translateY(-10px);
}
100% {
opacity: unset;
transform: none;
@ -254,6 +260,7 @@ hr {
opacity: 0;
transform: translateY(-10px);
}
0% {
opacity: unset;
transform: none;
@ -265,27 +272,32 @@ hr {
border-radius: var(--s);
box-shadow: initial;
}
50% {
border-radius: var(--s);
box-shadow: inset 0 20px 40px #FFF;
transition: box-shadow .3s ease-in-out;
z-index: 666;
}
100% {
border-radius: var(--s);
box-shadow: initial;
}
0% {
border-radius: var(--s);
box-shadow: initial;
}
50% {
border-radius: var(--s);
box-shadow: inset 0 20px 40px #000;
transition: box-shadow .3s ease-in-out;
}
100% {
border-radius: var(--s);
box-shadow: initial;
}
}
}

View File

@ -1,5 +1,3 @@
.favourite-button-container {
-moz-mask-image: url("../icons/heart.svg");
-o-mask-image: url("../icons/heart.svg");
@ -56,9 +54,8 @@
padding: var(--s);
}
.embed .p-author,
.embed .p-name {
font-weight: 700;
.embed .p-author,.embed .p-name {
font-weight: 600;
}
.embed .p-summary {
@ -87,26 +84,19 @@
padding: unset;
}
.feed-header > h1,
.feed-header > h2,
.feed-header > h3,
.feed-header > h4,
.feed-header > h5,
.feed-header > h6 {
.feed-header>h1,.feed-header>h2,.feed-header>h3,.feed-header>h4,.feed-header>h5,.feed-header>h6 {
margin-bottom: unset;
}
.feed-actions-details summary,
.note-actions-extra-details summary {
.feed-actions-details summary,.note-actions-extra-details summary {
display: block;
}
.feed-actions-details-dropdown {
font-size: 0.937rem;
font-size: .937rem;
}
.feed-actions-details[open]>.feed-actions-details-dropdown,
.note-actions-extra-details[open]>summary+* {
.feed-actions-details[open]>.feed-actions-details-dropdown,.note-actions-extra-details[open]>summary+* {
background: var(--background-card);
border: 1px solid var(--border);
border-radius: var(--s);
@ -120,8 +110,7 @@
z-index: 1;
}
.feed-actions-details[open]>summary,
.note-actions-extra-details[open]>summary {
.feed-actions-details[open]>summary,.note-actions-extra-details[open]>summary {
opacity: 1 !important;
}
@ -170,39 +159,35 @@
}
.note-replies-indicator {
font-size: 32px;
opacity: 0.66;
opacity: .66;
margin-right: 8px;
float: left;
}
.note-replies-indicator::before {
content: '\201C';
font-size: 1em;
opacity: 0.66;
margin-right: 0.33em;
font-size: 1.5em;
opacity: .66;
}
.note-replies-parent {
opacity: 0.66;
font-size: 0.937rem;
opacity: .66;
font-size: .937rem;
}
.h-entry a:focus {
text-decoration: underline;
}
.h-entry figure,
.note-attachments-unit figure {
.h-entry figure,.note-attachments-unit figure {
background: var(--gradient);
border-radius: var(--s);
margin: unset;
padding: var(--s);
}
.h-entry img,
.note-attachments-unit figure img {
background: repeating-conic-gradient(#ffffff66 0deg 90deg, #ffffff33 0deg 180deg) 0 0/40px 40px round;
.h-entry img,.note-attachments-unit figure img {
background: repeating-conic-gradient(#ffffff66 0 90deg,#ffffff33 0 180deg) 0 0/40px 40px round;
}
.h-entry-language {
@ -248,8 +233,7 @@
margin-right: var(--s);
}
.note-info,
embed header {
.note-info,embed header {
border-bottom: unset;
border-radius: 0 var(--s) 0 0;
display: flex;
@ -259,28 +243,26 @@ embed header {
.note-info {
display: flex;
align-items: flex-start;
align-items: center;
white-space: nowrap;
overflow: auto;
touch-action: manipulation;
text-overflow: ellipsis;
}
.note-info .note-conversation-info,
.note-info .note-author-uri {
.note-info .note-conversation-info,.note-info .note-author-uri {
margin-left: 4px;
}
.note-info small {
opacity: 0.5;
opacity: .5;
}
.note-author-url {
font-weight: 700;
font-weight: 600;
}
.note-author-uri,
.note-conversation-info {
.note-author-uri,.note-conversation-info {
font-style: italic;
}
@ -307,11 +289,11 @@ embed header {
}
.note-actions-extra-details summary {
opacity: 0.5;
opacity: .5;
}
.note-actions-extra-details[open]>summary+*>a {
font-size: 0.937rem;
font-size: .937rem;
line-height: 2;
}
@ -327,19 +309,18 @@ embed header {
width: 100%;
display: flex;
flex-wrap: wrap;
font-size: 0.937rem;
font-size: .937rem;
background: var(--gradient-backwards);
padding: 4px 8px;
border-radius: var(--s) 0 var(--s) var(--s);
}
.note-complementary:empty,
.note-complementary:-moz-only-whitespace {
.note-complementary:empty,.note-complementary:-moz-only-whitespace {
display: none !important;
}
.note-complementary-info a {
font-weight: 700;
font-weight: 600;
}
.note-complementary-info span {
@ -350,14 +331,11 @@ embed header {
.note-content {
border-radius: 0 0 var(--s) var(--s);
display: block;
padding: 0 0 8px 0;
flex: 1;
}
.note-replies-start {
font-size: 0.937rem;
font-weight: 700;
opacity: 0.5;
opacity: .5;
}
.hr-replies-end {
@ -365,6 +343,10 @@ embed header {
margin-bottom: var(--xl);
}
.hr-replies-end:last-of-type {
display: none;
}
.note-sidebar {
display: flex;
flex-direction: column;
@ -387,12 +369,6 @@ embed header {
text-decoration: underline !important;
}
.note-text p:not(:last-of-type) {
display: block;
margin-bottom: var(--s);
width: 100%;
}
.note-text-details-summary:after {
content: "\2193";
}
@ -416,8 +392,9 @@ embed header {
}
.posting-extra .h-entry {
padding-left: var(--s);
padding-right: var(--s);
padding: var(--s);
border: unset;
border-bottom: 1px solid var(--border);
}
.posting-extra .note-sidebar {
@ -432,22 +409,22 @@ embed header {
margin-right: 4px;
}
@media only screen and (max-width: 1280px) {
@media only screen and (max-width:1280px) {
.note-sidebar {
max-width: min-content !important;
}
.note-sidebar .avatar {
min-width: var(--xl) !important;
}
.note-replies .note-replies {
margin-left: 0.33em;
margin-left: .33em;
}
.note-replies-indicator::before {
content: '\201C';
font-size: 1em;
opacity: 0.66;
margin-right: 0.33em;
opacity: .66;
}
}
}

View File

@ -3,24 +3,24 @@
max-width: 100%;
}
body, html {
body,html {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
background-attachment: fixed;
background-color: var(--background-hard);
display: flex;
flex-direction: column;
font-family: "var(--unit) 'Open Sans'", sans-serif;
font-family: "var(--unit) 'Open Sans'",sans-serif;
font-style: normal;
font-variant: normal;
font-weight: normal;
}
body, input, select, textarea {
body,input,select,textarea {
color: var(--foreground);
}
:link, :visited {
:link,:visited {
color: currentColor;
text-decoration: none;
}
@ -32,13 +32,13 @@ hr {
height: 1px;
}
menu, ul {
menu,ul {
list-style: none;
margin: unset;
padding: unset;
}
blockquote, body, fieldset, form, html, input, pre, textarea {
blockquote,body,fieldset,form,html,input,pre,textarea {
border: 0;
margin: 0;
padding: 0;
@ -48,7 +48,7 @@ fieldset {
all: unset;
}
:link img, :visited img, a img {
:link img,:visited img,a img {
border: 0;
}
@ -68,16 +68,16 @@ details summary {
cursor: pointer !important;
}
details summary > * {
details summary>* {
margin: unset;
padding: unset;
}
details > summary {
details>summary {
list-style: none;
}
details > summary::-webkit-details-marker {
details>summary::-webkit-details-marker {
display: none;
}
@ -85,53 +85,67 @@ details > summary::-webkit-details-marker {
display: none;
}
html {font-size: 100%;} /*12px*/
html {
font-size: 100%;
}
body {
font-family: 'Open Sans', sans-serif;
font-family: 'Open Sans',sans-serif;
font-weight: 400;
line-height: 1.75;
}
p {
all: unset;
font-family: 'Open Sans', sans-serif;
margin-bottom: 1rem;
margin-top: 4px;
margin-bottom: 4px;
}
h1:first-child, h2:first-child, h3:first-child, h4:first-child, h5:first-child, legend:first-child {
margin-top: initial;
}
h1, h2, h3, h4, h5 {
h1,h2,h3,h4,h5 {
margin: 3rem 0 1.38rem;
font-family: 'Poppins', sans-serif;
font-weight: 900;
font-family: 'Poppins',sans-serif;
line-height: 1.3;
}
h1:first-child,h2:first-child,h3:first-child,h4:first-child,h5:first-child,legend:first-child {
margin-top: initial;
}
h1 {
margin-top: 0;
font-size: 1.383rem;
font-weight: 900;
}
h2 {font-size: 1.296rem;}
h3 {font-size: 1.215rem;}
h4 {font-size: 1.138rem;}
h5 {font-size: 1.067rem;}
small, .text_small {font-size: 0.937rem;}
legend {
font-size: 1.25rem;
h2 {
font-size: 1.296rem;
font-weight: 700;
}
input[type=password], input[type=text], textarea {
font-family: 'Open Sans', sans-serif;
font-weight: 400;
h3 {
font-size: 1.215rem;
font-weight: 600;
}
h4 {
font-size: 1.138rem;
font-weight: 600;
}
h5 {
font-size: 1.067rem;
font-weight: 600;
}
small,.text_small {
font-size: .937rem;
}
legend,label {
font-size: 1.067rem;
font-weight: 600;
}
input[type=password],input[type=text],textarea {
padding: 6px 8px;
}
@ -147,7 +161,7 @@ li {
padding: 0;
}
a:focus, a:hover {
a:focus,a:hover {
text-decoration: underline;
}

View File

@ -1,8 +1,4 @@
label {
font-weight: 900;
}
input + label {
input+label {
margin-left: 3px;
}
@ -11,7 +7,7 @@ input[type=file] {
background: var(--gradient) !important;
border-radius: var(--s);
display: block;
font-family: 'Open Sans', sans-serif !important;
font-family: 'Open Sans',sans-serif !important;
font-weight: 400 !important;
padding: unset !important;
}
@ -22,7 +18,7 @@ input[type=file] {
color: var(--foreground);
cursor: pointer;
fill: var(--foreground);
font-family: 'Open Sans', sans-serif !important;
font-family: 'Open Sans',sans-serif !important;
font-weight: 900 !important;
margin: 3px;
}
@ -31,33 +27,13 @@ input[type=file] {
all: unset !important;
}
button {
cursor: pointer !important;
display: block !important;
margin-left: auto !important;
margin-top: var(--s);
}
.alert button {
border-color: #ff6347 !important;
cursor: pointer !important;
margin-top: unset !important;
}
button, label {
color: currentColor;
}
button {
font-family: 'Poppins', sans-serif;
font-weight: 900 !important;
}
select::-ms-expand {
display: none;
}
button, input, select, textarea {
font-size: inherit;
button,input,select,textarea {
font-family: 'Open Sans',sans-serif !important;
font-size: 1rem;
border: 1px solid var(--border) !important;
border-radius: var(--s);
max-width: border-box;
@ -66,16 +42,36 @@ button, input, select, textarea {
width: auto;
}
button, select, textarea {
button,select,textarea {
background: var(--gradient) !important;
}
button, input {
button,input {
background: var(--gradient) !important;
}
input[type=radio],
input[type=checkbox] {
button {
cursor: pointer !important;
display: block !important;
margin-left: auto !important;
}
.alert button {
border-color: #ff6347 !important;
cursor: pointer !important;
margin-top: unset !important;
}
button,label {
color: currentColor;
}
button {
font-family: 'Poppins',sans-serif !important;
font-weight: 900 !important;
}
input[type=radio],input[type=checkbox] {
background: initial;
}
@ -87,39 +83,37 @@ select {
}
select[multiple] {
height: 20rem;
height: 8rem;
overflow-y: scroll;
}
button:focus, button:hover, input:focus, input:hover, select:focus, select:hover, textarea:focus, textarea:hover {
button:focus,button:hover,input:focus,input:hover,select:focus,select:hover,textarea:focus,textarea:hover {
box-shadow: var(--shadow-inset-accent);
}
input[type=color] {
appearance: none;
background-color: transparent;
border: none;
border: 0;
cursor: pointer;
height: var(--xxl);
width: var(--xxl);
}
input[type=color]::-webkit-color-swatch {
border: none;
border: 0;
border-radius: var(--s);
}
input[type=color]::-moz-color-swatch {
border: none;
border: 0;
border-radius: var(--s);
}
input[type=checkbox]:focus,
input[type=checkbox]:hover {
input[type=checkbox]:focus,input[type=checkbox]:hover {
outline: 2px solid var(--accent);
}
input[type=checkbox]
{
input[type=checkbox] {
accent-color: var(--accent);
}

View File

@ -5,7 +5,7 @@
mask-image: url(../icons/add-actor.svg);
}
.alert, .alert-danger, .form-error, .form-row-widget-error {
.alert,.alert-danger,.form-error,.form-row-widget-error {
align-items: center;
background-color: #FF634733;
border: solid 2px #ff6347;
@ -39,7 +39,7 @@
opacity: .33;
}
.button-container:focus, .button-container:hover {
.button-container:focus,.button-container:hover {
background-color: var(--accent);
border: none !important;
mask-repeat: no-repeat !important;
@ -58,20 +58,20 @@
.container-grid {
display: grid;
gap: var(--s);
grid-template-columns:repeat(auto-fit, minmax(200px, 1fr));
grid-template-columns: repeat(auto-fit,minmax(200px,1fr));
}
.details-subtitle-summary + * {
.details-subtitle-summary+* {
background: var(--gradient);
border-radius: var(--s);
padding: 2px 8px;
}
.details-subtitle-summary a, .details-title-summary a {
.details-subtitle-summary a,.details-title-summary a {
line-height: initial;
}
.details-subtitle-summary svg:last-child, .details-title-summary svg:last-child {
.details-subtitle-summary svg:last-child,.details-title-summary svg:last-child {
margin-left: 4px;
}
@ -110,18 +110,18 @@
padding: unset !important;
}
.form-search .form-row {
margin-bottom: unset;
width: 100%;
}
.form-search label {
.form-search span label {
display: block;
height: 0;
opacity: 0;
width: 0;
}
.form-search span .form-row {
margin-bottom: unset;
flex: 2;
}
.form-search span {
display: inline-flex;
width: 100%;
@ -133,6 +133,7 @@
border-top-left-radius: 0;
height: 100%;
margin: unset;
flex: 1;
}
.form-search span input[type='text'] {
@ -149,7 +150,7 @@
box-shadow: var(--shadow);
display: flex;
flex-direction: column;
margin-bottom: var(--m);
margin-bottom: var(--s);
}
.frame-section hr {
@ -162,7 +163,7 @@
border: 1px solid var(--border);
border-radius: var(--s);
display: block;
font-family: 'Poppins', sans-serif;
font-family: 'Poppins',sans-serif;
font-weight: 900;
padding: 6px 8px;
width: max-content;
@ -174,7 +175,7 @@
.frame-section-paging {
display: block;
font-family: 'Poppins', sans-serif;
font-family: 'Poppins',sans-serif;
font-weight: 900;
margin-left: auto;
margin-top: var(--s);
@ -189,7 +190,7 @@
background: var(--gradient) !important;
border: 1px solid var(--border);
border-radius: var(--s);
font-family: 'Open Sans', sans-serif;
font-family: 'Open Sans',sans-serif;
margin-bottom: var(--s);
padding: var(--unit);
}
@ -205,12 +206,12 @@
margin-top: 4px;
}
.profile-bio, .profile-info-url {
.profile-bio,.profile-info-url {
word-break: break-all;
}
.profile-extra-actions {
background: var(--gradient), var(--background-hard);
background: var(--gradient),var(--background-hard);
border: 1px solid var(--border);
border-radius: var(--s);
display: inline-block;
@ -237,7 +238,7 @@
display: block;
}
.profile-info-url > * {
.profile-info-url>* {
display: block;
}
@ -250,7 +251,7 @@
opacity: .66;
}
.profile-navigation > * {
.profile-navigation>* {
display: block;
}
@ -261,11 +262,11 @@
text-align: right;
}
.profile-stats-subscribers strong, .profile-stats-subscriptions strong {
.profile-stats-subscribers strong,.profile-stats-subscriptions strong {
margin-right: 4px;
}
.profile-stats-subscribers, .profile-stats-subscriptions {
.profile-stats-subscribers,.profile-stats-subscriptions {
display: block;
}
@ -280,6 +281,10 @@
mask-image: url(../icons/remove-actor.svg);
}
section {
margin-bottom: var(--s);
}
.section-details-subtitle .section-details-subtitle:not(:last-of-type) {
margin-bottom: var(--s);
}
@ -288,28 +293,24 @@
padding: 2px 8px;
}
.section-details-subtitle summary > *, .section-details-title summary > * {
.section-details-subtitle summary>*,.section-details-title summary>* {
display: inline-flex;
vertical-align: middle;
}
.section-details-subtitle summary > :last-child, .section-details-title summary > :last-child {
.section-details-subtitle summary>:last-child,.section-details-title summary>:last-child {
margin-right: 4px;
}
.section-details-subtitle summary, .section-details-title summary {
.section-details-subtitle summary,.section-details-title summary {
background: var(--gradient);
border-radius: var(--s);
display: inline-block;
width: 100%;
}
.section-details-title summary {
border-bottom: 1px solid var(--border);
}
.section-details-subtitle summary {
border: 1px solid var(--border);
.section-details-subtitle:not(:last-of-type) {
margin-bottom: var(--s);
}
.details-summary-title {
@ -318,6 +319,7 @@
font-weight: 900;
padding: 6px 8px;
}
.details-summary-subtitle {
font-size: 1em;
font-weight: bold;
@ -334,6 +336,7 @@
position: relative;
float: right;
}
.details-summary-subtitle:after {
content: "\2191";
display: block;
@ -341,23 +344,23 @@
float: right;
}
.section-details-subtitle:not([open]) > .details-summary-subtitle:after {
animation: fadeOut 200ms cubic-bezier(0, 0.55, 0.45, 1);
.section-details-subtitle:not([open])>.details-summary-subtitle:after {
animation: fadeOut 200ms cubic-bezier(0,0.55,0.45,1);
content: "\2193";
}
.section-details-subtitle[open] > .details-summary-subtitle:after {
animation: fadeIn 200ms cubic-bezier(0, 0.55, 0.45, 1);
.section-details-subtitle[open]>.details-summary-subtitle:after {
animation: fadeIn 200ms cubic-bezier(0,0.55,0.45,1);
transform: initial;
}
.section-details-title:not([open]) > .details-summary-title:after {
animation: fadeIn 200ms cubic-bezier(0, 0.55, 0.45, 1);
.section-details-title:not([open])>.details-summary-title:after {
animation: fadeIn 200ms cubic-bezier(0,0.55,0.45,1);
transform: initial;
}
.section-details-title[open] > .details-summary-title:after {
animation: fadeOut 200ms cubic-bezier(0, 0.55, 0.45, 1);
.section-details-title[open]>.details-summary-title:after {
animation: fadeOut 200ms cubic-bezier(0,0.55,0.45,1);
content: "\2191";
}
@ -377,7 +380,17 @@
}
.section-title {
margin-bottom: unset;
margin: 0 0 1.38rem;
}
.section-checkbox-flex {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
}
.section-checkbox-flex>* {
margin-right: var(--m);
}
textarea.form-row-widget {

View File

@ -0,0 +1,475 @@
{# Widgets #}
{%- block form_widget -%}
{% if compound %}
{{- block('form_widget_compound') -}}
{% else %}
{{- block('form_widget_simple') -}}
{% endif %}
{%- endblock form_widget -%}
{%- block form_widget_simple -%}
{%- set type = type|default('text') -%}
{%- if type == 'range' or type == 'color' -%}
{# Attribute "required" is not supported #}
{%- set required = false -%}
{%- endif -%}
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{%- endblock form_widget_simple -%}
{%- block form_widget_compound -%}
<div {{ block('widget_container_attributes') }}>
{%- if form is rootform -%}
{{ form_errors(form) }}
{%- endif -%}
{{- block('form_rows') -}}
{{- form_rest(form) -}}
</div>
{%- endblock form_widget_compound -%}
{%- block collection_widget -%}
{% if prototype is defined and not prototype.rendered %}
{%- set attr = attr|merge({'data-prototype': form_row(prototype) }) -%}
{% endif %}
{{- block('form_widget') -}}
{%- endblock collection_widget -%}
{%- block textarea_widget -%}
<textarea {{ block('widget_attributes') }}>{{ value }}</textarea>
{%- endblock textarea_widget -%}
{%- block choice_widget -%}
{% if expanded %}
{{- block('choice_widget_expanded') -}}
{% else %}
{{- block('choice_widget_collapsed') -}}
{% endif %}
{%- endblock choice_widget -%}
{%- block choice_widget_expanded -%}
<div {{ block('widget_container_attributes') }}>
{%- for child in form %}
{{- form_widget(child) -}}
{{- form_label(child, null, {translation_domain: choice_translation_domain}) -}}
{% endfor -%}
</div>
{%- endblock choice_widget_expanded -%}
{%- block choice_widget_collapsed -%}
{%- if required and placeholder is none and not placeholder_in_choices and not multiple and (attr.size is not defined or attr.size <= 1) -%}
{% set required = false %}
{%- endif -%}
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
{%- if placeholder is not none -%}
<option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ placeholder != '' ? (translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain)) }}</option>
{%- endif -%}
{%- if preferred_choices|length > 0 -%}
{% set options = preferred_choices %}
{% set render_preferred_choices = true %}
{{- block('choice_widget_options') -}}
{%- if choices|length > 0 and separator is not none -%}
<option disabled="disabled">{{ separator }}</option>
{%- endif -%}
{%- endif -%}
{%- set options = choices -%}
{%- set render_preferred_choices = false -%}
{{- block('choice_widget_options') -}}
</select>
{%- endblock choice_widget_collapsed -%}
{%- block choice_widget_options -%}
{% for group_label, choice in options %}
{%- if choice is iterable -%}
<optgroup label="{{ choice_translation_domain is same as(false) ? group_label : group_label|trans({}, choice_translation_domain) }}">
{% set options = choice %}
{{- block('choice_widget_options') -}}
</optgroup>
{%- else -%}
<option value="{{ choice.value }}"{% if choice.attr %}{% with { attr: choice.attr } %}{{ block('attributes') }}{% endwith %}{% endif %}{% if not render_preferred_choices|default(false) and choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans(choice.labelTranslationParameters, choice_translation_domain) }}</option>
{%- endif -%}
{% endfor %}
{%- endblock choice_widget_options -%}
{%- block checkbox_widget -%}
<input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
{%- endblock checkbox_widget -%}
{%- block radio_widget -%}
<input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
{%- endblock radio_widget -%}
{%- block datetime_widget -%}
{% if widget == 'single_text' %}
{{- block('form_widget_simple') -}}
{%- else -%}
<div {{ block('widget_container_attributes') }}>
{{- form_errors(form.date) -}}
{{- form_errors(form.time) -}}
{{- form_widget(form.date) -}}
{{- form_widget(form.time) -}}
</div>
{%- endif -%}
{%- endblock datetime_widget -%}
{%- block date_widget -%}
{%- if widget == 'single_text' -%}
{{ block('form_widget_simple') }}
{%- else -%}
<div {{ block('widget_container_attributes') }}>
{{- date_pattern|replace({
'{{ year }}': form_widget(form.year),
'{{ month }}': form_widget(form.month),
'{{ day }}': form_widget(form.day),
})|raw -}}
</div>
{%- endif -%}
{%- endblock date_widget -%}
{%- block time_widget -%}
{%- if widget == 'single_text' -%}
{{ block('form_widget_simple') }}
{%- else -%}
{%- set vars = widget == 'text' ? { 'attr': { 'size': 1 }} : {} -%}
<div {{ block('widget_container_attributes') }}>
{{ form_widget(form.hour, vars) }}{% if with_minutes %}:{{ form_widget(form.minute, vars) }}{% endif %}{% if with_seconds %}:{{ form_widget(form.second, vars) }}{% endif %}
</div>
{%- endif -%}
{%- endblock time_widget -%}
{%- block dateinterval_widget -%}
{%- if widget == 'single_text' -%}
{{- block('form_widget_simple') -}}
{%- else -%}
<div {{ block('widget_container_attributes') }}>
{{- form_errors(form) -}}
<table class="{{ table_class|default('') }}" role="presentation">
<thead>
<tr>
{%- if with_years %}<th>{{ form_label(form.years) }}</th>{% endif -%}
{%- if with_months %}<th>{{ form_label(form.months) }}</th>{% endif -%}
{%- if with_weeks %}<th>{{ form_label(form.weeks) }}</th>{% endif -%}
{%- if with_days %}<th>{{ form_label(form.days) }}</th>{% endif -%}
{%- if with_hours %}<th>{{ form_label(form.hours) }}</th>{% endif -%}
{%- if with_minutes %}<th>{{ form_label(form.minutes) }}</th>{% endif -%}
{%- if with_seconds %}<th>{{ form_label(form.seconds) }}</th>{% endif -%}
</tr>
</thead>
<tbody>
<tr>
{%- if with_years %}<td>{{ form_widget(form.years) }}</td>{% endif -%}
{%- if with_months %}<td>{{ form_widget(form.months) }}</td>{% endif -%}
{%- if with_weeks %}<td>{{ form_widget(form.weeks) }}</td>{% endif -%}
{%- if with_days %}<td>{{ form_widget(form.days) }}</td>{% endif -%}
{%- if with_hours %}<td>{{ form_widget(form.hours) }}</td>{% endif -%}
{%- if with_minutes %}<td>{{ form_widget(form.minutes) }}</td>{% endif -%}
{%- if with_seconds %}<td>{{ form_widget(form.seconds) }}</td>{% endif -%}
</tr>
</tbody>
</table>
{%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%}
</div>
{%- endif -%}
{%- endblock dateinterval_widget -%}
{%- block number_widget -%}
{# type="number" doesn't work with floats in localized formats #}
{%- set type = type|default('text') -%}
{{ block('form_widget_simple') }}
{%- endblock number_widget -%}
{%- block integer_widget -%}
{%- set type = type|default('number') -%}
{{ block('form_widget_simple') }}
{%- endblock integer_widget -%}
{%- block money_widget -%}
{{ money_pattern|form_encode_currency(block('form_widget_simple')) }}
{%- endblock money_widget -%}
{%- block url_widget -%}
{%- set type = type|default('url') -%}
{{ block('form_widget_simple') }}
{%- endblock url_widget -%}
{%- block search_widget -%}
{%- set type = type|default('search') -%}
{{ block('form_widget_simple') }}
{%- endblock search_widget -%}
{%- block percent_widget -%}
{%- set type = type|default('text') -%}
{{ block('form_widget_simple') }}{% if symbol %} {{ symbol|default('%') }}{% endif %}
{%- endblock percent_widget -%}
{%- block password_widget -%}
{%- set type = type|default('password') -%}
{{ block('form_widget_simple') }}
{%- endblock password_widget -%}
{%- block hidden_widget -%}
{%- set type = type|default('hidden') -%}
{{ block('form_widget_simple') }}
{%- endblock hidden_widget -%}
{%- block email_widget -%}
{%- set type = type|default('email') -%}
{{ block('form_widget_simple') }}
{%- endblock email_widget -%}
{%- block range_widget -%}
{% set type = type|default('range') %}
{{- block('form_widget_simple') -}}
{%- endblock range_widget %}
{%- block button_widget -%}
{%- if label is empty -%}
{%- if label_format is not empty -%}
{% set label = label_format|replace({
'%name%': name,
'%id%': id,
}) %}
{%- elseif label is not same as(false) -%}
{% set label = name|humanize %}
{%- endif -%}
{%- endif -%}
<button type="{{ type|default('button') }}" {{ block('button_attributes') }}>
{%- if translation_domain is same as(false) -%}
{%- if label_html is same as(false) -%}
{{- label -}}
{%- else -%}
{{- label|raw -}}
{%- endif -%}
{%- else -%}
{%- if label_html is same as(false) -%}
{{- label|trans(label_translation_parameters, translation_domain) -}}
{%- else -%}
{{- label|trans(label_translation_parameters, translation_domain)|raw -}}
{%- endif -%}
{%- endif -%}
</button>
{%- endblock button_widget -%}
{%- block submit_widget -%}
{%- set type = type|default('submit') -%}
{{ block('button_widget') }}
{%- endblock submit_widget -%}
{%- block reset_widget -%}
{%- set type = type|default('reset') -%}
{{ block('button_widget') }}
{%- endblock reset_widget -%}
{%- block tel_widget -%}
{%- set type = type|default('tel') -%}
{{ block('form_widget_simple') }}
{%- endblock tel_widget -%}
{%- block color_widget -%}
{%- set type = type|default('color') -%}
{{ block('form_widget_simple') }}
{%- endblock color_widget -%}
{%- block week_widget -%}
{%- if widget == 'single_text' -%}
{{ block('form_widget_simple') }}
{%- else -%}
{%- set vars = widget == 'text' ? { 'attr': { 'size': 1 }} : {} -%}
<div {{ block('widget_container_attributes') }}>
{{ form_widget(form.year, vars) }}-{{ form_widget(form.week, vars) }}
</div>
{%- endif -%}
{%- endblock week_widget -%}
{# Labels #}
{%- block form_label -%}
{% if label is not same as(false) -%}
{% if not compound -%}
{% set label_attr = label_attr|merge({'for': id}) %}
{%- endif -%}
{% if required -%}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
{%- endif -%}
{% if label is empty -%}
{%- if label_format is not empty -%}
{% set label = label_format|replace({
'%name%': name,
'%id%': id,
}) %}
{%- else -%}
{% set label = name|humanize %}
{%- endif -%}
{%- endif -%}
<{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}>
{%- if translation_domain is same as(false) -%}
{%- if label_html is same as(false) -%}
{{- label -}}
{%- else -%}
{{- label|raw -}}
{%- endif -%}
{%- else -%}
{%- if label_html is same as(false) -%}
{{- label|trans(label_translation_parameters, translation_domain) -}}
{%- else -%}
{{- label|trans(label_translation_parameters, translation_domain)|raw -}}
{%- endif -%}
{%- endif -%}
</{{ element|default('label') }}>
{%- endif -%}
{%- endblock form_label -%}
{%- block button_label -%}{%- endblock -%}
{# Help #}
{% block form_help -%}
{%- if help is not empty -%}
{%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ ' help-text')|trim}) -%}
<p id="{{ id }}_help"{% with { attr: help_attr } %}{{ block('attributes') }}{% endwith %}>
{%- if translation_domain is same as(false) -%}
{%- if help_html is same as(false) -%}
{{- help -}}
{%- else -%}
{{- help|raw -}}
{%- endif -%}
{%- else -%}
{%- if help_html is same as(false) -%}
{{- help|trans(help_translation_parameters, translation_domain) -}}
{%- else -%}
{{- help|trans(help_translation_parameters, translation_domain)|raw -}}
{%- endif -%}
{%- endif -%}
</p>
{%- endif -%}
{%- endblock form_help %}
{# Rows #}
{%- block repeated_row -%}
{#
No need to render the errors here, as all errors are mapped
to the first child (see RepeatedTypeValidatorExtension).
#}
{{- block('form_rows') -}}
{%- endblock repeated_row -%}
{%- block form_row -%}
{%- set widget_attr = {} -%}
{%- if help is not empty -%}
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
{%- endif -%}
<div{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}>
{{- form_label(form) -}}
{{- form_errors(form) -}}
{{- form_widget(form, widget_attr) -}}
{{- form_help(form) -}}
</div>
{%- endblock form_row -%}
{%- block button_row -%}
{%- set widget_attr = {} -%}
{{- form_widget(form, {'attr': widget_attr}) -}}
{%- endblock button_row -%}
{%- block hidden_row -%}
{{ form_widget(form) }}
{%- endblock hidden_row -%}
{# Misc #}
{%- block form -%}
{{ form_start(form) }}
{{- form_widget(form) -}}
{{ form_end(form) }}
{%- endblock form -%}
{%- block form_start -%}
{%- do form.setMethodRendered() -%}
{% set method = method|upper %}
{%- if method in ["GET", "POST"] -%}
{% set form_method = method %}
{%- else -%}
{% set form_method = "POST" %}
{%- endif -%}
<form{% if name != '' %} name="{{ name }}"{% endif %} method="{{ form_method|lower }}"{% if action != '' %} action="{{ action }}"{% endif %}{{ block('attributes') }}{% if multipart %} enctype="multipart/form-data"{% endif %}>
{%- if form_method != method -%}
<input type="hidden" name="_method" value="{{ method }}" />
{%- endif -%}
{%- endblock form_start -%}
{%- block form_end -%}
{%- if not render_rest is defined or render_rest -%}
{{ form_rest(form) }}
{%- endif -%}
</form>
{%- endblock form_end -%}
{%- block form_errors -%}
{%- if errors|length > 0 -%}
<ul>
{%- for error in errors -%}
<li>{{ error.message }}</li>
{%- endfor -%}
</ul>
{%- endif -%}
{%- endblock form_errors -%}
{%- block form_rest -%}
{% for child in form -%}
{% if not child.rendered %}
{{- form_row(child) -}}
{% endif %}
{%- endfor -%}
{% if not form.methodRendered and form is rootform %}
{%- do form.setMethodRendered() -%}
{% set method = method|upper %}
{%- if method in ["GET", "POST"] -%}
{% set form_method = method %}
{%- else -%}
{% set form_method = "POST" %}
{%- endif -%}
{%- if form_method != method -%}
<input type="hidden" name="_method" value="{{ method }}" />
{%- endif -%}
{% endif -%}
{% endblock form_rest %}
{# Support #}
{%- block form_rows -%}
{% for child in form|filter(child => not child.rendered) %}
{{- form_row(child) -}}
{% endfor %}
{%- endblock form_rows -%}
{%- block widget_attributes -%}
id="{{ id }}" name="{{ full_name }}"
{%- if disabled %} disabled="disabled"{% endif -%}
{%- if required %} required="required"{% endif -%}
{{ block('attributes') }}
{%- endblock widget_attributes -%}
{%- block widget_container_attributes -%}
{%- if id is not empty %}id="{{ id }}"{% endif -%}
{{ block('attributes') }}
{%- endblock widget_container_attributes -%}
{%- block button_attributes -%}
id="{{ id }}" name="{{ full_name }}"{% if disabled %} disabled="disabled"{% endif -%}
{{ block('attributes') }}
{%- endblock button_attributes -%}
{% block attributes -%}
{%- for attrname, attrvalue in attr -%}
{{- " " -}}
{%- if attrname in ['placeholder', 'title'] -%}
{{- attrname }}="{{ translation_domain is same as(false) or attrvalue is null ? attrvalue : attrvalue|trans(attr_translation_parameters, translation_domain) }}"
{%- elseif attrvalue is same as(true) -%}
{{- attrname }}="{{ attrname }}"
{%- elseif attrvalue is not same as(false) -%}
{{- attrname }}="{{ attrvalue }}"
{%- endif -%}
{%- endfor -%}
{%- endblock attributes -%}

View File

@ -1,4 +1,4 @@
{% use 'form_div_layout.html.twig' %}
{% use 'cards/forms/form_raw_layout.html.twig' %}
{%- block form_row -%}
{%- set row_attr = row_attr|merge({ class: row_attr.class|default(row_class|default('form-row')) }) -%}
@ -58,6 +58,15 @@
</div>
{%- endblock checkbox_row -%}
{%- block button_row -%}
{%- set btn_class = 'is-link' -%}
{%- for color in [ 'is-primary', 'is-info', 'is-success', 'is-warning', 'is-danger' ] -%}
{%- set btn_class = color -%}
{%- endfor -%}
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' button ' ~ btn_class)|trim}) -%}
{{- parent() -}}
{%- endblock button_row -%}
{%- block checkbox_widget -%}
{%- set widget_class = widget_class|default('form-row-checkbox-element') -%}
{{- parent() -}}