Beautify poll

This commit is contained in:
Lim Chee Aun 2023-03-30 11:11:35 +08:00
parent c2ee8c55d3
commit d2214c59be
2 changed files with 104 additions and 74 deletions

View file

@ -843,34 +843,48 @@ a.card:is(:hover, :focus) {
.poll.read-only { .poll.read-only {
pointer-events: none; pointer-events: none;
} }
.poll-options {
display: flex;
flex-direction: column;
gap: 4px;
padding: 4px;
border-radius: 16px;
border: 1px solid var(--outline-color);
background-color: var(--bg-faded-color);
}
.poll-option { .poll-option {
padding: 8px; padding: 4px;
display: flex; display: flex;
gap: 8px; gap: 8px;
justify-content: space-between; justify-content: space-between;
background-color: var(--bg-faded-color);
background-image: linear-gradient(
to right,
var(--link-faded-color),
var(--link-faded-color) var(--percentage),
transparent var(--percentage),
transparent
);
background-repeat: no-repeat;
/* border-radius: 8px; */
border: 1px solid var(--outline-color);
border-bottom: 0;
align-items: center; align-items: center;
text-shadow: 0 1px var(--bg-blur-color); position: relative;
} }
.poll-option:first-child { .poll-option:after {
border-top-left-radius: 8px; content: '';
border-top-right-radius: 8px; position: absolute;
inset: 0;
border-radius: 4px;
background-color: var(--link-faded-color);
opacity: 0;
pointer-events: none;
transition: all 0.2s ease-in-out;
mix-blend-mode: multiply;
} }
.poll-option:last-of-type { .poll-option:first-child:after {
border-bottom: 1px solid var(--outline-color); border-top-left-radius: 12px;
border-bottom-left-radius: 8px; border-top-right-radius: 12px;
border-bottom-right-radius: 8px; }
.poll-option:last-child:after {
border-bottom-left-radius: 12px;
border-bottom-right-radius: 12px;
}
.poll-option:hover:after {
opacity: 1;
}
.poll-option.poll-result:after {
width: var(--percentage);
opacity: 1;
} }
.poll-label { .poll-label {
width: 100%; width: 100%;
@ -897,6 +911,9 @@ a.card:is(:hover, :focus) {
margin: 8px 0; margin: 8px 0;
font-size: 90%; font-size: 90%;
} }
.poll-option-title {
text-shadow: 0 1px var(--bg-color);
}
.poll-option-title .icon { .poll-option-title .icon {
vertical-align: middle; vertical-align: middle;
} }

View file

@ -1309,15 +1309,22 @@ function Poll({
roundPrecision = 2; roundPrecision = 2;
} }
const [showResults, setShowResults] = useState(false);
const optionsHaveVoteCounts = options.every((o) => o.votesCount !== null);
return ( return (
<div <div
lang={lang} lang={lang}
class={`poll ${readOnly ? 'read-only' : ''} ${ class={`poll ${readOnly ? 'read-only' : ''} ${
uiState === 'loading' ? 'loading' : '' uiState === 'loading' ? 'loading' : ''
}`} }`}
onDblClick={() => {
setShowResults(!showResults);
}}
> >
{voted || expired ? ( {(showResults && optionsHaveVoteCounts) || voted || expired ? (
options.map((option, i) => { <div class="poll-options">
{options.map((option, i) => {
const { title, votesCount: optionVotesCount } = option; const { title, votesCount: optionVotesCount } = option;
const percentage = pollVotesCount const percentage = pollVotesCount
? ((optionVotesCount / pollVotesCount) * 100).toFixed( ? ((optionVotesCount / pollVotesCount) * 100).toFixed(
@ -1327,11 +1334,14 @@ function Poll({
// check if current poll choice is the leading one // check if current poll choice is the leading one
const isLeading = const isLeading =
optionVotesCount > 0 && optionVotesCount > 0 &&
optionVotesCount === Math.max(...options.map((o) => o.votesCount)); optionVotesCount ===
Math.max(...options.map((o) => o.votesCount));
return ( return (
<div <div
key={`${i}-${title}-${optionVotesCount}`} key={`${i}-${title}-${optionVotesCount}`}
class={`poll-option ${isLeading ? 'poll-option-leading' : ''}`} class={`poll-option poll-result ${
isLeading ? 'poll-option-leading' : ''
}`}
style={{ style={{
'--percentage': `${percentage}%`, '--percentage': `${percentage}%`,
}} }}
@ -1355,7 +1365,8 @@ function Poll({
</div> </div>
</div> </div>
); );
}) })}
</div>
) : ( ) : (
<form <form
onSubmit={async (e) => { onSubmit={async (e) => {
@ -1374,6 +1385,7 @@ function Poll({
setUIState('default'); setUIState('default');
}} }}
> >
<div class="poll-options">
{options.map((option, i) => { {options.map((option, i) => {
const { title } = option; const { title } = option;
return ( return (
@ -1391,6 +1403,7 @@ function Poll({
</div> </div>
); );
})} })}
</div>
{!readOnly && ( {!readOnly && (
<button <button
class="poll-vote-button" class="poll-vote-button"