Merge branch 'misc-style-fixes-or-changes' into 'develop'

Misc style fixes or changes

Closes #1378

See merge request pleroma/pleroma-fe!2219
This commit is contained in:
HJ 2025-08-21 14:58:26 +00:00
commit 589737dced
40 changed files with 328 additions and 191 deletions

View file

@ -0,0 +1,5 @@
Combined subject and content fields in post form (visually)
Fixes for some elements not scaling with user UI scale
Moved post form's emoji button into input field
Minor visual changes and fixes
Clicking on fav/rt/emoji notifications' contents expands/collapses it

View file

@ -16,7 +16,7 @@
</head>
<body>
<noscript>To use Pleroma, please enable JavaScript.</noscript>
<div id="splash">
<div id="splash" class="initial-hidden">
<!-- we are hiding entire graphic so no point showing credit -->
<div aria-hidden="true" id="splash-credit">
Art by pipivovott

View file

@ -5,15 +5,14 @@ body {
#splash {
--scale: 1;
width: 100vw;
height: 100vh;
display: grid;
grid-template-rows: auto;
grid-template-columns: auto;
align-content: center;
align-items: center;
justify-content: center;
justify-items: center;
place-items: center;
flex-direction: column;
background: #0f161e;
font-family: sans-serif;
@ -21,13 +20,20 @@ body {
position: absolute;
z-index: 9999;
font-size: calc(1vw + 1vh + 1vmin);
opacity: 1;
transition: opacity 500ms ease-out 2s;
}
#splash.hidden,
#splash.initial-hidden {
opacity: 0;
}
#splash-credit {
position: absolute;
font-size: 14px;
bottom: 16px;
right: 16px;
font-size: 1em;
bottom: 1em;
right: 1em;
}
#splash-container {

View file

@ -214,6 +214,9 @@ export default {
splashscreenRoot.addEventListener('transitionend', () => {
splashscreenRoot.remove()
})
setTimeout(() => {
splashscreenRoot.remove() // forcibly remove it, should fix my plasma browser widget t. HJ
}, 600)
splashscreenRoot.classList.add('hidden')
document.querySelector('#app').classList.remove('hidden')
}

View file

@ -21,7 +21,7 @@
}
html {
font-size: var(--textSize, 14px);
font-size: var(--textSize, 1rem);
--navbar-height: var(--navbarSize, 3.5rem);
--emoji-size: var(--emojiSize, 32px);
@ -382,6 +382,10 @@ nav {
font-family: sans-serif;
font-family: var(--font);
&.-transparent {
backdrop-filter: blur(0.125em) contrast(60%);
}
&::-moz-focus-inner {
border: none;
}
@ -741,17 +745,17 @@ option {
}
&.-dot {
min-height: 8px;
max-height: 8px;
min-width: 8px;
max-width: 8px;
min-height: 0.6em;
max-height: 0.6em;
min-width: 0.6em;
max-width: 0.6em;
padding: 0;
line-height: 0;
font-size: 0;
left: calc(50% - 4px);
top: calc(50% - 4px);
margin-left: 6px;
margin-top: -6px;
left: calc(50% - 0.6em);
top: calc(50% - 0.6em);
margin-left: 0.4em;
margin-top: -0.4em;
}
&.-counter {
@ -929,12 +933,7 @@ option {
#splash {
pointer-events: none;
transition: opacity 0.5s;
opacity: 1;
&.hidden {
opacity: 0;
}
// transition: opacity 0.5s;
#status {
&.css-ok {

View file

@ -107,9 +107,9 @@
.play-icon {
position: absolute;
font-size: 64px;
top: calc(50% - 32px);
left: calc(50% - 32px);
font-size: 4.5em;
top: calc(50% - 2.25rem);
left: calc(50% - 2.25rem);
color: rgb(255 255 255 / 75%);
text-shadow: 0 0 2px rgb(0 0 0 / 40%);

View file

@ -64,6 +64,26 @@ export default {
opacity: 0.5
}
},
{
component: 'Text',
parent: {
component: 'Button',
variant: 'transparent'
},
directives: {
textColor: '--text'
}
},
{
component: 'Icon',
parent: {
component: 'Button',
variant: 'transparent'
},
directives: {
textColor: '--text'
}
},
{
state: ['hover'],
directives: {

View file

@ -140,13 +140,13 @@ const EmojiPicker = {
},
updateEmojiSize () {
const css = window.getComputedStyle(this.$refs.popover.$el)
const fontSize = css.getPropertyValue('font-size') || '14px'
const fontSize = css.getPropertyValue('font-size') || '1rem'
const emojiSize = css.getPropertyValue('--emojiSize') || '2.2rem'
const fontSizeUnit = fontSize.replace(/[0-9,.]+/, '')
const fontSizeUnit = fontSize.replace(/[0-9,.]+/, '').trim()
const fontSizeValue = Number(fontSize.replace(/[^0-9,.]+/, ''))
const emojiSizeUnit = emojiSize.replace(/[0-9,.]+/, '')
const emojiSizeUnit = emojiSize.replace(/[0-9,.]+/, '').trim()
const emojiSizeValue = Number(emojiSize.replace(/[^0-9,.]+/, ''))
let fontSizeMultiplier

View file

@ -129,7 +129,7 @@
.gallery-item {
margin: 0;
height: 200px;
height: 15em;
}
}
}

View file

@ -168,7 +168,7 @@ $modal-view-button-icon-margin: 0.5em;
flex: 0 0 auto;
overflow-y: auto;
min-height: 1em;
max-width: 500px;
max-width: 35.8em;
max-height: 9.5em;
overflow-wrap: break-word;
text-wrap: pretty;

View file

@ -7,7 +7,6 @@
& .new,
& .original {
display: inline;
border-radius: 2px;
}
.mention-avatar {

View file

@ -4,13 +4,13 @@
table {
width: 100%;
text-align: left;
padding-left: 10px;
padding-bottom: 20px;
padding-left: 0.5em;
padding-bottom: 1.1em;
th,
td {
width: 180px;
max-width: 360px;
width: 11em;
max-width: 25em;
overflow: hidden;
vertical-align: text-top;
}

View file

@ -42,6 +42,7 @@ library.add(
const Notification = {
data () {
return {
selecting: false,
statusExpanded: false,
unmuted: false,
showingApproveConfirmDialog: false,
@ -62,10 +63,35 @@ const Notification = {
UserLink,
ConfirmModal
},
mounted () {
document.addEventListener('selectionchange', this.onContentSelect)
},
unmounted () {
document.removeEventListener('selectionchange', this.onContentSelect)
},
methods: {
toggleStatusExpanded () {
if (!this.expandable) return
this.statusExpanded = !this.statusExpanded
},
onContentSelect () {
const { isCollapsed, anchorNode, offsetNode } = document.getSelection()
if (isCollapsed) {
this.selecting = false
return
}
const within = this.$refs.root.contains(anchorNode) || this.$refs.root.contains(offsetNode)
if (within) {
this.selecting = true
} else {
this.selecting = false
}
},
onContentClick (e) {
if (!this.selecting && !e.target.closest('a') && !e.target.closest('button')) {
this.toggleStatusExpanded()
}
},
generateUserProfileLink (user) {
return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
},
@ -136,6 +162,9 @@ const Notification = {
const user = this.notification.from_profile
return highlightStyle(highlight[user.screen_name])
},
expandable () {
return (new Set(['like', 'pleroma:emoji_reaction', 'repeat'])).has(this.notification.type)
},
user () {
return this.$store.getters.findUser(this.notification.from_profile.id)
},

View file

@ -1,10 +1,15 @@
// TODO Copypaste from Status, should unify it somehow
.Notification {
border-bottom: 1px solid;
border-color: var(--border);
overflow-wrap: break-word;
text-wrap: pretty;
.status-content {
cursor: pointer;
}
&.Status {
/* stylelint-disable-next-line declaration-no-important */
background-color: transparent !important;

View file

@ -1,6 +1,7 @@
<template>
<article
v-if="notification.type === 'mention' || notification.type === 'status'"
ref="root"
>
<Status
class="Notification"
@ -9,9 +10,17 @@
@interacted="interacted"
/>
</article>
<article v-else>
<article
v-else
ref="root"
class="NotificationParent"
:class="{ '-expandable': expandable }"
>
<div
v-if="needMute && !unmuted"
:id="'notif-' +notification.id"
:aria-expanded="statusExpanded"
:aria-controls="'notif-' +notification.id"
class="Notification container -muted"
>
<small>
@ -246,8 +255,11 @@
/>
<template v-else>
<StatusContent
class="status-content"
:compact="!statusExpanded"
:status="notification.status"
:collapse="!statusExpanded"
@click="onContentClick"
/>
</template>
</div>

View file

@ -726,10 +726,6 @@ const PostStatusForm = {
scrollerRef.scrollTop = targetScroll
}
},
showEmojiPicker () {
this.$refs.textarea.focus()
this.$refs['emoji-input'].triggerShowPicker()
},
clearError () {
this.error = null
},

View file

@ -41,10 +41,12 @@
.form-bottom-left {
display: flex;
flex: 1;
padding-right: 7px;
margin-right: 7px;
max-width: 10em;
gap: 1.5em;
button {
padding: 0.5em;
margin: -0.5em;
}
}
.preview-heading {
@ -102,10 +104,16 @@
.visibility-tray {
display: flex;
justify-content: space-between;
padding-top: 5px;
padding-top: 0.5em;
align-items: baseline;
}
.visibility-notice {
border: 1px solid var(--border);
border-radius: var(--roundness);
padding: 0.5em 1em
}
.visibility-notice.edit-warning {
> :first-child {
margin-top: 0;
@ -193,6 +201,10 @@
line-height: 1.85;
}
.inputs-wrapper {
padding: 0;
}
.input.form-post-body {
// TODO: make a resizable textarea component?
box-sizing: content-box; // needed for easier computation of dynamic size
@ -200,6 +212,7 @@
transition: min-height 200ms 100ms;
// stock padding + 1 line of text (for counter)
padding-bottom: calc(var(--_padding) + var(--post-line-height) * 1em);
padding-right: 1.5em;
// two lines of text
height: calc(var(--post-line-height) * 1em);
min-height: calc(var(--post-line-height) * 1em);
@ -216,6 +229,10 @@
position: relative;
}
.subject-input {
border-bottom: 1px solid var(--border);
}
.character-counter {
position: absolute;
bottom: 0;

View file

@ -156,67 +156,68 @@
class="preview-status"
/>
</div>
<EmojiInput
v-if="!disableSubject && (newStatus.spoilerText || alwaysShowSubject)"
v-model="newStatus.spoilerText"
enable-emoji-picker
:suggest="emojiSuggestor"
class="input form-control"
>
<template #default="inputProps">
<input
v-model="newStatus.spoilerText"
type="text"
:placeholder="$t('post_status.content_warning')"
:disabled="posting && !optimisticPosting"
v-bind="propsToNative(inputProps)"
size="1"
class="input form-post-subject"
>
</template>
</EmojiInput>
<EmojiInput
ref="emoji-input"
v-model="newStatus.status"
:suggest="emojiUserSuggestor"
:placement="emojiPickerPlacement"
class="input form-control main-input"
enable-sticker-picker
enable-emoji-picker
hide-emoji-button
:newline-on-ctrl-enter="submitOnEnter"
@input="onEmojiInputInput"
@sticker-uploaded="addMediaFile"
@sticker-upload-failed="uploadFailed"
@shown="handleEmojiInputShow"
>
<template #default="inputProps">
<textarea
ref="textarea"
v-model="newStatus.status"
:placeholder="placeholder || $t('post_status.default')"
rows="1"
cols="1"
:disabled="posting && !optimisticPosting"
class="input form-post-body"
:class="{ 'scrollable-form': !!maxHeight }"
v-bind="propsToNative(inputProps)"
@keydown.exact.enter="submitOnEnter && postStatus($event, newStatus)"
@keydown.meta.enter="postStatus($event, newStatus)"
@keydown.ctrl.enter="!submitOnEnter && postStatus($event, newStatus)"
@input="resize"
@compositionupdate="resize"
@paste="paste"
/>
<p
v-if="hasStatusLengthLimit"
class="character-counter faint"
:class="{ error: isOverLengthLimit }"
>
{{ charactersLeft }}
</p>
</template>
</EmojiInput>
<div class="input inputs-wrapper">
<EmojiInput
v-if="!disableSubject && (newStatus.spoilerText || alwaysShowSubject)"
v-model="newStatus.spoilerText"
enable-emoji-picker
:suggest="emojiSuggestor"
class="input form-control subject-input unstyled"
>
<template #default="inputProps">
<input
v-model="newStatus.spoilerText"
type="text"
:placeholder="$t('post_status.content_warning')"
:disabled="posting && !optimisticPosting"
v-bind="propsToNative(inputProps)"
size="1"
class="input form-post-subject unstyled"
>
</template>
</EmojiInput>
<EmojiInput
ref="emoji-input"
v-model="newStatus.status"
:suggest="emojiUserSuggestor"
:placement="emojiPickerPlacement"
class="input form-control main-input unstyled"
enable-sticker-picker
enable-emoji-picker
:newline-on-ctrl-enter="submitOnEnter"
@input="onEmojiInputInput"
@sticker-uploaded="addMediaFile"
@sticker-upload-failed="uploadFailed"
@shown="handleEmojiInputShow"
>
<template #default="inputProps">
<textarea
ref="textarea"
v-model="newStatus.status"
:placeholder="placeholder || $t('post_status.default')"
rows="1"
cols="1"
:disabled="posting && !optimisticPosting"
class="input form-post-body"
:class="{ 'scrollable-form': !!maxHeight }"
v-bind="propsToNative(inputProps)"
@keydown.exact.enter="submitOnEnter && postStatus($event, newStatus)"
@keydown.meta.enter="postStatus($event, newStatus)"
@keydown.ctrl.enter="!submitOnEnter && postStatus($event, newStatus)"
@input="resize"
@compositionupdate="resize"
@paste="paste"
/>
<p
v-if="hasStatusLengthLimit"
class="character-counter faint"
:class="{ error: isOverLengthLimit }"
>
{{ charactersLeft }}
</p>
</template>
</EmojiInput>
</div>
<div
v-if="!disableScopeSelector"
class="visibility-tray"
@ -236,8 +237,9 @@
>
<Select
v-model="newStatus.contentType"
class="input form-control"
class="input form-control unstyled"
:attrs="{ 'aria-label': $t('post_status.content_type_selection') }"
unstyled="true"
>
<option
v-for="postFormat in postFormats"
@ -285,13 +287,6 @@
@upload-failed="uploadFailed"
@all-uploaded="finishedUploadingFiles"
/>
<button
class="emoji-icon button-unstyled"
:title="$t('emoji.add_emoji')"
@click="showEmojiPicker"
>
<FAIcon icon="smile-beam" />
</button>
<button
v-if="pollsAvailable"
class="poll-icon button-unstyled"

View file

@ -87,7 +87,19 @@ export default {
type: Boolean,
default: false
},
// Assume is local to be true if unspecified, so the button isn't show where it probably should not be
// Collapse newlines
collapse: {
required: false,
type: Boolean,
default: false
},
/* Content comes from current instance
*
* This is used for emoji stealing popover.
* By default we assume it is, so that steal
* emoji button isn't shown where it probably
* should not be.
*/
isLocal: {
required: false,
type: Boolean,
@ -290,11 +302,20 @@ export default {
const pass1 = convertHtmlToTree(html).map(processItem)
const pass2 = [...pass1].reverse().map(processItemReverse).reverse()
// DO NOT USE SLOTS they cause a re-render feedback loop here.
// slots updated -> rerender -> emit -> update up the tree -> rerender -> ...
// at least until vue3?
const result = <span class={['RichContent', this.faint ? '-faint' : '']}>
{ pass2 }
const result =
<span class={['RichContent', this.faint ? '-faint' : '']}>
{
this.collapse
? pass2.map(x => {
if (!Array.isArray(x)) return x.replace(/\n/g, ' ')
return x.map(y => y.type === 'br' ? ' ' : y)
})
: pass2
}
</span>
const event = {

View file

@ -64,6 +64,11 @@
.img {
display: inline-block;
// fix vertical alignment of stealable emoji
button {
display: inline-flex;
}
}
.emoji {

View file

@ -27,7 +27,10 @@
class="emoji"
/>
<div v-if="newUpload" class="emoji-tab-popover-new-upload">
<div
v-if="newUpload"
class="emoji-tab-popover-new-upload"
>
<h4>{{ $t('admin_dash.emoji.emoji_source') }}</h4>
<div class="emoji-tab-popover-input">
@ -295,8 +298,8 @@ export default {
}
.emoji {
width: 32px;
height: 32px;
width: 2.3em;
height: 2.3em;
}
.Select {

View file

@ -159,10 +159,16 @@
.qr-code {
flex: 1;
padding-right: 10px;
padding-right: 0.7em;
}
.verify {
flex: 1;
}
.error {
margin: 0.3em 0 0;
}
.verify { flex: 1; }
.error { margin: 4px 0 0; }
.confirm-otp-actions {
button {

View file

@ -21,7 +21,10 @@
</div>
<div class="panel-body theme-preview-content">
<div class="post">
<div class="avatar still-image">
<div
class="avatar still-image"
aria-hidden="true"
>
( ͡° ͜ʖ ͡°)
</div>
<div class="content">
@ -71,7 +74,10 @@
</div>
<div class="after-post">
<div class="avatar-alt">
<div
class="avatar-alt"
aria-hidden="true"
>
:^)
</div>
<div class="content">
@ -149,7 +155,7 @@ export default {
background-position: 50% 50%;
.theme-preview-content {
padding: 20px;
padding: 1.5em;
}
.dummy {
@ -203,19 +209,21 @@ export default {
.avatar-alt {
flex: 0 auto;
margin-left: 28px;
font-size: 12px;
min-width: 20px;
min-height: 20px;
line-height: 20px;
margin-left: 2em;
font-size: 0.85em;
min-width: 2.2rem;
min-height: 2.2rem;
line-height: 1.5em;
align-content: center;
}
.avatar {
flex: 0 auto;
width: 48px;
height: 48px;
font-size: 14px;
line-height: 48px;
width: 3.5em;
height: 3.5em;
font-size: 1rem;
line-height: 3.5em;
justify-content: center;
}
.actions {
@ -241,7 +249,7 @@ export default {
.underlay-preview {
position: absolute;
inset: 0 10px;
inset: 0 0.9em;
}
}
</style>

View file

@ -107,7 +107,7 @@
justify-content: space-between;
align-items: baseline;
width: 100%;
min-height: 30px;
min-height: 2.1em;
margin-bottom: 1em;
p {
@ -212,7 +212,7 @@
.theme-color-cl,
.theme-radius-in,
.theme-color-in {
margin-left: 4px;
margin-left: 0.3em;
}
.theme-radius-in {

View file

@ -122,8 +122,8 @@
.shout-avatar {
img {
height: 24px;
width: 24px;
height: 0.6em;
width: 0.6em;
border-radius: var(--roundness);
margin-right: 0.5em;
margin-top: 0.25em;

View file

@ -76,9 +76,10 @@
}
.status-favicon {
height: 18px;
width: 18px;
height: 1.2em;
width: 1.2em;
margin-right: 0.4em;
object-fit: contain;
}
.status-heading {
@ -100,7 +101,8 @@
}
.account-name {
min-width: 1.6em;
display: inline-block;
min-width: 1em;
margin-right: 0.4em;
white-space: nowrap;
overflow: hidden;
@ -116,10 +118,11 @@
.heading-right {
display: flex;
flex-shrink: 0;
align-self: baseline;
.button-unstyled {
padding: 5px;
margin: -5px;
padding: 0.2em;
margin: -0.2em;
}
.svg-inline--fa {
@ -232,9 +235,9 @@
.repeater-avatar {
border-radius: var(--roundness);
margin-left: 28px;
width: 20px;
height: 20px;
margin-left: 2em; // 3.5 (poster avatar size) - 1.5 (repeater avatar size)
width: 1.5em;
height: 1.5em;
}
.repeater-name {
@ -242,8 +245,8 @@
margin-right: 0;
.emoji {
width: 14px;
height: 14px;
width: 1em;
height: 1em;
vertical-align: middle;
object-fit: contain;
}

View file

@ -26,8 +26,8 @@
align-self: stretch;
width: 1px;
background-color: var(--icon);
margin-left: 1em;
margin-right: 0.5em;
margin-left: 0.75em;
margin-right: 0.125em;
}
&.-pin {

View file

@ -22,6 +22,7 @@ const StatusBody = {
name: 'StatusBody',
props: [
'compact',
'collapse', // replaces newlines with spaces
'status',
'focused',
'noHeading',
@ -40,6 +41,7 @@ const StatusBody = {
parseReadyDone: false
}
},
emits: ['parseReady'],
computed: {
localCollapseSubjectDefault () {
return this.mergedConfig.collapseMessageWithSubject
@ -95,6 +97,9 @@ const StatusBody = {
attachmentTypes () {
return this.status.attachments.map(file => fileType.fileType(file.mimetype))
},
collapsedStatus () {
return this.status.raw_html.replace(/(\n|<br\s?\/?>)/g, ' ')
},
...mapGetters(['mergedConfig'])
},
components: {

View file

@ -40,6 +40,7 @@
:class="{ '-single-line': singleLine }"
class="text media-body"
:html="status.raw_html"
:collapse="collapse"
:emoji="status.emojis"
:handle-links="true"
:faint="compact"
@ -59,32 +60,6 @@
@click.prevent="toggleShowMore"
>
{{ toggleText }}
<template v-if="!showingMore">
<FAIcon
v-if="attachmentTypes.includes('image')"
icon="image"
/>
<FAIcon
v-if="attachmentTypes.includes('video')"
icon="video"
/>
<FAIcon
v-if="attachmentTypes.includes('audio')"
icon="music"
/>
<FAIcon
v-if="attachmentTypes.includes('unknown')"
icon="file"
/>
<FAIcon
v-if="status.poll && status.poll.options"
icon="poll-h"
/>
<FAIcon
v-if="status.card"
icon="link"
/>
</template>
</button>
</div>
</div>

View file

@ -53,6 +53,7 @@ const StatusContent = {
props: [
'status',
'compact',
'collapse',
'focused',
'noHeading',
'fullContent',
@ -64,6 +65,7 @@ const StatusContent = {
'controlledShowingLongSubject',
'controlledToggleShowingLongSubject'
],
emits: ['parseReady', 'mediaplay', 'mediapause'],
data () {
return {
uncontrolledShowingTall: this.fullContent || (this.inConversation && this.focused),

View file

@ -14,6 +14,7 @@
:toggle-showing-tall="toggleShowingTall"
:toggle-expanding-subject="toggleExpandingSubject"
:toggle-showing-long-subject="toggleShowingLongSubject"
:collapse="collapse"
@parse-ready="$emit('parseReady', $event)"
>
<div v-if="status.poll && status.poll.options && !compact">
@ -23,7 +24,10 @@
/>
</div>
<div v-else-if="status.poll && status.poll.options && compact">
<div
v-else-if="status.poll && status.poll.options && compact"
class="poll-icon"
>
<FAIcon
icon="poll-h"
size="2x"
@ -62,5 +66,9 @@
.StatusContent {
flex: 1;
min-width: 0;
.poll-icon {
margin: 0.5em;
}
}
</style>

View file

@ -25,8 +25,8 @@
<button
class="button button-default btn emoji-popover-button"
type="button"
@click="copyToLocalPack"
:disabled="packName == ''"
@click="copyToLocalPack"
>
{{ $t('admin_dash.emoji.copy_to_pack') }}
</button>

View file

@ -202,9 +202,9 @@
}
img {
max-height: 26px;
max-height: 1.9em;
vertical-align: top;
margin-top: -5px;
margin-top: -0.3em;
}
}

View file

@ -41,7 +41,7 @@
display: inline-block;
position: relative;
width: 3.5em;
height: 48px;
height: 3.5em;
&.-compact {
width: 2.2em;

View file

@ -206,8 +206,6 @@
padding: 0.6em;
margin: -0.6em;
&.save-profile-button,
&.reset-profile-button,
&.edit-banner-button {
width: auto;
}
@ -272,6 +270,14 @@
// big one
z-index: 1;
line-height: 2em;
filter: drop-shadow(0 0 5em var(--profileTint))
drop-shadow(0 0 0.5em var(--profileTint))
drop-shadow(0 0 0.2em var(--profileTint));
.alert {
text-shadow: none;
}
--emoji-size: 1.7em;
@ -333,6 +339,7 @@
font-size: 0.9em;
font-size: calc(max(90%, 2.5cqw));
line-height: 1.5;
margin-top: 0.5em;
}
.lock-icon {

View file

@ -10,7 +10,10 @@
keypath="user_reporting.title"
class="title"
>
<UserLink :user="user" />
<UserLink
class="user-link"
:user="user"
/>
</i18n-t>
</div>
<div class="panel-body">
@ -74,10 +77,14 @@
<style lang="scss">
.user-reporting-panel {
width: 90vw;
max-width: 700px;
max-width: 50rem;
min-height: 20vh;
max-height: 80vh;
.user-link {
display: inline
}
.panel-body {
display: flex;
flex-direction: column-reverse;
@ -104,7 +111,7 @@
}
textarea.form-control {
line-height: 16px;
line-height: 1.1;
resize: none;
overflow: hidden;
transition: min-height 200ms 100ms;

View file

@ -1,6 +1,6 @@
.with-load-more {
&-footer {
padding: 10px;
padding: 0.9em;
text-align: center;
border-top: 1px solid;
border-top-color: var(--border);

View file

@ -1,6 +1,6 @@
.with-subscription {
&-loading {
padding: 10px;
padding: 0.7em;
text-align: center;
.error {

View file

@ -80,6 +80,7 @@ const persistedStateOptions = {
console.error('Storage error', e)
storageError = e
}
document.querySelector('#splash').classList.remove('initial-hidden')
document.querySelector('#mascot').src = `/static/pleromatan_apology${isFox}_small.webp`
document.querySelector('#status').removeAttribute('class')
document.querySelector('#status').textContent = i18n.global.t('splash.loading')

View file

@ -108,7 +108,7 @@ const defaultState = {
palette: null,
style: null,
emojiReactionsScale: 0.5,
textSize: '14px',
textSize: '1rem',
emojiSize: '2.2rem',
navbarSize: '3.5rem',
panelHeaderSize: '3.2rem',