Skip to content

Commit

Permalink
Improve readability of options text & distinct voted options (#79)
Browse files Browse the repository at this point in the history
* Fix CSS targeting voted options
* Use mix-blend-mode to make option text more readable
* Add setting to toggle color blending
* Adjust some colors to use Flarum CSS variables instead of hardcoded
  • Loading branch information
dsevillamartin authored Jul 25, 2023
1 parent 7061c24 commit 59be77c
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 83 deletions.
20 changes: 17 additions & 3 deletions extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
use Flarum\Api\Serializer\PostSerializer;
use Flarum\Discussion\Discussion;
use Flarum\Extend;
use Flarum\Post\Event\Saving;
use Flarum\Post\Event\Saving as PostSaving;
use Flarum\Post\Post;
use Flarum\Settings\Event\Saved as SettingsSaved;
use FoF\Polls\Api\Controllers;
use FoF\Polls\Api\Serializers\PollSerializer;

Expand Down Expand Up @@ -47,7 +48,16 @@
->hasMany('polls', Poll::class, 'post_id', 'first_post_id'),

(new Extend\Event())
->listen(Saving::class, Listeners\SavePollsToDatabase::class),
->listen(PostSaving::class, Listeners\SavePollsToDatabase::class)
->listen(SettingsSaved::class, function (SettingsSaved $event) {
foreach ($event->settings as $key => $value) {
if ($key === 'fof-polls.optionsColorBlend') {
resolve('fof-user-bio.formatter')->flush();

return;
}
}
}),

(new Extend\ApiSerializer(DiscussionSerializer::class))
->attribute('hasPoll', function (DiscussionSerializer $serializer, Discussion $discussion): bool {
Expand Down Expand Up @@ -100,8 +110,12 @@

(new Extend\Settings())
->default('fof-polls.maxOptions', 10)
->default('fof-polls.optionsColorBlend', true)
->serializeToForum('allowPollOptionImage', 'fof-polls.allowOptionImage', 'boolval')
->serializeToForum('pollMaxOptions', 'fof-polls.maxOptions', 'intval'),
->serializeToForum('pollMaxOptions', 'fof-polls.maxOptions', 'intval')
->registerLessConfigVar('fof-polls-options-color-blend', 'fof-polls.optionsColorBlend', function ($value) {
return $value ? 'true' : 'false';
}),

(new Extend\ModelVisibility(Poll::class))
->scope(Access\ScopePollVisibility::class),
Expand Down
6 changes: 6 additions & 0 deletions js/src/admin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ app.initializers.add('fof/polls', () => {
type: 'switch',
label: app.translator.trans('fof-polls.admin.settings.allow_option_image'),
})
.registerSetting({
setting: 'fof-polls.optionsColorBlend',
type: 'switch',
label: app.translator.trans('fof-polls.admin.settings.options_color_blend'),
help: app.translator.trans('fof-polls.admin.settings.options_color_blend_help'),
})
.registerSetting({
setting: 'fof-polls.maxOptions',
type: 'number',
Expand Down
22 changes: 10 additions & 12 deletions js/src/forum/components/PostPoll.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ListVotersModal from './ListVotersModal';
import classList from 'flarum/common/utils/classList';
import ItemList from 'flarum/common/utils/ItemList';
import Tooltip from 'flarum/common/components/Tooltip';
import icon from 'flarum/common/helpers/icon';
import EditPollModal from './EditPollModal';

export default class PostPoll extends Component {
Expand Down Expand Up @@ -149,24 +150,21 @@ export default class PostPoll extends Component {
const showCheckmark = !app.session.user || (!poll.hasEnded() && poll.canVote() && (!hasVoted || poll.canChangeVote()));

const bar = (
<div className="PollBar" data-selected={voted}>
<div className="PollBar" data-selected={!!voted} style={`--poll-option-width: ${width}%`}>
{showCheckmark && (
<label className="checkbox">
<label className="PollAnswer-checkbox checkbox">
<input onchange={this.changeVote.bind(this, opt)} type="checkbox" checked={voted} disabled={isDisabled} />
<span className="checkmark" />
</label>
)}

<div style={`--width: ${width}%`} className="PollOption-active" />
<label className="PollAnswer">
<span>{opt.answer()}</span>
{opt.imageUrl() ? <img className="PollAnswerImage" src={opt.imageUrl()} alt={opt.answer()} /> : null}
</label>
{canSeeVoteCount && (
<label>
<span className={classList('PollPercent', percent !== 100 && 'PollPercent--option')}>{percent}%</span>
</label>
)}
<div className="PollAnswer-text">
<span className="PollAnswer-text-answer">{opt.answer()}</span>
{voted && !showCheckmark && icon('fas fa-check-circle', { className: 'PollAnswer-check' })}
{canSeeVoteCount && <span className={classList('PollPercent', percent !== 100 && 'PollPercent--option')}>{percent}%</span>}
</div>

{opt.imageUrl() ? <img className="PollAnswer-image" src={opt.imageUrl()} alt={opt.answer()} /> : null}
</div>
);

Expand Down
168 changes: 100 additions & 68 deletions resources/less/forum.less
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
:root {
--poll-option-color: var(--muted-color);
--poll-option-active-color: var(--secondary-color);
}

.ComposerBody-poll {
margin-right: 15px;

Expand All @@ -6,16 +11,16 @@
font-weight: 600;
display: inline-block;
padding: 0.1em 0.5em;
border-radius: @border-radius;
background: @body-bg;
color: @control-color;
border-radius: var(--border-radius);
background: var(--body-bg);
color: var(--control-color);
text-transform: none;
border: 1px solid @primary-color;
border: 1px solid var(--primary-color);

&.none {
background: transparent;
border: 1px dotted @muted-color;
color: @muted-color;
border: 1px dotted var(--muted-color);
color: var(--muted-color);
}
}
}
Expand All @@ -34,6 +39,10 @@
background-color: var(--alert-error-bg);
color: var(--alert-error-color);
}

+ .FormControl {
margin-top: 5px;
}
}

.PollModal--answers {
Expand Down Expand Up @@ -110,6 +119,18 @@
row-gap: 15px;
margin-left: 15px;
align-items: start;

.PollAnswer when (@fof-polls-options-color-blend = true) {
&-checkbox, &-text {
& when (@config-dark-mode =true) {
mix-blend-mode: difference;
}

& when (@config-dark-mode =false) {
mix-blend-mode: darken;
}
}
}
}

.Poll-sticky {
Expand All @@ -121,9 +142,8 @@
display: flex;
align-items: flex-start;
column-gap: 15px;
z-index: 999;
background-color: var(--body-bg);
.box-shadow(inset 0px 2px 0px 0px fade(@text-color, 20%));
.box-shadow(inset 0px 2px 0px 0px var(--muted-more-bg));

&:empty {
display: none;
Expand Down Expand Up @@ -164,29 +184,23 @@
}

.PollOption {
& &-active {
height: 100%;
left: 0;
position: absolute;
z-index: 1;
top: 0;
width: var(--width, 0);
background-color: @muted-color;

// Don't animate if the post is hidden
&:not(.Post--hidden &) {
animation: slideIn 1s ease-in-out;
transition: width 0.75s ease-in-out;
}
&, .PollBar {
border-radius: 4px;
}

.checkmark {
background-color: #fabc67;
}
&:hover {
background: var(--muted-more-bg);
}

/* Percent */
.PollPercent {
padding-right: 5px;
font-size: 11px;
font-weight: 600;

&--option {
color: var(--muted-color);
}
}

.PollLabel {
Expand All @@ -195,62 +209,88 @@
display: inline-block;
padding: .1em .5em;
border-radius: 4px;
background: #e8ecf3;
color: #667c99;
background: transparent;
color: var(--muted-color);
text-transform: none;
}

.PollAnswerImage {
display: block; // Put image on its own line below label text
max-width: 100%;
margin-top: 10px;
&:not(.Post--hidden &) {
.PollBar::after {
animation: slideInPollBackground 1s ease-in-out;
transition: background-size 0.75s ease-in-out;
}
}

.PollBar {
background: transparent;
padding: 10px;
position: relative;
border-radius: 4px;
border: 2px solid @muted-color;
border: 2px solid var(--poll-option-color);
overflow: hidden;
isolation: isolate;

display: flex;
column-gap: 10px;
display: grid;
grid-template-columns: auto 1fr;
grid-auto-flow: row;
gap: 10px;
align-items: flex-start;

&:hover {
background: #f3f3f39e;
.PollAnswer-checkbox {
grid-column: 1;
grid-row: 1;

+ .PollAnswer-text {
grid-column: 2;
}
}

label {
position: relative;
z-index: 2;
.PollAnswer-text {
grid-column: ~"1 / span 2";
grid-row: 1;

display: flex;
column-gap: 5px;
align-items: first baseline;

span {
font-size: 11px;
line-height: 19px;
font-weight: 600;
&-answer {
flex-grow: 1;
}
}
.PollAnswer {
flex-grow: 1;

.PollAnswer-image {
grid-column: ~"1 / span 2";
grid-row: 2;
max-width: 100%;
}

&[data-selected=true] {
border-color: @secondary-color;
&::after {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
z-index: -1;
background-image: linear-gradient(
to right,
var(--poll-option-color) 0% 100%
);
background-size: var(--poll-option-width) 100%;
background-repeat: no-repeat;
content: '';
}

.PollOption-active {
background-color: @secondary-color;
}
.PollAnswer {
flex-grow: 1;
}

label .PollAnswer {
color: contrast(@secondary-color);
}
&[data-selected] {
--poll-option-color: var(--poll-option-active-color);
}
}

label.checkbox {
.PollAnswer-checkbox {
margin-bottom: 0;
position: relative;
z-index: 2;

input[type="checkbox"] {
position: absolute;
Expand Down Expand Up @@ -283,14 +323,10 @@
top: 3px;
width: 5px;
height: 10px;
border: solid black;
border: solid var(--text-color);
border-width: 0 3px 3px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}


}
}
}
Expand Down Expand Up @@ -350,15 +386,11 @@
}
}

@keyframes slideIn {
@keyframes slideInPollBackground {
from {
width: 0
background-size: 0 100%;
}
to {
width: var(--width);
background-size: var(--poll-option-width) 100%;
}
}

.PollPercent--option {
color: #868686;
}
2 changes: 2 additions & 0 deletions resources/locale/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ fof-polls:
settings:
allow_option_image: Allow an image URL to be provided for each poll option
max_options: Maximum number of options per poll
options_color_blend: Color blend text in poll options
options_color_blend_help: Use this to use color mixing to make the poll options more readable. Disable if this feature causes issues with your forum's appearance, reducing readability.
permissions:
view_results_without_voting: View results without voting
start: Start a poll
Expand Down

0 comments on commit 59be77c

Please sign in to comment.