Merge remote-tracking branch 'origin/develop' into shigusegubu-vue3

* origin/develop: (93 commits)
  Fix mobile layout margin
  Update dependency eslint-plugin-n to v15.6.1
  Add status authors from search results to store
  Fix notification attachment icon overflow
  Debounce mute word setting
  Use bdi to isolate repeater name
  Display better error message for unauthenticated timelines
  Make modal easier to close if there is only one image
  Disable no-shorthand for certain props for better readability
  Use splice instead of delete
  Pick a better query selector
  Adjust query selector to actually get the popover now
  Use stylelint
  Update stylelint and support vue/scss
  Update dependency stylelint to v14
  Stop propogation for all top-bar buttons
  Fix emoji picker off-by-1 error
  Update dependency nightwatch to v2.6.6
  Update dependency @vue/test-utils to v2.2.7
  Update dependency sinon to v15
  ...
This commit is contained in:
Henry Jameson 2023-01-16 21:44:58 +02:00
commit 71023491ed
163 changed files with 2777 additions and 2166 deletions

View file

@ -1,19 +1,41 @@
{ {
"extends": [ "extends": [
"stylelint-rscss/config", "stylelint-rscss/config",
"stylelint-config-recommended", "stylelint-config-standard",
"stylelint-config-standard" "stylelint-config-recommended-scss",
"stylelint-config-html",
"stylelint-config-recommended-vue/scss"
], ],
"rules": { "rules": {
"declaration-no-important": true, "declaration-no-important": true,
"rscss/no-descendant-combinator": false, "rscss/no-descendant-combinator": false,
"rscss/class-format": [ "rscss/class-format": [
true, false,
{ {
"component": "pascal-case", "component": "pascal-case",
"variant": "^-[a-z]\\w+", "variant": "^-[a-z]\\w+",
"element": "^[a-z]\\w+" "element": "^[a-z]\\w+"
} }
],
"selector-class-pattern": null,
"import-notation": null,
"custom-property-pattern": null,
"keyframes-name-pattern": null,
"scss/operator-no-newline-after": null,
"declaration-block-no-redundant-longhand-properties": [
true,
{
"ignoreShorthands": [
"grid-template",
"margin",
"padding",
"border",
"border-width",
"border-style",
"border-color",
"border-radius"
]
}
] ]
} }
} }

View file

@ -3,52 +3,76 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## Unreleased ## 2.5.0 - 23.12.2022
### Fixed ### Fixed
- AdminFE button no longer scrolls page to top when clicked - UI no longer lags when switching between mobile and desktop mode
- Popovers no longer constrained by DOM hierarchy, shouldn't be cut off by anything
- Emoji autocomplete popover and picker popover stick to the text cursor.
- Attachments are ALWAYS in same order as user uploaded, no more "videos first"
- Pinned statuses no longer appear at bottom of user timeline (still appear as part of the timeline when fetched deep enough) - Pinned statuses no longer appear at bottom of user timeline (still appear as part of the timeline when fetched deep enough)
- Fixed many many bugs related to new mentions, including spacing and alignment issues - Fixed many many bugs related to new mentions, including spacing and alignment issues
- Links in profile bios now properly open in new tabs - Links in profile bios now properly open in new tabs
- "Always show mobile button" is working now
- Inline images now respect their intended width/height attributes - Inline images now respect their intended width/height attributes
- Links with `&` in them work properly now - Links with `&` in them work properly now
- Interaction list popovers now properly emojify names
- Completely hidden posts still had 1px border
- Attachments are ALWAYS in same order as user uploaded, no more "videos first"
- Attachment description is prefilled with backend-provided default when uploading - Attachment description is prefilled with backend-provided default when uploading
- Proper visual feedback that next image is loading when browsing - Proper visual feedback that next image is loading when browsing
- UI no longer lags when switching between mobile and desktop mode - Additional HTML sanitization on frontend side in case backend sanitization fails
- Popovers no longer constrained by DOM hierarchy, shouldn't be cut off by anything - Interaction list popovers now properly emojify names
- "Always show mobile button" is working now - AdminFE button no longer scrolls page to top when clicked
- User handles with non-ascii domains now have less intrusive indicator for the domain name
- Completely hidden posts still no longer have 1px border
- A lot of accessibility improvements
### Changed ### Changed
- Using Vue 3 now - Using Vue 3 now
- (You)s are optional (opt-in) now, bolding your nickname is also optional (opt-out) - A lot of internal dependencies updated
- "(You)s" are optional (opt-in) now, bolding your nickname is also optional (opt-out)
- User highlight background now also covers the `@` - User highlight background now also covers the `@`
- Reverted back to textual `@`, svg version is opt-in. - Reverted back to textual `@`, svg version is opt-in.
- Settings window has been thoroughly rearranged to make more sense and make navigation settings easier. - Settings window has been thoroughly rearranged to make more sense and make navigation settings easier.
- Uploaded attachments are uniform with displayed attachments - Uploaded attachments are uniform with displayed attachments
- Flash is watchable in media-modal (takes up nearly full screen though due to sizing issues) - Flash is watchable in media-modal (takes up nearly full screen though due to sizing issues)
- Notifications about likes/repeats/emoji reacts are now minimized so they always take up same amount of space irrelevant to size of post. - Notifications about likes/repeats/emoji reacts are now minimized so they always take up same amount of space irrelevant to size of post. (You can expand them to full if need be)
- Slight width/spacing adjustments - Slight width/spacing adjustments
- More sizing stuff is font-size dependent now - More sizing stuff is font-size dependent now
- Scrollbars are styled/colorized now - Scrollbars are styled/colorized now
- Scrollbars are toggleable (for stuff that didn't have visible scrollbars before) (opt-in) - Scrollbars are toggleable (for stuff that didn't have visible scrollbars before) (opt-in)
- Updated localization files
- Top bar is more useful in mobile mode now.
- "Show new" button is way more compact in mobile mode
- Slightly adjusted placement and spacing of the topbar buttons so it's less easy to accidentally log yourself out
### Added ### Added
- 3 column mode: only enables when there's space for it (opt-out, customizable) - 3 column mode: only enables when there's space for it (opt-out, customizable)
- Apologetic pleroma-tan
- New button on timeline header to change some of the new and often-used settings
- Support for lists
- Added ability to edit posts and view post edit history etc.
- Added ability to add personal note to users
- Added initial support for admin announcements
- Added ui for account migration
- Added ui for backups
- Added ability to force-unfollow a user from you
- Emoji are now grouped by pack
- Ability to pin navigation items and collapse the navigation menu
- Ability to rearrange order of attachments when uploading
- Ability to scroll column (or page) to top via panel header button
- Options to show domains in mentions - Options to show domains in mentions
- Option to show user avatars in mention links (opt-in) - Option to show user avatars in mention links (opt-in)
- Option to disable the tooltip for mentions - Option to disable the tooltip for mentions
- Option to completely hide muted threads - Option to completely hide muted threads
- Option to customize what clicking user avatar does in user popover
- Notifications for poll results
- "Favorites" link in navigation
- Very early and somewhat experimental system for automatic settings sync (used only for pinned navigation and apologetic pleroma-tan)
- Implemented remote interaction with statuses for anon visitors
- Ability to open videos in modal even if you disabled that feature, via an icon button - Ability to open videos in modal even if you disabled that feature, via an icon button
- New button on attachment that indicates that attachment has a description and shows a bar filled with description - New button on attachment that indicates that attachment has a description and shows a bar filled with description
- Attachments are truncated just like post contents - Attachments are truncated just like post contents
- Media modal now also displays description and counter position in gallery (i.e. 1/5) - Media modal now also displays description and counter position in gallery (i.e. 1/5)
- Ability to rearrange order of attachments when uploading
- Enabled users to zoom and pan images in media viewer with mouse and touch - Enabled users to zoom and pan images in media viewer with mouse and touch
- Timelines/panels and conversations have sticky headers now - Timelines/panels and conversations have sticky headers now (a bit glitchy on some browsers like safari) (opt-out)
- Added frontend ui for account migration
- Implemented remote interaction with statuses
## [2.4.2] - 2022-01-09 ## [2.4.2] - 2022-01-09

View file

@ -11,4 +11,4 @@ Contributors of this project.
- Vincent Guth (https://unsplash.com/photos/XrwVIFy6rTw): Background images. - Vincent Guth (https://unsplash.com/photos/XrwVIFy6rTw): Background images.
- hj (hj@shigusegubu.club): Code - hj (hj@shigusegubu.club): Code
- Sean King (seanking@kazv.moe): Code - Sean King (seanking@kazv.moe): Code
- Tusooa Zhu (tusooa@kazv.moe): Code - tusooa (tusooa@kazv.moe): Code

View file

@ -1,18 +1,19 @@
# Pleroma-FE # Pleroma-FE
> A single column frontend designed for Pleroma. > Highly-customizable frontend designed for Pleroma.
![screenshot](/uploads/796c5ecf985ed1e2b0943ee0df131ed0/DJVqSJ0.png) ![screenshot](./image-1.png)
# For Translators # For Translators
To translate Pleroma-FE, add your language to [src/i18n/messages.js](https://git.pleroma.social/pleroma/pleroma-fe/blob/develop/src/i18n/messages.js). Pleroma-FE will set your language by your browser locale, but you can temporarily force it in the code by changing the locale in main.js. To translate Pleroma-FE, use our weblate server: https://translate.pleroma.social/. If you need to add your language it should be added as a json file in [src/i18n/](https://git.pleroma.social/pleroma/pleroma-fe/blob/develop/src/i18n/) folder and added in a list within [src/i18n/languages.js](https://git.pleroma.social/pleroma/pleroma-fe/blob/develop/src/i18n/languages.js).
# FOR ADMINS Pleroma-FE will set your language by your browser locale, but you can change language in settings.
You don't need to build Pleroma-FE yourself. Those using the Pleroma backend will be able to use it out of the box. # For instance admins
You don't need to build Pleroma-FE yourself. Those using the Pleroma backend will be able to use it out of the box. Information of customizing PleromaFE settings/defaults is in our [guide](https://docs-develop.pleroma.social/frontend/CONFIGURATION/) and in case you want to build your own custom version there's [another](https://docs-develop.pleroma.social/frontend/HACKING/)
## Build Setup # Build Setup
``` bash ``` bash
# install dependencies # install dependencies
@ -20,13 +21,13 @@ npm install -g yarn
yarn yarn
# serve with hot reload at localhost:8080 # serve with hot reload at localhost:8080
npm run dev yarn dev
# build for production with minification # build for production with minification
npm run build yarn build
# run unit tests # run unit tests
npm run unit yarn unit
``` ```
# For Contributors: # For Contributors:
@ -40,10 +41,4 @@ FE Build process also leaves current commit hash in global variable `___pleromaf
# Configuration # Configuration
Edit config.json for configuration. Set configuration settings in AdminFE, additionally you can edit config.json. For more details see [documentation](https://docs-develop.pleroma.social/frontend/CONFIGURATION/).
## Options
### Login methods
```loginMethod``` can be set to either ```password``` (the default) or ```token```, which will use the full oauth redirection flow, which is useful for SSO situations.

View file

@ -6,7 +6,7 @@ var ServiceWorkerWebpackPlugin = require('serviceworker-webpack5-plugin')
var CopyPlugin = require('copy-webpack-plugin'); var CopyPlugin = require('copy-webpack-plugin');
var { VueLoaderPlugin } = require('vue-loader') var { VueLoaderPlugin } = require('vue-loader')
var ESLintPlugin = require('eslint-webpack-plugin'); var ESLintPlugin = require('eslint-webpack-plugin');
var StylelintPlugin = require('stylelint-webpack-plugin');
var env = process.env.NODE_ENV var env = process.env.NODE_ENV
// check env & config/index.js to decide weither to enable CSS Sourcemaps for the // check env & config/index.js to decide weither to enable CSS Sourcemaps for the
@ -111,6 +111,7 @@ module.exports = {
extensions: ['js', 'vue'], extensions: ['js', 'vue'],
formatter: require('eslint-formatter-friendly') formatter: require('eslint-formatter-friendly')
}), }),
new StylelintPlugin({}),
new VueLoaderPlugin(), new VueLoaderPlugin(),
// This copies Ruffle's WASM to a directory so that JS side can access it // This copies Ruffle's WASM to a directory so that JS side can access it
new CopyPlugin({ new CopyPlugin({

BIN
image-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 KiB

BIN
image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View file

@ -1,9 +1,9 @@
{ {
"name": "pleroma_fe", "name": "pleroma_fe",
"version": "1.0.0", "version": "2.5.0",
"description": "A Qvitter-style frontend for certain GS servers.", "description": "Pleroma frontend, the default frontend of Pleroma social network server",
"author": "Roger Braun <roger@rogerbraun.net>", "author": "Pleroma contributors <https://git.pleroma.social/pleroma/pleroma-fe/-/blob/develop/CONTRIBUTORS.md>",
"private": true, "private": false,
"scripts": { "scripts": {
"dev": "node build/dev-server.js", "dev": "node build/dev-server.js",
"build": "node build/build.js", "build": "node build/build.js",
@ -11,17 +11,17 @@
"unit:watch": "karma start test/unit/karma.conf.js --single-run=false", "unit:watch": "karma start test/unit/karma.conf.js --single-run=false",
"e2e": "node test/e2e/runner.js", "e2e": "node test/e2e/runner.js",
"test": "npm run unit && npm run e2e", "test": "npm run unit && npm run e2e",
"stylelint": "npx stylelint src/components/status/status.scss", "stylelint": "npx stylelint '**/*.scss' '**/*.vue'",
"lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs", "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs",
"lint-fix": "eslint --fix --ext .js,.vue src test/unit/specs test/e2e/specs" "lint-fix": "eslint --fix --ext .js,.vue src test/unit/specs test/e2e/specs"
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "7.20.0", "@babel/runtime": "7.20.7",
"@chenfengyuan/vue-qrcode": "2.0.0", "@chenfengyuan/vue-qrcode": "2.0.0",
"@fortawesome/fontawesome-svg-core": "6.2.0", "@fortawesome/fontawesome-svg-core": "6.2.1",
"@fortawesome/free-regular-svg-icons": "6.2.0", "@fortawesome/free-regular-svg-icons": "6.2.1",
"@fortawesome/free-solid-svg-icons": "6.2.0", "@fortawesome/free-solid-svg-icons": "6.2.1",
"@fortawesome/vue-fontawesome": "3.0.1", "@fortawesome/vue-fontawesome": "3.0.2",
"@kazvmoe-infra/pinch-zoom-element": "1.2.0", "@kazvmoe-infra/pinch-zoom-element": "1.2.0",
"@kazvmoe-infra/unicode-emoji-json": "0.4.0", "@kazvmoe-infra/unicode-emoji-json": "0.4.0",
"@ruffle-rs/ruffle": "0.1.0-nightly.2022.7.12", "@ruffle-rs/ruffle": "0.1.0-nightly.2022.7.12",
@ -34,7 +34,6 @@
"escape-html": "1.0.3", "escape-html": "1.0.3",
"js-cookie": "3.0.1", "js-cookie": "3.0.1",
"localforage": "1.10.0", "localforage": "1.10.0",
"lozad": "1.16.0",
"parse-link-header": "2.0.0", "parse-link-header": "2.0.0",
"lozad": "^1.16.0", "lozad": "^1.16.0",
"phoenix": "1.6.2", "phoenix": "1.6.2",
@ -43,43 +42,44 @@
"querystring-es3": "0.2.1", "querystring-es3": "0.2.1",
"url": "0.11.0", "url": "0.11.0",
"utf8": "3.0.0", "utf8": "3.0.0",
"vue": "3.2.41", "vue": "3.2.45",
"vue-i18n": "9.2.2", "vue-i18n": "9.2.2",
"vue-router": "4.1.6", "vue-router": "4.1.6",
"vue-template-compiler": "2.7.13", "vue-template-compiler": "2.7.14",
"vue-virtual-scroller": "^2.0.0-beta.7",
"vuex": "4.1.0" "vuex": "4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.19.6", "@babel/core": "7.20.7",
"@babel/eslint-parser": "7.19.1", "@babel/eslint-parser": "7.19.1",
"@babel/plugin-transform-runtime": "7.19.6", "@babel/plugin-transform-runtime": "7.19.6",
"@babel/preset-env": "7.19.4", "@babel/preset-env": "7.20.2",
"@babel/register": "7.18.9", "@babel/register": "7.18.9",
"@intlify/vue-i18n-loader": "5.0.0", "@intlify/vue-i18n-loader": "5.0.0",
"@ungap/event-target": "0.2.3", "@ungap/event-target": "0.2.3",
"@vue/babel-helper-vue-jsx-merge-props": "1.4.0", "@vue/babel-helper-vue-jsx-merge-props": "1.4.0",
"@vue/babel-plugin-jsx": "1.1.1", "@vue/babel-plugin-jsx": "1.1.1",
"@vue/compiler-sfc": "3.2.41", "@vue/compiler-sfc": "3.2.45",
"@vue/test-utils": "2.2.6", "@vue/test-utils": "2.2.7",
"autoprefixer": "10.4.12", "autoprefixer": "10.4.13",
"babel-loader": "8.2.5", "babel-loader": "9.1.0",
"babel-plugin-lodash": "3.3.4", "babel-plugin-lodash": "3.3.4",
"chai": "4.3.7", "chai": "4.3.7",
"chalk": "1.1.3", "chalk": "1.1.3",
"chromedriver": "104.0.0", "chromedriver": "108.0.0",
"connect-history-api-fallback": "2.0.0", "connect-history-api-fallback": "2.0.0",
"copy-webpack-plugin": "11.0.0", "copy-webpack-plugin": "11.0.0",
"cross-spawn": "7.0.3", "cross-spawn": "7.0.3",
"css-loader": "6.7.1", "css-loader": "6.7.3",
"css-minimizer-webpack-plugin": "4.2.2", "css-minimizer-webpack-plugin": "4.2.2",
"custom-event-polyfill": "1.0.7", "custom-event-polyfill": "1.0.7",
"eslint": "8.29.0", "eslint": "8.31.0",
"eslint-config-standard": "17.0.0", "eslint-config-standard": "17.0.0",
"eslint-formatter-friendly": "7.0.0", "eslint-formatter-friendly": "7.0.0",
"eslint-plugin-import": "2.26.0", "eslint-plugin-import": "2.26.0",
"eslint-plugin-n": "15.5.0", "eslint-plugin-n": "15.6.1",
"eslint-plugin-promise": "6.1.1", "eslint-plugin-promise": "6.1.1",
"eslint-plugin-vue": "9.7.0", "eslint-plugin-vue": "9.8.0",
"eslint-webpack-plugin": "3.2.0", "eslint-webpack-plugin": "3.2.0",
"eventsource-polyfill": "0.9.6", "eventsource-polyfill": "0.9.6",
"express": "4.18.2", "express": "4.18.2",
@ -95,37 +95,42 @@
"karma-mocha-reporter": "2.2.5", "karma-mocha-reporter": "2.2.5",
"karma-sinon-chai": "2.0.2", "karma-sinon-chai": "2.0.2",
"karma-sourcemap-loader": "0.3.8", "karma-sourcemap-loader": "0.3.8",
"karma-spec-reporter": "0.0.34", "karma-spec-reporter": "0.0.36",
"karma-webpack": "5.0.0", "karma-webpack": "5.0.0",
"lodash": "4.17.21", "lodash": "4.17.21",
"mini-css-extract-plugin": "2.6.1", "mini-css-extract-plugin": "2.7.2",
"mocha": "10.0.0", "mocha": "10.2.0",
"nightwatch": "2.3.3", "nightwatch": "2.6.6",
"opn": "5.5.0", "opn": "5.5.0",
"ora": "0.4.1", "ora": "0.4.1",
"postcss": "8.4.16", "postcss": "8.4.20",
"postcss-loader": "7.0.1", "postcss-html": "^1.5.0",
"sass": "1.55.0", "postcss-loader": "7.0.2",
"sass-loader": "13.0.2", "postcss-scss": "^4.0.6",
"sass": "1.57.1",
"sass-loader": "13.2.0",
"selenium-server": "2.53.1", "selenium-server": "2.53.1",
"semver": "7.3.8", "semver": "7.3.8",
"serviceworker-webpack5-plugin": "2.0.0", "serviceworker-webpack5-plugin": "2.0.0",
"shelljs": "0.8.5", "shelljs": "0.8.5",
"sinon": "14.0.2", "sinon": "15.0.1",
"sinon-chai": "3.7.0", "sinon-chai": "3.7.0",
"stylelint": "13.13.1", "stylelint": "14.16.1",
"stylelint-config-standard": "20.0.0", "stylelint-config-html": "^1.1.0",
"stylelint-config-recommended-scss": "^8.0.0",
"stylelint-config-recommended-vue": "^1.4.0",
"stylelint-config-standard": "29.0.0",
"stylelint-rscss": "0.4.0", "stylelint-rscss": "0.4.0",
"unicode-emoji-json": "^0.3.0", "stylelint-webpack-plugin": "^3.3.0",
"vue-loader": "17.0.1", "vue-loader": "17.0.1",
"vue-style-loader": "4.1.3", "vue-style-loader": "4.1.3",
"webpack": "5.74.0", "webpack": "5.75.0",
"webpack-dev-middleware": "3.7.3", "webpack-dev-middleware": "3.7.3",
"webpack-hot-middleware": "2.25.2", "webpack-hot-middleware": "2.25.3",
"webpack-merge": "0.20.0" "webpack-merge": "0.20.0"
}, },
"engines": { "engines": {
"node": ">= 4.0.0", "node": ">= 16.0.0",
"npm": ">= 3.0.0" "npm": ">= 3.0.0"
} }
} }

View file

@ -1,5 +1,7 @@
// stylelint-disable rscss/class-format // stylelint-disable rscss/class-format
@import './_variables.scss'; /* stylelint-disable no-descending-specificity */
@import "./variables";
@import "./panel";
:root { :root {
--navbar-height: 3.5rem; --navbar-height: 3.5rem;
@ -123,7 +125,7 @@ h4 {
font-weight: 1000; font-weight: 1000;
} }
i[class*=icon-], i[class*="icon-"],
.svg-inline--fa, .svg-inline--fa,
.iconLetter { .iconLetter {
color: $fallback--icon; color: $fallback--icon;
@ -132,7 +134,7 @@ i[class*=icon-],
.button-unstyled:hover, .button-unstyled:hover,
a:hover { a:hover {
> i[class*=icon-], > i[class*="icon-"],
> .svg-inline--fa, > .svg-inline--fa,
> .iconLetter { > .iconLetter {
color: var(--text); color: var(--text);
@ -141,12 +143,11 @@ a:hover {
nav { nav {
z-index: var(--ZI_navbar); z-index: var(--ZI_navbar);
color: var(--topBarText);
background-color: $fallback--fg; background-color: $fallback--fg;
background-color: var(--topBar, $fallback--fg); background-color: var(--topBar, $fallback--fg);
color: $fallback--faint; color: $fallback--faint;
color: var(--faint, $fallback--faint); color: var(--faint, $fallback--faint);
box-shadow: 0 0 4px rgba(0, 0, 0, 0.6); box-shadow: 0 0 4px rgb(0 0 0 / 60%);
box-shadow: var(--topBarShadow); box-shadow: var(--topBarShadow);
box-sizing: border-box; box-sizing: border-box;
height: var(--navbar-height); height: var(--navbar-height);
@ -191,13 +192,11 @@ nav {
} }
.underlay { .underlay {
grid-column-start: 1; grid-column: 1 / span 3;
grid-column-end: span 3; grid-row: 1 / 1;
grid-row-start: 1;
grid-row-end: 1;
pointer-events: none; pointer-events: none;
background-color: rgba(0, 0, 0, 0.15); background-color: rgb(0 0 0 / 15%);
background-color: var(--underlay, rgba(0, 0, 0, 0.15)); background-color: var(--underlay, rgb(0 0 0 / 15%));
z-index: -1000; z-index: -1000;
} }
@ -231,8 +230,7 @@ nav {
display: grid; display: grid;
grid-template-columns: 100%; grid-template-columns: 100%;
box-sizing: border-box; box-sizing: border-box;
grid-row-start: 1; grid-row: 1 / 1;
grid-row-end: 1;
margin: 0 calc(var(--___columnMargin) / 2); margin: 0 calc(var(--___columnMargin) / 2);
padding: calc(var(--___columnMargin)) 0; padding: calc(var(--___columnMargin)) 0;
row-gap: var(--___columnMargin); row-gap: var(--___columnMargin);
@ -307,7 +305,7 @@ nav {
align-content: start; align-content: start;
} }
&.-reverse:not(.-wide):not(.-mobile) { &.-reverse:not(.-wide, .-mobile) {
grid-template-columns: grid-template-columns:
var(--effectiveContentColumnWidth) var(--effectiveContentColumnWidth)
var(--effectiveSidebarColumnWidth); var(--effectiveSidebarColumnWidth);
@ -336,11 +334,8 @@ nav {
padding: 0; padding: 0;
.column { .column {
margin-left: 0;
margin-right: 0;
padding-top: 0; padding-top: 0;
margin-top: var(--navbar-height); margin: var(--navbar-height) 0 0 0;
margin-bottom: 0;
} }
.panel-heading, .panel-heading,
@ -389,7 +384,7 @@ nav {
background: transparent; background: transparent;
} }
i[class*=icon-], i[class*="icon-"],
.svg-inline--fa { .svg-inline--fa {
color: $fallback--text; color: $fallback--text;
color: var(--btnText, $fallback--text); color: var(--btnText, $fallback--text);
@ -400,12 +395,15 @@ nav {
} }
&:hover { &:hover {
box-shadow: 0 0 4px rgba(255, 255, 255, 0.3); box-shadow: 0 0 4px rgb(255 255 255 / 30%);
box-shadow: var(--buttonHoverShadow); box-shadow: var(--buttonHoverShadow);
} }
&:active { &:active {
box-shadow: 0 0 4px 0 rgba(255, 255, 255, 0.3), 0 1px 0 0 rgba(0, 0, 0, 0.2) inset, 0 -1px 0 0 rgba(255, 255, 255, 0.2) inset; box-shadow:
0 0 4px 0 rgb(255 255 255 / 30%),
0 1px 0 0 rgb(0 0 0 / 20%) inset,
0 -1px 0 0 rgb(255 255 255 / 20%) inset;
box-shadow: var(--buttonPressedShadow); box-shadow: var(--buttonPressedShadow);
color: $fallback--text; color: $fallback--text;
color: var(--btnPressedText, $fallback--text); color: var(--btnPressedText, $fallback--text);
@ -438,7 +436,10 @@ nav {
color: var(--btnToggledText, $fallback--text); color: var(--btnToggledText, $fallback--text);
background-color: $fallback--fg; background-color: $fallback--fg;
background-color: var(--btnToggled, $fallback--fg); background-color: var(--btnToggled, $fallback--fg);
box-shadow: 0 0 4px 0 rgba(255, 255, 255, 0.3), 0 1px 0 0 rgba(0, 0, 0, 0.2) inset, 0 -1px 0 0 rgba(255, 255, 255, 0.2) inset; box-shadow:
0 0 4px 0 rgb(255 255 255 / 30%),
0 1px 0 0 rgb(0 0 0 / 20%) inset,
0 -1px 0 0 rgb(255 255 255 / 20%) inset;
box-shadow: var(--buttonPressedShadow); box-shadow: var(--buttonPressedShadow);
svg, svg,
@ -503,7 +504,10 @@ textarea,
border: none; border: none;
border-radius: $fallback--inputRadius; border-radius: $fallback--inputRadius;
border-radius: var(--inputRadius, $fallback--inputRadius); border-radius: var(--inputRadius, $fallback--inputRadius);
box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2) inset, 0 -1px 0 0 rgba(255, 255, 255, 0.2) inset, 0 0 2px 0 rgba(0, 0, 0, 1) inset; box-shadow:
0 1px 0 0 rgb(0 0 0 / 20%) inset,
0 -1px 0 0 rgb(255 255 255 / 20%) inset,
0 0 2px 0 rgb(0 0 0 / 100%) inset;
box-shadow: var(--inputShadow); box-shadow: var(--inputShadow);
background-color: $fallback--fg; background-color: $fallback--fg;
background-color: var(--input, $fallback--fg); background-color: var(--input, $fallback--fg);
@ -521,13 +525,13 @@ textarea,
padding: 0 var(--_padding); padding: 0 var(--_padding);
&:disabled, &:disabled,
&[disabled=disabled], &[disabled="disabled"],
&.disabled { &.disabled {
cursor: not-allowed; cursor: not-allowed;
opacity: 0.5; opacity: 0.5;
} }
&[type=range] { &[type="range"] {
background: none; background: none;
border: none; border: none;
margin: 0; margin: 0;
@ -535,7 +539,7 @@ textarea,
flex: 1; flex: 1;
} }
&[type=radio] { &[type="radio"] {
display: none; display: none;
&:checked + label::before { &:checked + label::before {
@ -555,7 +559,7 @@ textarea,
+ label::before { + label::before {
flex-shrink: 0; flex-shrink: 0;
display: inline-block; display: inline-block;
content: ''; content: "";
transition: box-shadow 200ms; transition: box-shadow 200ms;
width: 1.1em; width: 1.1em;
height: 1.1em; height: 1.1em;
@ -575,7 +579,7 @@ textarea,
} }
} }
&[type=checkbox] { &[type="checkbox"] {
display: none; display: none;
&:checked + label::before { &:checked + label::before {
@ -594,7 +598,7 @@ textarea,
+ label::before { + label::before {
flex-shrink: 0; flex-shrink: 0;
display: inline-block; display: inline-block;
content: ''; content: "";
transition: color 200ms; transition: color 200ms;
width: 1.1em; width: 1.1em;
height: 1.1em; height: 1.1em;
@ -634,10 +638,10 @@ option {
} }
.hide-number-spinner { .hide-number-spinner {
-moz-appearance: textfield; appearance: textfield;
&[type=number]::-webkit-inner-spin-button, &[type="number"]::-webkit-inner-spin-button,
&[type=number]::-webkit-outer-spin-button { &[type="number"]::-webkit-outer-spin-button {
opacity: 0; opacity: 0;
display: none; display: none;
} }
@ -669,8 +673,6 @@ option {
} }
} }
@import './panel.scss';
.fa { .fa {
color: grey; color: grey;
} }
@ -686,7 +688,7 @@ option {
max-width: 10em; max-width: 10em;
min-width: 1.7em; min-width: 1.7em;
height: 1.3em; height: 1.3em;
padding: 0.15em 0.15em; padding: 0.15em;
vertical-align: middle; vertical-align: middle;
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
@ -789,7 +791,8 @@ option {
.fa-old-padding { .fa-old-padding {
&.iconLetter, &.iconLetter,
&.svg-inline--fa, &-layer { &.svg-inline--fa,
&-layer {
padding: 0 0.3em; padding: 0 0.3em;
} }
} }
@ -883,3 +886,4 @@ option {
.fade-leave-active { .fade-leave-active {
opacity: 0; opacity: 0;
} }
/* stylelint-enable no-descending-specificity */

View file

@ -1,13 +1,14 @@
@mixin unfocused-style { @mixin unfocused-style {
@content; @content;
&:focus:not(:focus-visible):not(:hover) { &:focus:not(:focus-visible, :hover) {
@content; @content;
} }
} }
@mixin focused-style { @mixin focused-style {
&:hover, &:focus { &:hover,
&:focus {
@content; @content;
} }

View file

@ -4,20 +4,20 @@ $darkened-background: whitesmoke;
$fallback--bg: #121a24; $fallback--bg: #121a24;
$fallback--fg: #182230; $fallback--fg: #182230;
$fallback--faint: rgba(185, 185, 186, .5); $fallback--faint: rgb(185 185 186 / 50%);
$fallback--text: #b9b9ba; $fallback--text: #b9b9ba;
$fallback--link: #d8a070; $fallback--link: #d8a070;
$fallback--icon: #666; $fallback--icon: #666;
$fallback--lightBg: rgb(21, 30, 42); $fallback--lightBg: rgb(21 30 42);
$fallback--lightText: #b9b9ba; $fallback--lightText: #b9b9ba;
$fallback--border: #222; $fallback--border: #222;
$fallback--cRed: #ff0000; $fallback--cRed: #f00;
$fallback--cBlue: #0095ff; $fallback--cBlue: #0095ff;
$fallback--cGreen: #0fa00f; $fallback--cGreen: #0fa00f;
$fallback--cOrange: orange; $fallback--cOrange: orange;
$fallback--alertError: rgba(211,16,20,.5); $fallback--alertError: rgb(211 16 20 / 50%);
$fallback--alertWarning: rgba(111,111,20,.5); $fallback--alertWarning: rgb(111 111 20 / 50%);
$fallback--panelRadius: 10px; $fallback--panelRadius: 10px;
$fallback--checkboxRadius: 2px; $fallback--checkboxRadius: 2px;
@ -29,6 +29,8 @@ $fallback--avatarAltRadius: 10px;
$fallback--attachmentRadius: 10px; $fallback--attachmentRadius: 10px;
$fallback--chatMessageRadius: 10px; $fallback--chatMessageRadius: 10px;
$fallback--buttonShadow: 0px 0px 2px 0px rgba(0, 0, 0, 1), 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset, 0px -1px 0px 0px rgba(0, 0, 0, 0.2) inset; $fallback--buttonShadow: 0 0 2px 0 rgb(0 0 0 / 100%),
0 1px 0 0 rgb(255 255 255 / 20%) inset,
0 -1px 0 0 rgb(0 0 0 / 20%) inset;
$status-margin: 0.75em; $status-margin: 0.75em;

View file

@ -1,6 +1,8 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router' import { createRouter, createWebHistory } from 'vue-router'
import vClickOutside from 'click-outside-vue3' import vClickOutside from 'click-outside-vue3'
import VueVirtualScroller from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
import { FontAwesomeIcon, FontAwesomeLayers } from '@fortawesome/vue-fontawesome' import { FontAwesomeIcon, FontAwesomeLayers } from '@fortawesome/vue-fontawesome'
@ -397,6 +399,7 @@ const afterStoreSetup = async ({ store, i18n }) => {
app.use(vClickOutside) app.use(vClickOutside)
app.use(VBodyScrollLock) app.use(VBodyScrollLock)
app.use(VueVirtualScroller)
app.component('FAIcon', FontAwesomeIcon) app.component('FAIcon', FontAwesomeIcon)
app.component('FALayers', FontAwesomeLayers) app.component('FALayers', FontAwesomeLayers)

View file

@ -9,6 +9,3 @@
</template> </template>
<script src="./about.js"></script> <script src="./about.js"></script>
<style lang="scss">
</style>

View file

@ -80,7 +80,8 @@
<script src="./account_actions.js"></script> <script src="./account_actions.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.AccountActions { .AccountActions {
.ellipsis-button { .ellipsis-button {
width: 2.5em; width: 2.5em;

View file

@ -27,6 +27,9 @@ const Announcement = {
...mapState({ ...mapState({
currentUser: state => state.users.currentUser currentUser: state => state.users.currentUser
}), }),
canEditAnnouncement () {
return this.currentUser && this.currentUser.privileges.includes('announcements_manage_announcements')
},
content () { content () {
return this.announcement.content return this.announcement.content
}, },

View file

@ -45,14 +45,14 @@
{{ $t('announcements.mark_as_read_action') }} {{ $t('announcements.mark_as_read_action') }}
</button> </button>
<button <button
v-if="currentUser && currentUser.role === 'admin'" v-if="canEditAnnouncement"
class="btn button-default" class="btn button-default"
@click="enterEditMode" @click="enterEditMode"
> >
{{ $t('announcements.edit_action') }} {{ $t('announcements.edit_action') }}
</button> </button>
<button <button
v-if="currentUser && currentUser.role === 'admin'" v-if="canEditAnnouncement"
class="btn button-default" class="btn button-default"
@click="deleteAnnouncement" @click="deleteAnnouncement"
> >
@ -102,19 +102,19 @@
@import "../../variables"; @import "../../variables";
.announcement { .announcement {
border-bottom-width: 1px; border-bottom: 1px solid var(--border, $fallback--border);
border-bottom-style: solid;
border-bottom-color: var(--border, $fallback--border);
border-radius: 0; border-radius: 0;
padding: var(--status-margin, $status-margin); padding: var(--status-margin, $status-margin);
.heading, .body { .heading,
.body {
margin-bottom: var(--status-margin, $status-margin); margin-bottom: var(--status-margin, $status-margin);
} }
.footer { .footer {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.times { .times {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View file

@ -28,6 +28,9 @@ const AnnouncementsPage = {
}), }),
announcements () { announcements () {
return this.$store.state.announcements.announcements return this.$store.state.announcements.announcements
},
canPostAnnouncement () {
return this.currentUser && this.currentUser.privileges.includes('announcements_manage_announcements')
} }
}, },
methods: { methods: {

View file

@ -7,7 +7,7 @@
</div> </div>
<div class="panel-body"> <div class="panel-body">
<section <section
v-if="currentUser && currentUser.role === 'admin'" v-if="canPostAnnouncement"
> >
<div class="post-form"> <div class="post-form">
<div class="heading"> <div class="heading">
@ -67,7 +67,8 @@
.post-form { .post-form {
padding: var(--status-margin, $status-margin); padding: var(--status-margin, $status-margin);
.heading, .body { .heading,
.body {
margin-bottom: var(--status-margin, $status-margin); margin-bottom: var(--status-margin, $status-margin);
} }

View file

@ -34,9 +34,10 @@ export default {
height: 100%; height: 100%;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
.btn { .btn {
margin: .5em; margin: 0.5em;
padding: .5em 2em; padding: 0.5em 2em;
} }
} }
</style> </style>

View file

@ -36,6 +36,7 @@ library.add(
const Attachment = { const Attachment = {
props: [ props: [
'attachment', 'attachment',
'compact',
'description', 'description',
'hideDescription', 'hideDescription',
'nsfw', 'nsfw',
@ -71,7 +72,8 @@ const Attachment = {
{ {
'-loading': this.loading, '-loading': this.loading,
'-nsfw-placeholder': this.hidden, '-nsfw-placeholder': this.hidden,
'-editable': this.edit !== undefined '-editable': this.edit !== undefined,
'-compact': this.compact
}, },
'-type-' + this.type, '-type-' + this.type,
this.size && '-size-' + this.size, this.size && '-size-' + this.size,

View file

@ -1,4 +1,4 @@
@import '../../_variables.scss'; @import "../../variables";
.Attachment { .Attachment {
display: inline-flex; display: inline-flex;
@ -102,14 +102,13 @@
padding-top: 0.5em; padding-top: 0.5em;
} }
.play-icon { .play-icon {
position: absolute; position: absolute;
font-size: 64px; font-size: 64px;
top: calc(50% - 32px); top: calc(50% - 32px);
left: calc(50% - 32px); left: calc(50% - 32px);
color: rgba(255, 255, 255, 0.75); color: rgb(255 255 255 / 75%);
text-shadow: 0 0 2px rgba(0, 0, 0, 0.4); text-shadow: 0 0 2px rgb(0 0 0 / 40%);
&::before { &::before {
margin: 0; margin: 0;
@ -135,18 +134,32 @@
margin-left: 0.5em; margin-left: 0.5em;
font-size: 1.25em; font-size: 1.25em;
// TODO: theming? hard to theme with unknown background image color // TODO: theming? hard to theme with unknown background image color
background: rgba(230, 230, 230, 0.7); background: rgb(230 230 230 / 70%);
.svg-inline--fa { .svg-inline--fa {
color: rgba(0, 0, 0, 0.6); color: rgb(0 0 0 / 60%);
} }
&:hover .svg-inline--fa { &:hover .svg-inline--fa {
color: rgba(0, 0, 0, 0.9); color: rgb(0 0 0 / 90%);
} }
} }
} }
&.-contain-fit {
img,
canvas {
object-fit: contain;
}
}
&.-cover-fit {
img,
canvas {
object-fit: cover;
}
}
.oembed-container { .oembed-container {
line-height: 1.2em; line-height: 1.2em;
flex: 1 0 100%; flex: 1 0 100%;
@ -160,8 +173,9 @@
.image { .image {
flex: 1; flex: 1;
img { img {
border: 0px; border: 0;
border-radius: 5px; border-radius: 5px;
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
@ -172,9 +186,10 @@
flex: 2; flex: 2;
margin: 8px; margin: 8px;
word-break: break-all; word-break: break-all;
h1 { h1 {
font-size: 1rem; font-size: 1rem;
margin: 0px; margin: 0;
} }
} }
} }
@ -252,17 +267,9 @@
cursor: progress; cursor: progress;
} }
&.-contain-fit { &.-compact {
img, .placeholder-container {
canvas { padding-bottom: 0.5em;
object-fit: contain;
}
}
&.-cover-fit {
img,
canvas {
object-fit: cover;
} }
} }
} }

View file

@ -162,10 +162,11 @@
target="_blank" target="_blank"
> >
<FAIcon <FAIcon
size="5x" :size="compact ? '2x' : '5x'"
:icon="placeholderIconClass" :icon="placeholderIconClass"
:title="localDescription"
/> />
<p> <p v-if="!compact">
{{ localDescription }} {{ localDescription }}
</p> </p>
</a> </a>

View file

@ -24,7 +24,7 @@
<script src="./autosuggest.js"></script> <script src="./autosuggest.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.autosuggest { .autosuggest {
position: relative; position: relative;
@ -50,7 +50,7 @@
border-radius: var(--inputRadius, $fallback--inputRadius); border-radius: var(--inputRadius, $fallback--inputRadius);
border-top-left-radius: 0; border-top-left-radius: 0;
border-top-right-radius: 0; border-top-right-radius: 0;
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6); box-shadow: 1px 1px 4px rgb(0 0 0 / 60%);
box-shadow: var(--panelShadow); box-shadow: var(--panelShadow);
overflow-y: auto; overflow-y: auto;
z-index: 1; z-index: 1;

View file

@ -17,7 +17,7 @@
<script src="./avatar_list.js"></script> <script src="./avatar_list.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.avatars { .avatars {
display: flex; display: flex;

View file

@ -49,7 +49,7 @@
margin: 0; margin: 0;
padding: 0.6em 1em; padding: 0.6em 1em;
--emoji-size: 14px; --emoji-size: 14px;
&-collapsed-content { &-collapsed-content {
margin-left: 0.7em; margin-left: 0.7em;

View file

@ -37,6 +37,7 @@
.block-card-content-container { .block-card-content-container {
margin-top: 0.5em; margin-top: 0.5em;
text-align: right; text-align: right;
button { button {
width: 10em; width: 10em;
} }

View file

@ -17,7 +17,7 @@
width: 100%; width: 100%;
overflow: visible; overflow: visible;
min-height: calc(100vh - var(--navbar-height)); min-height: calc(100vh - var(--navbar-height));
margin: 0 0 0 0; margin: 0;
border-radius: 10px 10px 0 0; border-radius: 10px 10px 0 0;
border-radius: var(--panelRadius, 10px) var(--panelRadius, 10px) 0 0; border-radius: var(--panelRadius, 10px) var(--panelRadius, 10px) 0 0;
@ -66,7 +66,7 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3), 0 2px 4px rgba(0, 0, 0, 0.3); box-shadow: 0 1px 1px rgb(0 0 0 / 30%), 0 2px 4px rgb(0 0 0 / 30%);
z-index: 10; z-index: 10;
transition: 0.35s all; transition: 0.35s all;
transition-timing-function: cubic-bezier(0, 1, 0.5, 1); transition-timing-function: cubic-bezier(0, 1, 0.5, 1);

View file

@ -95,6 +95,6 @@
<script src="./chat.js"></script> <script src="./chat.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
@import './chat.scss'; @import "./chat";
</style> </style>

View file

@ -45,7 +45,7 @@
<script src="./chat_list.js"></script> <script src="./chat_list.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.chat-list { .chat-list {
min-height: 25em; min-height: 25em;

View file

@ -13,7 +13,7 @@
&:hover { &:hover {
background-color: var(--selectedPost, $fallback--lightBg); background-color: var(--selectedPost, $fallback--lightBg);
box-shadow: 0 0 3px 1px rgba(0, 0, 0, 0.1); box-shadow: 0 0 3px 1px rgb(0 0 0 / 10%);
} }
.chat-list-item-left { .chat-list-item-left {
@ -67,6 +67,7 @@
canvas { canvas {
display: none; display: none;
} }
img { img {
visibility: visible; visibility: visible;
} }
@ -79,13 +80,11 @@
.chat-preview-body { .chat-preview-body {
--emoji-size: 1.4em; --emoji-size: 1.4em;
padding-right: 1em;
} }
.time-wrapper { .time-wrapper {
line-height: var(--post-line-height); line-height: var(--post-line-height);
} }
.chat-preview-body {
padding-right: 1em;
}
} }

View file

@ -48,6 +48,6 @@
<script src="./chat_list_item.js"></script> <script src="./chat_list_item.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
@import './chat_list_item.scss'; @import "./chat_list_item";
</style> </style>

View file

@ -1,12 +1,12 @@
@import '../../_variables.scss'; @import "../../variables";
.chat-message-wrapper { .chat-message-wrapper {
&.hovered-message-chain { &.hovered-message-chain {
.animated.Avatar { .animated.Avatar {
canvas { canvas {
display: none; display: none;
} }
img { img {
visibility: visible; visibility: visible;
} }
@ -28,7 +28,8 @@
.menu-icon { .menu-icon {
cursor: pointer; cursor: pointer;
&:hover, .extra-button-popover.open & { &:hover,
.extra-button-popover.open & {
color: $fallback--text; color: $fallback--text;
color: var(--text, $fallback--text); color: var(--text, $fallback--text);
} }
@ -54,27 +55,11 @@
width: 32px; width: 32px;
} }
.link-preview, .attachments { .link-preview,
.attachments {
margin-bottom: 1em; margin-bottom: 1em;
} }
.chat-message-inner {
display: flex;
flex-direction: column;
align-items: flex-start;
max-width: 80%;
min-width: 10em;
width: 100%;
&.with-media {
width: 100%;
.status {
width: 100%;
}
}
}
.status { .status {
border-radius: $fallback--chatMessageRadius; border-radius: $fallback--chatMessageRadius;
border-radius: var(--chatMessageRadius, $fallback--chatMessageRadius); border-radius: var(--chatMessageRadius, $fallback--chatMessageRadius);
@ -86,7 +71,7 @@
position: relative; position: relative;
float: right; float: right;
font-size: 0.8em; font-size: 0.8em;
margin: -1em 0 -0.5em 0; margin: -1em 0 -0.5em;
font-style: italic; font-style: italic;
opacity: 0.8; opacity: 0.8;
} }
@ -103,18 +88,54 @@
} }
.pending { .pending {
.status-content.media-body, .created-at { .status-content.media-body,
.created-at {
color: var(--faint); color: var(--faint);
} }
} }
.error { .error {
.status-content.media-body, .created-at { .status-content.media-body,
.created-at {
color: $fallback--cRed; color: $fallback--cRed;
color: var(--badgeNotification, $fallback--cRed); color: var(--badgeNotification, $fallback--cRed);
} }
} }
.chat-message-inner {
display: flex;
flex-direction: column;
align-items: flex-start;
max-width: 80%;
min-width: 10em;
width: 100%;
}
.outgoing {
display: flex;
flex-flow: row wrap;
align-content: end;
justify-content: flex-end;
a {
color: var(--chatMessageOutgoingLink, $fallback--link);
}
.status {
color: var(--chatMessageOutgoingText, $fallback--text);
background-color: var(--chatMessageOutgoingBg, $fallback--lightBg);
border: 1px solid var(--chatMessageOutgoingBorder, --lightBg);
}
.chat-message-inner {
align-items: flex-end;
}
.chat-message-menu {
right: 0.4rem;
}
}
.incoming { .incoming {
a { a {
color: var(--chatMessageIncomingLink, $fallback--link); color: var(--chatMessageIncomingLink, $fallback--link);
@ -137,36 +158,17 @@
} }
} }
.outgoing { .chat-message-inner.with-media {
display: flex; width: 100%;
flex-direction: row;
flex-wrap: wrap;
align-content: end;
justify-content: flex-end;
a {
color: var(--chatMessageOutgoingLink, $fallback--link);
}
.status { .status {
color: var(--chatMessageOutgoingText, $fallback--text); width: 100%;
background-color: var(--chatMessageOutgoingBg, $fallback--lightBg);
border: 1px solid var(--chatMessageOutgoingBorder, --lightBg);
}
.chat-message-inner {
align-items: flex-end;
}
.chat-message-menu {
right: 0.4rem;
} }
} }
.visible { .visible {
opacity: 1; opacity: 1;
} }
} }
.chat-message-date-separator { .chat-message-date-separator {

View file

@ -33,7 +33,7 @@
<div <div
class="media status" class="media status"
:class="{ 'without-attachment': !hasAttachment, 'pending': chatViewItem.data.pending, 'error': chatViewItem.data.error }" :class="{ 'without-attachment': !hasAttachment, 'pending': chatViewItem.data.pending, 'error': chatViewItem.data.error }"
style="position: relative" style="position: relative;"
@mouseenter="hovered = true" @mouseenter="hovered = true"
@mouseleave="hovered = false" @mouseleave="hovered = false"
> >
@ -98,6 +98,6 @@
<script src="./chat_message.js"></script> <script src="./chat_message.js"></script>
<style lang="scss"> <style lang="scss">
@import './chat_message.scss'; @import "./chat_message";
</style> </style>

View file

@ -1,7 +1,7 @@
.chat-new { .chat-new {
.input-wrap { .input-wrap {
display: flex; display: flex;
margin: 0.7em 0.5em 0.7em 0.5em; margin: 0.7em 0.5em;
input { input {
width: 100%; width: 100%;

View file

@ -46,6 +46,6 @@
<script src="./chat_new.js"></script> <script src="./chat_new.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
@import './chat_new.scss'; @import "./chat_new";
</style> </style>

View file

@ -26,7 +26,7 @@
<script src="./chat_title.js"></script> <script src="./chat_title.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.chat-title { .chat-title {
display: flex; display: flex;

View file

@ -32,7 +32,7 @@ export default {
</script> </script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.checkbox { .checkbox {
position: relative; position: relative;
@ -49,13 +49,13 @@ export default {
right: 0; right: 0;
top: 0; top: 0;
display: block; display: block;
content: '✓'; content: "✓";
transition: color 200ms; transition: color 200ms;
width: 1.1em; width: 1.1em;
height: 1.1em; height: 1.1em;
border-radius: $fallback--checkboxRadius; border-radius: $fallback--checkboxRadius;
border-radius: var(--checkboxRadius, $fallback--checkboxRadius); border-radius: var(--checkboxRadius, $fallback--checkboxRadius);
box-shadow: 0px 0px 2px black inset; box-shadow: 0 0 2px black inset;
box-shadow: var(--inputShadow); box-shadow: var(--inputShadow);
background-color: $fallback--fg; background-color: $fallback--fg;
background-color: var(--input, $fallback--fg); background-color: var(--input, $fallback--fg);
@ -71,15 +71,16 @@ export default {
&.disabled { &.disabled {
.checkbox-indicator::before, .checkbox-indicator::before,
.label { .label {
opacity: .5; opacity: 0.5;
} }
.label { .label {
color: $fallback--faint; color: $fallback--faint;
color: var(--faint, $fallback--faint); color: var(--faint, $fallback--faint);
} }
} }
input[type=checkbox] { input[type="checkbox"] {
display: none; display: none;
&:checked + .checkbox-indicator::before { &:checked + .checkbox-indicator::before {
@ -88,15 +89,14 @@ export default {
} }
&:indeterminate + .checkbox-indicator::before { &:indeterminate + .checkbox-indicator::before {
content: ''; content: "";
color: $fallback--text; color: $fallback--text;
color: var(--inputText, $fallback--text); color: var(--inputText, $fallback--text);
} }
} }
& > span { & > span {
margin-left: .5em; margin-left: 0.5em;
} }
} }
</style> </style>

View file

@ -1,4 +1,4 @@
@import '../../_variables.scss'; @import "../../variables";
.color-input { .color-input {
display: inline-flex; display: inline-flex;
@ -8,7 +8,7 @@
flex: 0 0 0; flex: 0 0 0;
max-width: 9em; max-width: 9em;
align-items: stretch; align-items: stretch;
padding: .2em 8px; padding: 0.2em 8px;
input { input {
background: none; background: none;
@ -31,6 +31,7 @@
min-height: 100%; min-height: 100%;
} }
} }
.computedIndicator, .computedIndicator,
.transparentIndicator { .transparentIndicator {
flex: 0 0 2em; flex: 0 0 2em;
@ -38,22 +39,27 @@
align-self: stretch; align-self: stretch;
min-height: 100%; min-height: 100%;
} }
.transparentIndicator { .transparentIndicator {
// forgot to install counter-strike source, ooops // forgot to install counter-strike source, ooops
background-color: #FF00FF; background-color: #f0f;
position: relative; position: relative;
&::before, &::after {
&::before,
&::after {
display: block; display: block;
content: ''; content: "";
background-color: #000000; background-color: #000;
position: absolute; position: absolute;
height: 50%; height: 50%;
width: 50%; width: 50%;
} }
&::after { &::after {
top: 0; top: 0;
left: 0; left: 0;
} }
&::before { &::before {
bottom: 0; bottom: 0;
right: 0; right: 0;
@ -64,5 +70,4 @@
.label { .label {
flex: 1 1 auto; flex: 1 1 auto;
} }
} }

View file

@ -87,7 +87,6 @@ export default {
.contrast-ratio { .contrast-ratio {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
margin-top: -4px; margin-top: -4px;
margin-bottom: 5px; margin-bottom: 5px;

View file

@ -210,17 +210,16 @@
<script src="./conversation.js"></script> <script src="./conversation.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.Conversation { .Conversation {
z-index: 1; z-index: 1;
.conversation-dive-to-top-level-box { .conversation-dive-to-top-level-box {
padding: var(--status-margin, $status-margin); padding: var(--status-margin, $status-margin);
border-bottom-width: 1px; border-bottom: 1px solid var(--border, $fallback--border);
border-bottom-style: solid;
border-bottom-color: var(--border, $fallback--border);
border-radius: 0; border-radius: 0;
/* Make the button stretch along the whole row */ /* Make the button stretch along the whole row */
display: flex; display: flex;
align-items: stretch; align-items: stretch;
@ -235,52 +234,48 @@
.thread-ancestor.-faded .StatusContent { .thread-ancestor.-faded .StatusContent {
--link: var(--faintLink); --link: var(--faintLink);
--text: var(--faint); --text: var(--faint);
color: var(--text); color: var(--text);
} }
.thread-ancestor-dive-box { .thread-ancestor-dive-box {
padding-left: var(--status-margin, $status-margin); padding-left: var(--status-margin, $status-margin);
border-bottom-width: 1px; border-bottom: 1px solid var(--border, $fallback--border);
border-bottom-style: solid;
border-bottom-color: var(--border, $fallback--border);
border-radius: 0; border-radius: 0;
/* Make the button stretch along the whole row */ /* Make the button stretch along the whole row */
&, &-inner { &,
&-inner {
display: flex; display: flex;
align-items: stretch; align-items: stretch;
flex-direction: column; flex-direction: column;
} }
} }
.thread-ancestor-dive-box-inner { .thread-ancestor-dive-box-inner {
padding: var(--status-margin, $status-margin); padding: var(--status-margin, $status-margin);
} }
.conversation-status { .conversation-status {
border-bottom-width: 1px; border-bottom: 1px solid var(--border, $fallback--border);
border-bottom-style: solid;
border-bottom-color: var(--border, $fallback--border);
border-radius: 0; border-radius: 0;
} }
.thread-ancestor-has-other-replies .conversation-status, .thread-ancestor-has-other-replies .conversation-status,
&:last-child .conversation-status,
.thread-ancestor:last-child .conversation-status, .thread-ancestor:last-child .conversation-status,
.thread-ancestor:last-child .thread-ancestor-dive-box, .thread-ancestor:last-child .thread-ancestor-dive-box,
&:last-child .conversation-status,
&.-expanded .thread-tree .conversation-status { &.-expanded .thread-tree .conversation-status {
border-bottom: none; border-bottom: none;
} }
.thread-ancestors + .thread-tree > .conversation-status { .thread-ancestors + .thread-tree > .conversation-status {
border-top-width: 1px; border-top: 1px solid var(--border, $fallback--border);
border-top-style: solid;
border-top-color: var(--border, $fallback--border);
} }
/* expanded conversation in timeline */ /* expanded conversation in timeline */
&.status-fadein.-expanded .thread-body { &.status-fadein.-expanded .thread-body {
border-left-width: 4px; border-left: 4px solid $fallback--cRed;
border-left-style: solid;
border-left-color: $fallback--cRed;
border-left-color: var(--cRed, $fallback--cRed); border-left-color: var(--cRed, $fallback--cRed);
border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius; border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius;
border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius); border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius);

View file

@ -1,4 +1,4 @@
@import '../../_variables.scss'; @import "../../variables";
.DesktopNav { .DesktopNav {
width: 100%; width: 100%;
@ -27,20 +27,13 @@
--miniColumn: 25rem; --miniColumn: 25rem;
--maxiColumn: 45rem; --maxiColumn: 45rem;
--columnGap: 1em; --columnGap: 1em;
max-width: calc(
var(--sidebarColumnWidth, var(--miniColumn)) +
var(--contentColumnWidth, var(--maxiColumn)) +
var(--columnGap)
);
}
&.-column-stretch.-wide .inner-nav { max-width:
max-width: calc( calc(
var(--sidebarColumnWidth, var(--miniColumn)) + var(--sidebarColumnWidth, var(--miniColumn)) +
var(--contentColumnWidth, var(--maxiColumn)) + var(--contentColumnWidth, var(--maxiColumn)) +
var(--notifsColumnWidth, var(--miniColumn)) + var(--columnGap)
var(--columnGap) );
);
} }
&.-logoLeft .inner-nav { &.-logoLeft .inner-nav {
@ -48,8 +41,19 @@
grid-template-areas: "logo sitename actions"; grid-template-areas: "logo sitename actions";
} }
&.-column-stretch.-wide .inner-nav {
max-width:
calc(
var(--sidebarColumnWidth, var(--miniColumn)) +
var(--contentColumnWidth, var(--maxiColumn)) +
var(--notifsColumnWidth, var(--miniColumn)) +
var(--columnGap)
);
}
.button-default { .button-default {
&, svg { &,
svg {
color: $fallback--text; color: $fallback--text;
color: var(--btnTopBarText, $fallback--text); color: var(--btnTopBarText, $fallback--text);
} }
@ -70,7 +74,7 @@
color: $fallback--text; color: $fallback--text;
color: var(--btnToggledTopBarText, $fallback--text); color: var(--btnToggledTopBarText, $fallback--text);
background-color: $fallback--fg; background-color: $fallback--fg;
background-color: var(--btnToggledTopBar, $fallback--fg) background-color: var(--btnToggledTopBar, $fallback--fg);
} }
} }
@ -82,6 +86,7 @@
transition-duration: 100ms; transition-duration: 100ms;
@media all and (min-width: 800px) { @media all and (min-width: 800px) {
/* stylelint-disable-next-line declaration-no-important */
opacity: 1 !important; opacity: 1 !important;
} }

View file

@ -38,7 +38,7 @@
/> />
<button <button
class="button-unstyled nav-icon" class="button-unstyled nav-icon"
@click="openSettingsModal" @click.stop="openSettingsModal"
> >
<FAIcon <FAIcon
fixed-width fixed-width
@ -65,7 +65,7 @@
<button <button
v-if="currentUser" v-if="currentUser"
class="button-unstyled nav-icon" class="button-unstyled nav-icon"
@click.prevent="logout" @click.stop.prevent="logout"
> >
<FAIcon <FAIcon
fixed-width fixed-width

View file

@ -25,7 +25,7 @@
<script src="./dialog_modal.js"></script> <script src="./dialog_modal.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
// TODO: unify with other modals. // TODO: unify with other modals.
.dark-overlay { .dark-overlay {
@ -38,7 +38,7 @@
position: fixed; position: fixed;
right: 0; right: 0;
top: 0; top: 0;
background: rgba(27,31,35,.5); background: rgb(27 31 35 / 50%);
z-index: 99; z-index: 99;
} }
} }
@ -65,7 +65,7 @@
.dialog-modal-content { .dialog-modal-content {
margin: 0; margin: 0;
padding: 1rem 1rem; padding: 1rem;
background-color: $fallback--bg; background-color: $fallback--bg;
background-color: var(--bg, $fallback--bg); background-color: var(--bg, $fallback--bg);
white-space: normal; white-space: normal;
@ -73,7 +73,7 @@
.dialog-modal-footer { .dialog-modal-footer {
margin: 0; margin: 0;
padding: .5em .5em; padding: 0.5em;
background-color: $fallback--bg; background-color: $fallback--bg;
background-color: var(--bg, $fallback--bg); background-color: var(--bg, $fallback--bg);
border-top: 1px solid $fallback--border; border-top: 1px solid $fallback--border;
@ -83,7 +83,7 @@
button { button {
width: auto; width: auto;
margin-left: .5rem; margin-left: 0.5rem;
} }
} }
} }

View file

@ -26,6 +26,7 @@
.modal-view.edit-form-modal-view { .modal-view.edit-form-modal-view {
align-items: flex-start; align-items: flex-start;
} }
.edit-form-modal-panel { .edit-form-modal-panel {
flex-shrink: 0; flex-shrink: 0;
margin-top: 25%; margin-top: 25%;

View file

@ -91,22 +91,18 @@
<script src="./emoji_input.js"></script> <script src="./emoji_input.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.emoji-input { .emoji-input {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative; position: relative;
&.with-picker input {
padding-right: 30px;
}
.emoji-picker-icon { .emoji-picker-icon {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
margin: .2em .25em; margin: 0.2em 0.25em;
font-size: 1.3em; font-size: 1.3em;
cursor: pointer; cursor: pointer;
line-height: 24px; line-height: 24px;
@ -123,14 +119,19 @@
margin-top: 2px; margin-top: 2px;
&.hide { &.hide {
display: none display: none;
} }
} }
input, textarea { input,
textarea {
flex: 1 0 auto; flex: 1 0 auto;
} }
&.with-picker input {
padding-right: 30px;
}
.hidden-overlay { .hidden-overlay {
opacity: 0; opacity: 0;
pointer-events: none; pointer-events: none;
@ -140,8 +141,10 @@
right: 0; right: 0;
left: 0; left: 0;
overflow: hidden; overflow: hidden;
/* DEBUG STUFF */ /* DEBUG STUFF */
color: red; color: red;
/* set opacity to non-zero to see the overlay */ /* set opacity to non-zero to see the overlay */
.caret { .caret {
@ -151,6 +154,7 @@
} }
} }
} }
.autocomplete { .autocomplete {
&-panel { &-panel {
position: absolute; position: absolute;
@ -160,7 +164,7 @@
display: flex; display: flex;
cursor: pointer; cursor: pointer;
padding: 0.2em 0.4em; padding: 0.2em 0.4em;
border-bottom: 1px solid rgba(0, 0, 0, 0.4); border-bottom: 1px solid rgb(0 0 0 / 40%);
height: 32px; height: 32px;
.image { .image {
@ -169,7 +173,6 @@
line-height: 32px; line-height: 32px;
text-align: center; text-align: center;
font-size: 32px; font-size: 32px;
margin-right: 4px; margin-right: 4px;
img { img {
@ -199,6 +202,7 @@
background-color: $fallback--fg; background-color: $fallback--fg;
background-color: var(--selectedMenuPopover, $fallback--fg); background-color: var(--selectedMenuPopover, $fallback--fg);
color: var(--selectedMenuPopoverText, $fallback--text); color: var(--selectedMenuPopoverText, $fallback--text);
--faint: var(--selectedMenuPopoverFaintText, $fallback--faint); --faint: var(--selectedMenuPopoverFaintText, $fallback--faint);
--faintLink: var(--selectedMenuPopoverFaintLink, $fallback--faint); --faintLink: var(--selectedMenuPopoverFaintLink, $fallback--faint);
--lightText: var(--selectedMenuPopoverLightText, $fallback--lightText); --lightText: var(--selectedMenuPopoverLightText, $fallback--lightText);

View file

@ -3,7 +3,6 @@ import Checkbox from '../checkbox/checkbox.vue'
import Popover from 'src/components/popover/popover.vue' import Popover from 'src/components/popover/popover.vue'
import StillImage from '../still-image/still-image.vue' import StillImage from '../still-image/still-image.vue'
import { ensureFinalFallback } from '../../i18n/languages.js' import { ensureFinalFallback } from '../../i18n/languages.js'
import lozad from 'lozad'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
faBoxOpen, faBoxOpen,
@ -19,7 +18,7 @@ import {
faCode, faCode,
faFlag faFlag
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
import { debounce, trim } from 'lodash' import { debounce, trim, chunk } from 'lodash'
library.add( library.add(
faBoxOpen, faBoxOpen,
@ -82,6 +81,17 @@ const filterByKeyword = (list, keyword = '', languages, nameLocalizer) => {
return orderedEmojiList.flat() return orderedEmojiList.flat()
} }
const getOffset = (elem) => {
const style = elem.style.transform
const res = /translateY\((\d+)px\)/.exec(style)
if (!res) { return 0 }
return res[1]
}
const toHeaderId = id => {
return id.replace(/^row-\d+-/, '')
}
const EmojiPicker = { const EmojiPicker = {
props: { props: {
enableStickerPicker: { enableStickerPicker: {
@ -102,7 +112,8 @@ const EmojiPicker = {
contentLoaded: false, contentLoaded: false,
groupRefs: {}, groupRefs: {},
emojiRefs: {}, emojiRefs: {},
filteredEmojiGroups: [] filteredEmojiGroups: [],
width: 0
} }
}, },
components: { components: {
@ -125,9 +136,6 @@ const EmojiPicker = {
setGroupRef (name) { setGroupRef (name) {
return el => { this.groupRefs[name] = el } return el => { this.groupRefs[name] = el }
}, },
setEmojiRef (name) {
return el => { this.emojiRefs[name] = el }
},
onPopoverShown () { onPopoverShown () {
this.$emit('show') this.$emit('show')
}, },
@ -147,18 +155,21 @@ const EmojiPicker = {
} }
this.$emit('emoji', { insertion: value, keepOpen: this.keepOpen }) this.$emit('emoji', { insertion: value, keepOpen: this.keepOpen })
}, },
onScroll (e) { onScroll (startIndex, endIndex, visibleStartIndex, visibleEndIndex) {
const target = (e && e.target) || this.$refs['emoji-groups'] const target = this.$refs['emoji-groups'].$el
this.updateScrolledClass(target) this.scrolledGroup(target, visibleStartIndex, visibleEndIndex)
this.scrolledGroup(target)
}, },
scrolledGroup (target) { scrolledGroup (target, start, end) {
const top = target.scrollTop + 5 const top = target.scrollTop + 5
this.$nextTick(() => { this.$nextTick(() => {
this.allEmojiGroups.forEach(group => { this.emojiItems.slice(start, end + 1).forEach(group => {
const headerId = toHeaderId(group.id)
const ref = this.groupRefs['group-' + group.id] const ref = this.groupRefs['group-' + group.id]
if (ref && ref.offsetTop <= top) { if (!ref) { return }
this.activeGroup = group.id const elem = ref.$el.parentElement
if (!elem) { return }
if (elem && getOffset(elem) <= top) {
this.activeGroup = headerId
} }
}) })
this.scrollHeader() this.scrollHeader()
@ -181,14 +192,10 @@ const EmojiPicker = {
setScroll(right + margin - headerCont.clientWidth) setScroll(right + margin - headerCont.clientWidth)
} }
}, },
highlight (key) { highlight (groupId) {
const ref = this.groupRefs['group-' + key]
const top = ref.offsetTop
this.setShowStickers(false) this.setShowStickers(false)
this.activeGroup = key const indexInList = this.emojiItems.findIndex(k => k.id === groupId)
this.$nextTick(() => { this.$refs['emoji-groups'].scrollToItem(indexInList)
this.$refs['emoji-groups'].scrollTop = top + 1
})
}, },
updateScrolledClass (target) { updateScrolledClass (target) {
if (target.scrollTop <= 5) { if (target.scrollTop <= 5) {
@ -208,43 +215,13 @@ const EmojiPicker = {
filterByKeyword (list, keyword) { filterByKeyword (list, keyword) {
return filterByKeyword(list, keyword, this.languages, this.maybeLocalizedEmojiName) return filterByKeyword(list, keyword, this.languages, this.maybeLocalizedEmojiName)
}, },
initializeLazyLoad () {
this.destroyLazyLoad()
this.$nextTick(() => {
this.$lozad = lozad('.still-image.emoji-picker-emoji', {
load: el => {
const name = el.getAttribute('data-emoji-name')
const vn = this.emojiRefs[name]
if (!vn) {
return
}
vn.loadLazy()
}
})
this.$lozad.observe()
})
},
waitForDomAndInitializeLazyLoad () {
this.$nextTick(() => this.initializeLazyLoad())
},
destroyLazyLoad () {
if (this.$lozad) {
if (this.$lozad.observer) {
this.$lozad.observer.disconnect()
}
if (this.$lozad.mutationObserver) {
this.$lozad.mutationObserver.disconnect()
}
}
},
onShowing () { onShowing () {
const oldContentLoaded = this.contentLoaded const oldContentLoaded = this.contentLoaded
this.recalculateItemPerRow()
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.search.focus() this.$refs.search.focus()
}) })
this.contentLoaded = true this.contentLoaded = true
this.waitForDomAndInitializeLazyLoad()
this.filteredEmojiGroups = this.getFilteredEmojiGroups() this.filteredEmojiGroups = this.getFilteredEmojiGroups()
if (!oldContentLoaded) { if (!oldContentLoaded) {
this.$nextTick(() => { this.$nextTick(() => {
@ -261,6 +238,14 @@ const EmojiPicker = {
emojis: this.filterByKeyword(group.emojis, trim(this.keyword)) emojis: this.filterByKeyword(group.emojis, trim(this.keyword))
})) }))
.filter(group => group.emojis.length > 0) .filter(group => group.emojis.length > 0)
},
recalculateItemPerRow () {
this.$nextTick(() => {
if (!this.$refs['emoji-groups']) {
return
}
this.width = this.$refs['emoji-groups'].$el.clientWidth
})
} }
}, },
watch: { watch: {
@ -269,14 +254,22 @@ const EmojiPicker = {
this.debouncedHandleKeywordChange() this.debouncedHandleKeywordChange()
}, },
allCustomGroups () { allCustomGroups () {
this.waitForDomAndInitializeLazyLoad()
this.filteredEmojiGroups = this.getFilteredEmojiGroups() this.filteredEmojiGroups = this.getFilteredEmojiGroups()
} }
}, },
destroyed () {
this.destroyLazyLoad()
},
computed: { computed: {
minItemSize () {
return this.emojiHeight
},
emojiHeight () {
return 32 + 4
},
emojiWidth () {
return 32 + 4
},
itemPerRow () {
return this.width ? Math.floor(this.width / this.emojiWidth - 1) : 6
},
activeGroupView () { activeGroupView () {
return this.showingStickers ? '' : this.activeGroup return this.showingStickers ? '' : this.activeGroup
}, },
@ -287,7 +280,11 @@ const EmojiPicker = {
return 0 return 0
}, },
allCustomGroups () { allCustomGroups () {
return this.$store.getters.groupedCustomEmojis const emojis = this.$store.getters.groupedCustomEmojis
if (emojis.unpacked) {
emojis.unpacked.text = this.$t('emoji.unpacked')
}
return emojis
}, },
defaultGroup () { defaultGroup () {
return Object.keys(this.allCustomGroups)[0] return Object.keys(this.allCustomGroups)[0]
@ -310,10 +307,20 @@ const EmojiPicker = {
}, },
debouncedHandleKeywordChange () { debouncedHandleKeywordChange () {
return debounce(() => { return debounce(() => {
this.waitForDomAndInitializeLazyLoad()
this.filteredEmojiGroups = this.getFilteredEmojiGroups() this.filteredEmojiGroups = this.getFilteredEmojiGroups()
}, 500) }, 500)
}, },
emojiItems () {
return this.filteredEmojiGroups.map(group =>
chunk(group.emojis, this.itemPerRow)
.map((items, index) => ({
...group,
id: index === 0 ? group.id : `row-${index}-${group.id}`,
emojis: items,
isFirstRow: index === 0
})))
.reduce((a, c) => a.concat(c), [])
},
languages () { languages () {
return ensureFinalFallback(this.$store.getters.mergedConfig.interfaceLanguage) return ensureFinalFallback(this.$store.getters.mergedConfig.interfaceLanguage)
}, },

View file

@ -1,4 +1,4 @@
@import '../../_variables.scss'; @import "../../variables";
$emoji-picker-header-height: 36px; $emoji-picker-header-height: 36px;
$emoji-picker-header-picture-width: 32px; $emoji-picker-header-picture-width: 32px;
@ -7,14 +7,14 @@ $emoji-picker-emoji-size: 32px;
.emoji-picker { .emoji-picker {
width: 25em; width: 25em;
max-width: 100vw; max-width: calc(100vw - 20px); // popover gives 10px margin from window edge
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background-color: $fallback--bg; background-color: $fallback--bg;
background-color: var(--popover, $fallback--bg); background-color: var(--popover, $fallback--bg);
color: $fallback--link; color: $fallback--link;
color: var(--popoverText, $fallback--link); color: var(--popoverText, $fallback--link);
--lightText: var(--popoverLightText, $fallback--faint);
--faint: var(--popoverFaintText, $fallback--faint); --faint: var(--popoverFaintText, $fallback--faint);
--faintLink: var(--popoverFaintLink, $fallback--faint); --faintLink: var(--popoverFaintLink, $fallback--faint);
--lightText: var(--popoverLightText, $fallback--lightText); --lightText: var(--popoverLightText, $fallback--lightText);
@ -28,6 +28,7 @@ $emoji-picker-emoji-size: 32px;
max-width: $emoji-picker-header-picture-width; max-width: $emoji-picker-header-picture-width;
height: $emoji-picker-header-picture-height; height: $emoji-picker-header-picture-height;
max-height: $emoji-picker-header-picture-height; max-height: $emoji-picker-header-picture-height;
.still-image { .still-image {
max-width: 100%; max-width: 100%;
max-height: 100%; max-height: 100%;
@ -62,24 +63,18 @@ $emoji-picker-emoji-size: 32px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1 1 auto; flex: 1 1 auto;
min-height: 0px; min-height: 0;
} }
.emoji-tabs { .emoji-tabs {
flex-grow: 1; flex-grow: 1;
display: flex; display: flex;
flex-direction: row; flex-flow: row nowrap;
flex-wrap: nowrap;
overflow-x: auto; overflow-x: auto;
} }
.emoji-groups {
min-height: 200px;
}
.additional-tabs { .additional-tabs {
display: flex; display: flex;
flex: 1;
border-left: 1px solid; border-left: 1px solid;
border-left-color: $fallback--icon; border-left-color: $fallback--icon;
border-left-color: var(--icon, $fallback--icon); border-left-color: var(--icon, $fallback--icon);
@ -121,7 +116,7 @@ $emoji-picker-emoji-size: 32px;
} }
.sticker-picker { .sticker-picker {
flex: 1 1 auto flex: 1 1 auto;
} }
.stickers, .stickers,
@ -151,22 +146,27 @@ $emoji-picker-emoji-size: 32px;
} }
&-groups { &-groups {
height: 100%;
min-height: 200px;
flex: 1 1 1px; flex: 1 1 1px;
position: relative; position: relative;
overflow: auto; overflow: auto;
user-select: none; user-select: none;
mask: linear-gradient(to top, white 0, transparent 100%) bottom no-repeat, mask:
linear-gradient(to bottom, white 0, transparent 100%) top no-repeat, linear-gradient(to top, white 0, transparent 100%) bottom no-repeat,
linear-gradient(to top, white, white); linear-gradient(to bottom, white 0, transparent 100%) top no-repeat,
linear-gradient(to top, white, white);
transition: mask-size 150ms; transition: mask-size 150ms;
mask-size: 100% 20px, 100% 20px, auto; mask-size: 100% 20px, 100% 20px, auto;
// Autoprefixed seem to ignore this one, and also syntax is different // Autoprefixed seem to ignore this one, and also syntax is different
-webkit-mask-composite: xor; mask-composite: xor;
mask-composite: exclude; mask-composite: exclude;
&.scrolled { &.scrolled {
&-top { &-top {
mask-size: 100% 20px, 100% 0, auto; mask-size: 100% 20px, 100% 0, auto;
} }
&-bottom { &-bottom {
mask-size: 100% 0, 100% 20px, auto; mask-size: 100% 0, 100% 20px, auto;
} }
@ -200,7 +200,6 @@ $emoji-picker-emoji-size: 32px;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin: 4px; margin: 4px;
cursor: pointer; cursor: pointer;
.emoji-picker-emoji.-custom { .emoji-picker-emoji.-custom {
@ -208,12 +207,11 @@ $emoji-picker-emoji-size: 32px;
max-width: 100%; max-width: 100%;
max-height: 100%; max-height: 100%;
} }
.emoji-picker-emoji.-unicode { .emoji-picker-emoji.-unicode {
font-size: 24px; font-size: 24px;
overflow: hidden; overflow: hidden;
} }
} }
} }
} }

View file

@ -74,45 +74,57 @@
@input="$event.target.composing = false" @input="$event.target.composing = false"
> >
</div> </div>
<div <DynamicScroller
ref="emoji-groups" ref="emoji-groups"
class="emoji-groups" class="emoji-groups"
:class="groupsScrolledClass" :class="groupsScrolledClass"
@scroll="onScroll" :min-item-size="minItemSize"
:items="emojiItems"
:emit-update="true"
@update="onScroll"
@visible="recalculateItemPerRow"
@resize="recalculateItemPerRow"
> >
<div <template #default="{ item: group, index, active }">
v-for="group in filteredEmojiGroups" <DynamicScrollerItem
:key="group.id"
class="emoji-group"
>
<h6
:ref="setGroupRef('group-' + group.id)" :ref="setGroupRef('group-' + group.id)"
class="emoji-group-title" :item="group"
:active="active"
:data-index="index"
:size-dependencies="[group.emojis.length]"
> >
{{ group.text }} <div
</h6> class="emoji-group"
<span >
v-for="emoji in group.emojis" <h6
:key="group.id + emoji.displayText" v-if="group.isFirstRow"
:title="maybeLocalizedEmojiName(emoji)" class="emoji-group-title"
class="emoji-item" >
@click.stop.prevent="onEmoji(emoji)" {{ group.text }}
> </h6>
<span <span
v-if="!emoji.imageUrl" v-for="emoji in group.emojis"
class="emoji-picker-emoji -unicode" :key="group.id + emoji.displayText"
>{{ emoji.replacement }}</span> :title="maybeLocalizedEmojiName(emoji)"
<still-image class="emoji-item"
v-else @click.stop.prevent="onEmoji(emoji)"
:ref="setEmojiRef(group.id + emoji.displayText)" >
class="emoji-picker-emoji -custom" <span
:data-src="emoji.imageUrl" v-if="!emoji.imageUrl"
:data-emoji-name="group.id + emoji.displayText" class="emoji-picker-emoji -unicode"
/> >{{ emoji.replacement }}</span>
</span> <still-image
<span :ref="setGroupRef('group-end-' + group.id)" /> v-else
</div> class="emoji-picker-emoji -custom"
</div> loading="lazy"
:src="emoji.imageUrl"
:data-emoji-name="group.id + emoji.displayText"
/>
</span>
</div>
</DynamicScrollerItem>
</template>
</DynamicScroller>
<div class="keep-open"> <div class="keep-open">
<Checkbox v-model="keepOpen"> <Checkbox v-model="keepOpen">
{{ $t('emoji.keep_open') }} {{ $t('emoji.keep_open') }}

View file

@ -28,7 +28,7 @@
<script src="./emoji_reactions.js"></script> <script src="./emoji_reactions.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.EmojiReactions { .EmojiReactions {
display: flex; display: flex;
@ -55,6 +55,7 @@
&.not-clickable { &.not-clickable {
cursor: default; cursor: default;
&:hover { &:hover {
box-shadow: $fallback--buttonShadow; box-shadow: $fallback--buttonShadow;
box-shadow: var(--buttonShadow); box-shadow: var(--buttonShadow);
@ -75,10 +76,10 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
&:hover { &:hover {
text-decoration: underline; text-decoration: underline;
} }
} }
} }
</style> </style>

View file

@ -172,15 +172,10 @@
<script src="./extra_buttons.js"></script> <script src="./extra_buttons.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
@import '../../_mixins.scss'; @import "../../mixins";
.ExtraButtons { .ExtraButtons {
/* override of popover internal stuff */
.popover-trigger-button {
width: auto;
}
.popover-trigger { .popover-trigger {
position: static; position: static;
padding: 10px; padding: 10px;
@ -190,10 +185,12 @@
color: $fallback--text; color: $fallback--text;
color: var(--text, $fallback--text); color: var(--text, $fallback--text);
} }
} }
.popover-trigger-button { .popover-trigger-button {
/* override of popover internal stuff */
width: auto;
@include unfocused-style { @include unfocused-style {
.focus-marker { .focus-marker {
visibility: hidden; visibility: hidden;

View file

@ -58,8 +58,8 @@
<script src="./favorite_button.js"></script> <script src="./favorite_button.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
@import '../../_mixins.scss'; @import "../../mixins";
.FavoriteButton { .FavoriteButton {
display: flex; display: flex;

View file

@ -42,7 +42,8 @@
<script src="./flash.js"></script> <script src="./flash.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.Flash { .Flash {
display: inline-block; display: inline-block;
width: 100%; width: 100%;
@ -78,7 +79,7 @@
.hidden { .hidden {
display: none; display: none;
visibility: 'hidden'; visibility: "hidden";
} }
} }
</style> </style>

View file

@ -39,9 +39,8 @@
&-content-container { &-content-container {
flex-shrink: 0; flex-shrink: 0;
display: flex; display: flex;
flex-direction: row; flex-flow: row wrap;
justify-content: space-between; justify-content: space-between;
flex-wrap: wrap;
line-height: 1.5em; line-height: 1.5em;
} }

View file

@ -22,8 +22,8 @@
<style lang="scss"> <style lang="scss">
.follow-request-card-content-container { .follow-request-card-content-container {
display: flex; display: flex;
flex-direction: row; flex-flow: row wrap;
flex-wrap: wrap;
button { button {
margin-top: 0.5em; margin-top: 0.5em;
margin-right: 0.5em; margin-right: 0.5em;

View file

@ -50,17 +50,20 @@
<script src="./font_control.js"></script> <script src="./font_control.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.font-control { .font-control {
input.custom-font { input.custom-font {
min-width: 10em; min-width: 10em;
} }
&.custom { &.custom {
/* TODO Should make proper joiners... */ /* TODO Should make proper joiners... */
.font-switcher { .font-switcher {
border-top-right-radius: 0; border-top-right-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
} }
.custom-font { .custom-font {
border-top-left-radius: 0; border-top-left-radius: 0;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;

View file

@ -4,6 +4,7 @@ import { sumBy, set } from 'lodash'
const Gallery = { const Gallery = {
props: [ props: [
'attachments', 'attachments',
'compact',
'limitRows', 'limitRows',
'descriptions', 'descriptions',
'limit', 'limit',

View file

@ -20,6 +20,7 @@
v-for="(attachment, attachmentIndex) in row.items" v-for="(attachment, attachmentIndex) in row.items"
:key="attachment.id" :key="attachment.id"
class="gallery-item" class="gallery-item"
:compact="compact"
:nsfw="nsfw" :nsfw="nsfw"
:attachment="attachment" :attachment="attachment"
:size="size" :size="size"
@ -86,7 +87,7 @@
<script src='./gallery.js'></script> <script src='./gallery.js'></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.Gallery { .Gallery {
.gallery-rows { .gallery-rows {
@ -100,6 +101,53 @@
width: 100%; width: 100%;
flex-grow: 1; flex-grow: 1;
.gallery-row-inner {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
flex-flow: row wrap;
align-content: stretch;
.gallery-item {
margin: 0 0.5em 0 0;
flex-grow: 1;
height: 100%;
box-sizing: border-box;
// to make failed images a bit more noticeable on chromium
min-width: 2em;
&:last-child {
margin: 0;
}
}
&.-grid {
width: 100%;
height: auto;
position: relative;
display: grid;
grid-gap: 0.5em;
grid-template-columns: repeat(auto-fill, minmax(15em, 1fr));
.gallery-item {
margin: 0;
height: 200px;
}
}
}
&.-grid,
&.-minimal {
height: auto;
.gallery-row-inner {
position: relative;
}
}
&:not(:first-child) { &:not(:first-child) {
margin-top: 0.5em; margin-top: 0.5em;
} }
@ -114,7 +162,7 @@
linear-gradient(to top, white, white); linear-gradient(to top, white, white);
/* Autoprefixed seem to ignore this one, and also syntax is different */ /* Autoprefixed seem to ignore this one, and also syntax is different */
-webkit-mask-composite: xor; mask-composite: xor;
mask-composite: exclude; mask-composite: exclude;
} }
} }
@ -138,54 +186,5 @@
padding: 0 2em; padding: 0 2em;
} }
} }
.gallery-row {
&.-grid,
&.-minimal {
height: auto;
.gallery-row-inner {
position: relative;
}
}
}
.gallery-row-inner {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: stretch;
&.-grid {
width: 100%;
height: auto;
position: relative;
display: grid;
grid-column-gap: 0.5em;
grid-row-gap: 0.5em;
grid-template-columns: repeat(auto-fill, minmax(15em, 1fr));
.gallery-item {
margin: 0;
height: 200px;
}
}
}
.gallery-item {
margin: 0 0.5em 0 0;
flex-grow: 1;
height: 100%;
box-sizing: border-box;
// to make failed images a bit more noticeable on chromium
min-width: 2em;
&:last-child {
margin: 0;
}
}
} }
</style> </style>

View file

@ -25,7 +25,7 @@
<script src="./global_notice_list.js"></script> <script src="./global_notice_list.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.global-notice-list { .global-notice-list {
position: fixed; position: fixed;
@ -73,6 +73,7 @@
.global-success { .global-success {
background-color: var(--alertPopupSuccess, $fallback--cGreen); background-color: var(--alertPopupSuccess, $fallback--cGreen);
color: var(--alertPopupSuccessText, $fallback--text); color: var(--alertPopupSuccessText, $fallback--text);
.svg-inline--fa { .svg-inline--fa {
color: var(--alertPopupSuccessText, $fallback--text); color: var(--alertPopupSuccessText, $fallback--text);
} }
@ -81,6 +82,7 @@
.global-info { .global-info {
background-color: var(--alertPopupNeutral, $fallback--fg); background-color: var(--alertPopupNeutral, $fallback--fg);
color: var(--alertPopupNeutralText, $fallback--text); color: var(--alertPopupNeutralText, $fallback--text);
.svg-inline--fa { .svg-inline--fa {
color: var(--alertPopupNeutralText, $fallback--text); color: var(--alertPopupNeutralText, $fallback--text);
} }
@ -88,6 +90,7 @@
.close-notice { .close-notice {
padding-right: 0.2em; padding-right: 0.2em;
.svg-inline--fa:hover { .svg-inline--fa:hover {
opacity: 0.6; opacity: 0.6;
} }

View file

@ -33,7 +33,7 @@
<script src="./link-preview.js"></script> <script src="./link-preview.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.link-preview-card { .link-preview-card {
display: flex; display: flex;
@ -46,6 +46,7 @@
flex-shrink: 0; flex-shrink: 0;
width: 120px; width: 120px;
max-width: 25%; max-width: 25%;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -67,7 +68,7 @@
} }
.card-description { .card-description {
margin: 0.5em 0 0 0; margin: 0.5em 0 0;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
word-break: break-word; word-break: break-word;

View file

@ -35,7 +35,7 @@ export default {
</script> </script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.list { .list {
&-item:not(:last-child) { &-item:not(:last-child) {

View file

@ -21,12 +21,16 @@
<script src="./lists_card.js"></script> <script src="./lists_card.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.list-card { .list-card {
display: flex; display: flex;
} }
.list-name {
flex-grow: 1;
}
.list-name, .list-name,
.button-list-edit { .button-list-edit {
margin: 0; margin: 0;
@ -39,13 +43,10 @@
background-color: var(--selectedMenu, $fallback--lightBg); background-color: var(--selectedMenu, $fallback--lightBg);
color: $fallback--link; color: $fallback--link;
color: var(--selectedMenuText, $fallback--link); color: var(--selectedMenuText, $fallback--link);
--faint: var(--selectedMenuFaintText, $fallback--faint); --faint: var(--selectedMenuFaintText, $fallback--faint);
--faintLink: var(--selectedMenuFaintLink, $fallback--faint); --faintLink: var(--selectedMenuFaintLink, $fallback--faint);
--lightText: var(--selectedMenuLightText, $fallback--lightText); --lightText: var(--selectedMenuLightText, $fallback--lightText);
} }
} }
.list-name {
flex-grow: 1;
}
</style> </style>

View file

@ -95,10 +95,10 @@ const ListsNew = {
return this.addedUserIds.has(user.id) return this.addedUserIds.has(user.id)
}, },
addUser (user) { addUser (user) {
this.$store.dispatch('addListAccount', { accountId: this.user.id, listId: this.id }) this.$store.dispatch('addListAccount', { accountId: user.id, listId: this.id })
}, },
removeUser (userId) { removeUser (userId) {
this.$store.dispatch('removeListAccount', { accountId: this.user.id, listId: this.id }) this.$store.dispatch('removeListAccount', { accountId: userId, listId: this.id })
}, },
onSearchLoading (results) { onSearchLoading (results) {
this.searchLoading = true this.searchLoading = true

View file

@ -164,7 +164,7 @@
<script src="./lists_edit.js"></script> <script src="./lists_edit.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.ListEdit { .ListEdit {
--panel-body-padding: 0.5em; --panel-body-padding: 0.5em;

View file

@ -27,12 +27,12 @@
<script src="./lists_user_search.js"></script> <script src="./lists_user_search.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.ListsUserSearch { .ListsUserSearch {
.input-wrap { .input-wrap {
display: flex; display: flex;
margin: 0.7em 0.5em 0.7em 0.5em; margin: 0.7em 0.5em;
input { input {
width: 100%; width: 100%;

View file

@ -93,7 +93,7 @@
<script src="./login_form.js"></script> <script src="./login_form.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.login-form { .login-form {
display: flex; display: flex;
@ -110,7 +110,7 @@
} }
.login-bottom { .login-bottom {
margin-top: 1.0em; margin-top: 1em;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
@ -121,7 +121,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 0.3em 0.5em 0.6em; padding: 0.3em 0.5em 0.6em;
line-height:24px; line-height: 24px;
} }
.form-bottom { .form-bottom {
@ -142,7 +142,6 @@
.error { .error {
text-align: center; text-align: center;
animation-name: shakeError; animation-name: shakeError;
animation-duration: 0.4s; animation-duration: 0.4s;
animation-timing-function: ease-in-out; animation-timing-function: ease-in-out;

View file

@ -63,6 +63,11 @@ const MediaModal = {
}, },
type () { type () {
return this.currentMedia ? this.getType(this.currentMedia) : null return this.currentMedia ? this.getType(this.currentMedia) : null
},
swipeDisableClickThreshold () {
// If there is only one media, allow more mouse movements to close the modal
// because there is less chance that the user wants to switch to another image
return () => this.canNavigate ? 1 : 30
} }
}, },
methods: { methods: {

View file

@ -10,6 +10,7 @@
class="modal-image-container" class="modal-image-container"
:direction="swipeDirection" :direction="swipeDirection"
:threshold="swipeThreshold" :threshold="swipeThreshold"
:disable-click-threshold="swipeDisableClickThreshold"
@preview-requested="handleSwipePreview" @preview-requested="handleSwipePreview"
@swipe-finished="handleSwipeEnd" @swipe-finished="handleSwipeEnd"
@swipeless-clicked="hide" @swipeless-clicked="hide"
@ -120,32 +121,12 @@ $modal-view-button-icon-half-height: calc(#{$modal-view-button-icon-height} / 2)
$modal-view-button-icon-width: 3em; $modal-view-button-icon-width: 3em;
$modal-view-button-icon-margin: 0.5em; $modal-view-button-icon-margin: 0.5em;
.modal-view.media-modal-view {
z-index: var(--ZI_media_modal);
flex-direction: column;
.modal-view-button-arrow,
.modal-view-button-hide {
opacity: 0.75;
&:focus,
&:hover {
outline: none;
box-shadow: none;
}
&:hover {
opacity: 1;
}
}
overflow: hidden;
}
.media-modal-view { .media-modal-view {
@keyframes media-fadein { @keyframes media-fadein {
from { from {
opacity: 0; opacity: 0;
} }
to { to {
opacity: 1; opacity: 1;
} }
@ -226,7 +207,7 @@ $modal-view-button-icon-margin: 0.5em;
appearance: none; appearance: none;
overflow: visible; overflow: visible;
cursor: pointer; cursor: pointer;
transition: opacity 333ms cubic-bezier(.4,0,.22,1); transition: opacity 333ms cubic-bezier(0.4, 0, 0.22, 1);
height: $modal-view-button-icon-height; height: $modal-view-button-icon-height;
width: $modal-view-button-icon-width; width: $modal-view-button-icon-width;
@ -236,9 +217,9 @@ $modal-view-button-icon-margin: 0.5em;
width: $modal-view-button-icon-width; width: $modal-view-button-icon-width;
font-size: 1rem; font-size: 1rem;
line-height: $modal-view-button-icon-height; line-height: $modal-view-button-icon-height;
color: #FFF; color: #fff;
text-align: center; text-align: center;
background-color: rgba(0,0,0,.3); background-color: rgb(0 0 0 / 30%);
} }
} }
@ -254,13 +235,14 @@ $modal-view-button-icon-margin: 0.5em;
position: absolute; position: absolute;
top: 0; top: 0;
line-height: $modal-view-button-icon-height; line-height: $modal-view-button-icon-height;
color: #FFF; color: #fff;
text-align: center; text-align: center;
background-color: rgba(0,0,0,.3); background-color: rgb(0 0 0 / 30%);
} }
&--prev { &--prev {
left: 0; left: 0;
.arrow-icon { .arrow-icon {
left: $modal-view-button-icon-margin; left: $modal-view-button-icon-margin;
} }
@ -268,6 +250,7 @@ $modal-view-button-icon-margin: 0.5em;
&--next { &--next {
right: 0; right: 0;
.arrow-icon { .arrow-icon {
right: $modal-view-button-icon-margin; right: $modal-view-button-icon-margin;
} }
@ -278,10 +261,33 @@ $modal-view-button-icon-margin: 0.5em;
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
.button-icon { .button-icon {
top: $modal-view-button-icon-margin; top: $modal-view-button-icon-margin;
right: $modal-view-button-icon-margin; right: $modal-view-button-icon-margin;
} }
} }
} }
.modal-view.media-modal-view {
z-index: var(--ZI_media_modal);
flex-direction: column;
.modal-view-button-arrow,
.modal-view-button-hide {
opacity: 0.75;
&:focus,
&:hover {
outline: none;
box-shadow: none;
}
&:hover {
opacity: 1;
}
}
overflow: hidden;
}
</style> </style>

View file

@ -29,7 +29,7 @@
<script src="./media_upload.js"></script> <script src="./media_upload.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.media-upload { .media-upload {
cursor: pointer; // We use <label> for interactivity... i wonder if it's fine cursor: pointer; // We use <label> for interactivity... i wonder if it's fine

View file

@ -1,4 +1,4 @@
@import '../../_variables.scss'; @import "../../variables";
.MentionLink { .MentionLink {
position: relative; position: relative;
@ -59,6 +59,7 @@
font-weight: 600; font-weight: 600;
} }
} }
&.-has-selection { &.-has-selection {
color: var(--alertNeutralText, $fallback--text); color: var(--alertNeutralText, $fallback--text);
background-color: var(--alertNeutral, $fallback--fg); background-color: var(--alertNeutral, $fallback--fg);
@ -100,10 +101,6 @@
} }
} }
.full {
pointer-events: none;
}
.serverName.-faded { .serverName.-faded {
color: var(--faintLink, $fallback--link); color: var(--faintLink, $fallback--link);
} }

View file

@ -2,7 +2,7 @@
word-break: break-all; word-break: break-all;
.mention-link:not(:first-child)::before { .mention-link:not(:first-child)::before {
content: ' '; content: " ";
} }
.showMoreLess { .showMoreLess {

View file

@ -94,7 +94,7 @@
<script src="./mobile_nav.js"></script> <script src="./mobile_nav.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.MobileNav { .MobileNav {
z-index: var(--ZI_navbar); z-index: var(--ZI_navbar);
@ -127,7 +127,7 @@
} }
.site-name { .site-name {
padding: 0 .3em; padding: 0 0.3em;
display: inline-block; display: inline-block;
} }
@ -156,7 +156,7 @@
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
box-shadow: 1px 1px 4px rgba(0,0,0,.6); box-shadow: 1px 1px 4px rgb(0 0 0 / 60%);
box-shadow: var(--panelShadow); box-shadow: var(--panelShadow);
transition-property: transform; transition-property: transform;
transition-duration: 0.25s; transition-duration: 0.25s;
@ -182,7 +182,7 @@
color: var(--topBarText); color: var(--topBarText);
background-color: $fallback--fg; background-color: $fallback--fg;
background-color: var(--topBar, $fallback--fg); background-color: var(--topBar, $fallback--fg);
box-shadow: 0px 0px 4px rgba(0,0,0,.6); box-shadow: 0 0 4px rgb(0 0 0 / 60%);
box-shadow: var(--topBarShadow); box-shadow: var(--topBarShadow);
.spacer { .spacer {

View file

@ -13,7 +13,7 @@
<script src="./mobile_post_status_button.js"></script> <script src="./mobile_post_status_button.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.MobilePostButton { .MobilePostButton {
&.button-default { &.button-default {
@ -30,9 +30,8 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3), 0px 4px 6px rgba(0, 0, 0, 0.3); box-shadow: 0 2px 2px rgb(0 0 0 / 30%), 0 4px 6px rgb(0 0 0 / 30%);
z-index: 10; z-index: 10;
transition: 0.35s transform; transition: 0.35s transform;
transition-timing-function: cubic-bezier(0, 1, 0.5, 1); transition-timing-function: cubic-bezier(0, 1, 0.5, 1);
} }

View file

@ -59,7 +59,7 @@ export default {
&.modal-background { &.modal-background {
pointer-events: initial; pointer-events: initial;
background-color: rgba(0, 0, 0, 0.5); background-color: rgb(0 0 0 / 50%);
} }
&.open { &.open {
@ -69,10 +69,11 @@ export default {
@keyframes modal-background-fadein { @keyframes modal-background-fadein {
from { from {
background-color: rgba(0, 0, 0, 0); background-color: rgb(0 0 0 / 0%);
} }
to { to {
background-color: rgba(0, 0, 0, 0.5); background-color: rgb(0 0 0 / 50%);
} }
} }
</style> </style>

View file

@ -166,18 +166,21 @@
<script src="./moderation_tools.js"></script> <script src="./moderation_tools.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.moderation-tools-popover { .moderation-tools-popover {
height: 100%; height: 100%;
.trigger { .trigger {
/* stylelint-disable-next-line declaration-no-important */
display: flex !important; display: flex !important;
height: 100%; height: 100%;
} }
} }
.moderation-tools-button { .moderation-tools-button {
svg,i { svg,
i {
font-size: 0.8em; font-size: 0.8em;
} }
} }

View file

@ -2,19 +2,21 @@
margin: 1em; margin: 1em;
table { table {
width:100%; width: 100%;
text-align: left; text-align: left;
padding-left:10px; padding-left: 10px;
padding-bottom:20px; padding-bottom: 20px;
th, td { th,
td {
width: 180px; width: 180px;
max-width: 360px; max-width: 360px;
overflow: hidden; overflow: hidden;
vertical-align: text-top; vertical-align: text-top;
} }
th+th, td+td { th + th,
td + td {
width: auto; width: auto;
} }
} }

View file

@ -227,6 +227,6 @@
<script src="./mrf_transparency_panel.js"></script> <script src="./mrf_transparency_panel.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
@import './mrf_transparency_panel.scss'; @import "./mrf_transparency_panel";
</style> </style>

View file

@ -37,6 +37,7 @@
.mute-card-content-container { .mute-card-content-container {
margin-top: 0.5em; margin-top: 0.5em;
text-align: right; text-align: right;
button { button {
width: 10em; width: 10em;
} }

View file

@ -102,7 +102,7 @@
<script src="./nav_panel.js"></script> <script src="./nav_panel.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.NavPanel { .NavPanel {
.panel { .panel {
@ -169,8 +169,9 @@
} }
.nav-panel-heading { .nav-panel-heading {
// breaks without a unit // breaks without a unit
--panel-heading-height-padding: 0em; // stylelint-disable-next-line length-zero-no-unit
--panel-heading-height-padding: 0px;
} }
} }
</style> </style>

View file

@ -63,7 +63,7 @@
<script src="./navigation_entry.js"></script> <script src="./navigation_entry.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.NavigationEntry { .NavigationEntry {
display: flex; display: flex;
@ -102,6 +102,7 @@
background-color: var(--selectedMenu, $fallback--lightBg); background-color: var(--selectedMenu, $fallback--lightBg);
color: $fallback--link; color: $fallback--link;
color: var(--selectedMenuText, $fallback--link); color: var(--selectedMenuText, $fallback--link);
--faint: var(--selectedMenuFaintText, $fallback--faint); --faint: var(--selectedMenuFaintText, $fallback--faint);
--faintLink: var(--selectedMenuFaintLink, $fallback--faint); --faintLink: var(--selectedMenuFaintLink, $fallback--faint);
--lightText: var(--selectedMenuLightText, $fallback--lightText); --lightText: var(--selectedMenuLightText, $fallback--lightText);
@ -117,6 +118,7 @@
background-color: var(--selectedMenu, $fallback--lightBg); background-color: var(--selectedMenu, $fallback--lightBg);
color: $fallback--text; color: $fallback--text;
color: var(--selectedMenuText, $fallback--text); color: var(--selectedMenuText, $fallback--text);
--faint: var(--selectedMenuFaintText, $fallback--faint); --faint: var(--selectedMenuFaintText, $fallback--faint);
--faintLink: var(--selectedMenuFaintLink, $fallback--faint); --faintLink: var(--selectedMenuFaintLink, $fallback--faint);
--lightText: var(--selectedMenuLightText, $fallback--lightText); --lightText: var(--selectedMenuLightText, $fallback--lightText);

View file

@ -27,7 +27,8 @@
<script src="./navigation_pins.js"></script> <script src="./navigation_pins.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.NavigationPins { .NavigationPins {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;

View file

@ -60,7 +60,6 @@ const Notification = {
}, },
methods: { methods: {
toggleStatusExpanded () { toggleStatusExpanded () {
console.log('as')
this.statusExpanded = !this.statusExpanded this.statusExpanded = !this.statusExpanded
}, },
generateUserProfileLink (user) { generateUserProfileLink (user) {

View file

@ -1,13 +1,14 @@
@import '../../_variables.scss'; @import "../../variables";
// TODO Copypaste from Status, should unify it somehow // TODO Copypaste from Status, should unify it somehow
.Notification { .Notification {
border-bottom: 1px solid; border-bottom: 1px solid;
border-color: $fallback--border; border-color: $fallback--border;
border-color: var(--border, $fallback--border); border-color: var(--border, $fallback--border);
word-wrap: break-word; word-wrap: break-word;
word-break: break-word; word-break: break-word;
--emoji-size: 14px;
--emoji-size: 14px;
&.-muted { &.-muted {
padding: 0.25em 0.6em; padding: 0.25em 0.6em;
@ -48,7 +49,7 @@
margin-left: 0.2em; margin-left: 0.2em;
&::before { &::before {
content: ' '; content: " ";
} }
} }

View file

@ -155,6 +155,7 @@
class="button-unstyled expand-icon" class="button-unstyled expand-icon"
@click.prevent="toggleStatusExpanded" @click.prevent="toggleStatusExpanded"
:title="$t('tool_tip.toggle_expand')" :title="$t('tool_tip.toggle_expand')"
:aria-expanded="statusExpanded"
> >
<FAIcon <FAIcon
class="fa-scale-110" class="fa-scale-110"
@ -178,6 +179,7 @@
v-if="needMute" v-if="needMute"
class="button-unstyled" class="button-unstyled"
:title="$t('tool_tip.toggle_mute')" :title="$t('tool_tip.toggle_mute')"
:aria-expanded="!unmuted"
@click.prevent="toggleMute" @click.prevent="toggleMute"
> >
<FAIcon <FAIcon

View file

@ -101,6 +101,9 @@ const Notifications = {
if (!this.scrollerRef) { if (!this.scrollerRef) {
this.scrollerRef = this.$refs.root.closest('.mobile-notifications') this.scrollerRef = this.$refs.root.closest('.mobile-notifications')
} }
if (!this.scrollerRef) {
this.scrollerRef = this.$refs.root.closest('.column.main')
}
this.scrollerRef.addEventListener('scroll', this.updateScrollPosition) this.scrollerRef.addEventListener('scroll', this.updateScrollPosition)
}, },
unmounted () { unmounted () {

View file

@ -1,4 +1,4 @@
@import '../../_variables.scss'; @import "../../variables";
.Notifications { .Notifications {
&:not(.minimal) { &:not(.minimal) {
@ -25,12 +25,13 @@
&.unseen { &.unseen {
.notification-overlay { .notification-overlay {
background-image: linear-gradient(135deg, var(--badgeNotification, $fallback--cRed) 4px, transparent 10px) background-image: linear-gradient(135deg, var(--badgeNotification, $fallback--cRed) 4px, transparent 10px);
} }
} }
} }
} }
/* stylelint-disable-next-line no-descending-specificity */
.notification { .notification {
box-sizing: border-box; box-sizing: border-box;
@ -38,6 +39,7 @@
canvas { canvas {
display: none; display: none;
} }
img { img {
visibility: visible; visibility: visible;
} }
@ -79,7 +81,8 @@
} }
} }
.follow-text, .move-text { .follow-text,
.move-text {
padding: 0.5em 0; padding: 0.5em 0;
overflow-wrap: break-word; overflow-wrap: break-word;
display: flex; display: flex;

View file

@ -23,7 +23,7 @@ export default {}
</script> </script>
<style lang="scss"> <style lang="scss">
@import 'src/_variables.scss'; @import "src/variables";
.panel-loading { .panel-loading {
display: flex; display: flex;
@ -33,6 +33,7 @@ export default {}
font-size: 2em; font-size: 2em;
color: $fallback--text; color: $fallback--text;
color: var(--text, $fallback--text); color: var(--text, $fallback--text);
.loading-text svg { .loading-text svg {
line-height: 0; line-height: 0;
vertical-align: middle; vertical-align: middle;

View file

@ -77,7 +77,7 @@
<script src="./password_reset.js"></script> <script src="./password_reset.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.password-reset-form { .password-reset-form {
display: flex; display: flex;

View file

@ -90,7 +90,7 @@
<script src="./poll.js"></script> <script src="./poll.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.poll { .poll {
.votes { .votes {
@ -98,9 +98,11 @@
flex-direction: column; flex-direction: column;
margin: 0 0 0.5em; margin: 0 0 0.5em;
} }
.poll-option { .poll-option {
margin: 0.75em 0.5em; margin: 0.75em 0.5em;
} }
.option-result { .option-result {
height: 100%; height: 100%;
display: flex; display: flex;
@ -109,6 +111,7 @@
color: $fallback--lightText; color: $fallback--lightText;
color: var(--lightText, $fallback--lightText); color: var(--lightText, $fallback--lightText);
} }
.option-result-label { .option-result-label {
display: flex; display: flex;
align-items: center; align-items: center;
@ -116,10 +119,12 @@
z-index: 1; z-index: 1;
word-break: break-word; word-break: break-word;
} }
.result-percentage { .result-percentage {
width: 3.5em; width: 3.5em;
flex-shrink: 0; flex-shrink: 0;
} }
.result-fill { .result-fill {
height: 100%; height: 100%;
position: absolute; position: absolute;
@ -133,20 +138,25 @@
left: 0; left: 0;
transition: width 0.5s; transition: width 0.5s;
} }
.option-vote { .option-vote {
display: flex; display: flex;
align-items: center; align-items: center;
} }
input { input {
width: 3.5em; width: 3.5em;
} }
.footer { .footer {
display: flex; display: flex;
align-items: center; align-items: center;
} }
&.loading * { &.loading * {
cursor: progress; cursor: progress;
} }
.poll-vote-button { .poll-vote-button {
padding: 0 0.5em; padding: 0 0.5em;
margin-right: 0.5em; margin-right: 0.5em;

View file

@ -95,7 +95,7 @@
<script src="./poll_form.js"></script> <script src="./poll_form.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.poll-form { .poll-form {
display: flex; display: flex;
@ -117,6 +117,7 @@
.input-container { .input-container {
width: 100%; width: 100%;
input { input {
// Hack: dodge the floating X icon // Hack: dodge the floating X icon
padding-right: 2.5em; padding-right: 2.5em;

View file

@ -41,7 +41,7 @@
<script src="./popover.js" /> <script src="./popover.js" />
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.popover-trigger-button { .popover-trigger-button {
display: inline-block; display: inline-block;
@ -52,31 +52,31 @@
position: fixed; position: fixed;
min-width: 0; min-width: 0;
max-width: calc(100vw - 20px); max-width: calc(100vw - 20px);
box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5); box-shadow: 2px 2px 3px rgb(0 0 0 / 50%);
box-shadow: var(--popupShadow); box-shadow: var(--popupShadow);
} }
.popover-default { .popover-default {
&:after { &::after {
content: ''; content: "";
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
z-index: 3; z-index: 3;
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6); box-shadow: 1px 1px 4px rgb(0 0 0 / 60%);
box-shadow: var(--panelShadow); box-shadow: var(--panelShadow);
pointer-events: none; pointer-events: none;
} }
border-radius: $fallback--btnRadius; border-radius: $fallback--btnRadius;
border-radius: var(--btnRadius, $fallback--btnRadius); border-radius: var(--btnRadius, $fallback--btnRadius);
background-color: $fallback--bg; background-color: $fallback--bg;
background-color: var(--popover, $fallback--bg); background-color: var(--popover, $fallback--bg);
color: $fallback--text; color: $fallback--text;
color: var(--popoverText, $fallback--text); color: var(--popoverText, $fallback--text);
--faint: var(--popoverFaintText, $fallback--faint); --faint: var(--popoverFaintText, $fallback--faint);
--faintLink: var(--popoverFaintLink, $fallback--faint); --faintLink: var(--popoverFaintLink, $fallback--faint);
--lightText: var(--popoverLightText, $fallback--lightText); --lightText: var(--popoverLightText, $fallback--lightText);
@ -87,7 +87,7 @@
.dropdown-menu { .dropdown-menu {
display: block; display: block;
padding: .5rem 0; padding: 0.5rem 0;
font-size: 1em; font-size: 1em;
text-align: left; text-align: left;
list-style: none; list-style: none;
@ -97,7 +97,7 @@
.dropdown-divider { .dropdown-divider {
height: 0; height: 0;
margin: .5rem 0; margin: 0.5rem 0;
overflow: hidden; overflow: hidden;
border-top: 1px solid $fallback--border; border-top: 1px solid $fallback--border;
border-top: 1px solid var(--border, $fallback--border); border-top: 1px solid var(--border, $fallback--border);
@ -113,7 +113,7 @@
text-align: inherit; text-align: inherit;
white-space: nowrap; white-space: nowrap;
border: none; border: none;
border-radius: 0px; border-radius: 0;
background-color: transparent; background-color: transparent;
box-shadow: none; box-shadow: none;
width: 100%; width: 100%;
@ -126,7 +126,7 @@
svg { svg {
width: 22px; width: 22px;
margin-right: 0.75rem; margin-right: 0.75rem;
color: var(--menuPopoverIcon, $fallback--icon) color: var(--menuPopoverIcon, $fallback--icon);
} }
} }
@ -137,17 +137,21 @@
} }
} }
&:active, &:hover { &:active,
&:hover {
background-color: $fallback--lightBg; background-color: $fallback--lightBg;
background-color: var(--selectedMenuPopover, $fallback--lightBg); background-color: var(--selectedMenuPopover, $fallback--lightBg);
box-shadow: none; box-shadow: none;
--btnText: var(--selectedMenuPopoverText, $fallback--link); --btnText: var(--selectedMenuPopoverText, $fallback--link);
--faint: var(--selectedMenuPopoverFaintText, $fallback--faint); --faint: var(--selectedMenuPopoverFaintText, $fallback--faint);
--faintLink: var(--selectedMenuPopoverFaintLink, $fallback--faint); --faintLink: var(--selectedMenuPopoverFaintLink, $fallback--faint);
--lightText: var(--selectedMenuPopoverLightText, $fallback--lightText); --lightText: var(--selectedMenuPopoverLightText, $fallback--lightText);
--icon: var(--selectedMenuPopoverIcon, $fallback--icon); --icon: var(--selectedMenuPopoverIcon, $fallback--icon);
svg { svg {
color: var(--selectedMenuPopoverIcon, $fallback--icon); color: var(--selectedMenuPopoverIcon, $fallback--icon);
--icon: var(--selectedMenuPopoverIcon, $fallback--icon); --icon: var(--selectedMenuPopoverIcon, $fallback--icon);
} }
} }
@ -161,16 +165,16 @@
max-height: 22px; max-height: 22px;
line-height: 22px; line-height: 22px;
text-align: center; text-align: center;
border-radius: 0px; border-radius: 0;
background-color: $fallback--fg; background-color: $fallback--fg;
background-color: var(--input, $fallback--fg); background-color: var(--input, $fallback--fg);
box-shadow: 0px 0px 2px black inset; box-shadow: 0 0 2px black inset;
box-shadow: var(--inputShadow); box-shadow: var(--inputShadow);
margin-right: 0.75em; margin-right: 0.75em;
&.menu-checkbox-checked::after { &.menu-checkbox-checked::after {
font-size: 1.25em; font-size: 1.25em;
content: '✓'; content: "✓";
} }
&.-radio { &.-radio {
@ -178,16 +182,15 @@
&.menu-checkbox-checked::after { &.menu-checkbox-checked::after {
font-size: 2em; font-size: 2em;
content: '•'; content: "•";
} }
} }
} }
} }
.button-default.dropdown-item { .button-default.dropdown-item {
&, &,
i[class*=icon-] { i[class*="icon-"] {
color: $fallback--text; color: $fallback--text;
color: var(--btnText, $fallback--text); color: var(--btnText, $fallback--text);
} }

View file

@ -331,7 +331,7 @@
<script src="./post_status_form.js"></script> <script src="./post_status_form.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.post-status-form { .post-status-form {
position: relative; position: relative;
@ -378,7 +378,9 @@
&:hover { &:hover {
text-decoration: underline; text-decoration: underline;
} }
svg, i {
svg,
i {
margin-left: 0.2em; margin-left: 0.2em;
font-size: 0.8em; font-size: 0.8em;
transform: rotate(90deg); transform: rotate(90deg);
@ -428,36 +430,6 @@
} }
} }
.media-upload-icon, .poll-icon, .emoji-icon {
font-size: 1.85em;
line-height: 1.1;
flex: 1;
padding: 0 0.1em;
display: flex;
align-items: center;
&.selected, &:hover {
// needs to be specific to override icon default color
svg, i, label {
color: $fallback--lightText;
color: var(--lightText, $fallback--lightText);
}
}
&.disabled {
svg, i {
cursor: not-allowed;
color: $fallback--icon;
color: var(--btnDisabledText, $fallback--icon);
&:hover {
color: $fallback--icon;
color: var(--btnDisabledText, $fallback--icon);
}
}
}
}
// Order is not necessary but a good indicator // Order is not necessary but a good indicator
.media-upload-icon { .media-upload-icon {
order: 1; order: 1;
@ -474,16 +446,53 @@
justify-content: right; justify-content: right;
} }
.media-upload-icon,
.poll-icon,
.emoji-icon {
font-size: 1.85em;
line-height: 1.1;
flex: 1;
padding: 0 0.1em;
display: flex;
align-items: center;
&.selected,
&:hover {
// needs to be specific to override icon default color
svg,
i,
label {
color: $fallback--lightText;
color: var(--lightText, $fallback--lightText);
}
}
&.disabled {
svg,
i {
cursor: not-allowed;
color: $fallback--icon;
color: var(--btnDisabledText, $fallback--icon);
&:hover {
color: $fallback--icon;
color: var(--btnDisabledText, $fallback--icon);
}
}
}
}
.error { .error {
text-align: center; text-align: center;
} }
.media-upload-wrapper { .media-upload-wrapper {
margin-right: .2em; margin-right: 0.2em;
margin-bottom: .5em; margin-bottom: 0.5em;
width: 18em; width: 18em;
img, video { img,
video {
object-fit: contain; object-fit: contain;
max-height: 10em; max-height: 10em;
} }
@ -557,18 +566,14 @@
} }
} }
.btn[disabled] {
cursor: not-allowed;
}
@keyframes fade-in { @keyframes fade-in {
from { opacity: 0; } from { opacity: 0; }
to { opacity: 0.6; } to { opacity: 0.6; }
} }
@keyframes fade-out { @keyframes fade-out {
from { opacity: 0.6; } from { opacity: 0.6; }
to { opacity: 0; } to { opacity: 0; }
} }
.drop-indicator { .drop-indicator {

View file

@ -41,7 +41,7 @@ const ReactButton = {
}, },
focusInput () { focusInput () {
this.$nextTick(() => { this.$nextTick(() => {
const input = this.$el.querySelector('input') const input = document.querySelector('.reaction-picker-filter > input')
if (input) input.focus() if (input) input.focus()
}) })
}, },

View file

@ -73,8 +73,8 @@
<script src="./react_button.js"></script> <script src="./react_button.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
@import '../../_mixins.scss'; @import "../../mixins";
.ReactButton { .ReactButton {
.reaction-picker-filter { .reaction-picker-filter {
@ -104,20 +104,19 @@
text-align: center; text-align: center;
align-content: flex-start; align-content: flex-start;
user-select: none; user-select: none;
mask:
mask: linear-gradient(to top, white 0, transparent 100%) bottom no-repeat, linear-gradient(to top, white 0, transparent 100%) bottom no-repeat,
linear-gradient(to bottom, white 0, transparent 100%) top no-repeat, linear-gradient(to bottom, white 0, transparent 100%) top no-repeat,
linear-gradient(to top, white, white); linear-gradient(to top, white, white);
transition: mask-size 150ms; transition: mask-size 150ms;
mask-size: 100% 20px, 100% 20px, auto; mask-size: 100% 20px, 100% 20px, auto;
/* Autoprefixed seem to ignore this one, and also syntax is different */ /* Autoprefixed seem to ignore this one, and also syntax is different */
-webkit-mask-composite: xor; mask-composite: xor;
mask-composite: exclude; mask-composite: exclude;
.emoji-button { .emoji-button {
cursor: pointer; cursor: pointer;
flex-basis: 20%; flex-basis: 20%;
line-height: 1.5; line-height: 1.5;
align-content: center; align-content: center;
@ -128,11 +127,6 @@
} }
} }
/* override of popover internal stuff */
.popover-trigger-button {
width: auto;
}
.popover-trigger { .popover-trigger {
padding: 10px; padding: 10px;
margin: -10px; margin: -10px;
@ -141,10 +135,12 @@
color: $fallback--text; color: $fallback--text;
color: var(--text, $fallback--text); color: var(--text, $fallback--text);
} }
} }
.popover-trigger-button { .popover-trigger-button {
/* override of popover internal stuff */
width: auto;
@include unfocused-style { @include unfocused-style {
.focus-marker { .focus-marker {
visibility: hidden; visibility: hidden;

View file

@ -158,10 +158,10 @@
class="form-error" class="form-error"
> >
<ul> <ul>
<li v-if="!v$.user.confirm.required"> <li v-if="v$.user.confirm.required.$invalid">
<span>{{ $t('registration.validations.password_confirmation_required') }}</span> <span>{{ $t('registration.validations.password_confirmation_required') }}</span>
</li> </li>
<li v-if="!v$.user.confirm.sameAsPassword"> <li v-if="v$.user.confirm.sameAs.$invalid">
<span>{{ $t('registration.validations.password_confirmation_match') }}</span> <span>{{ $t('registration.validations.password_confirmation_match') }}</span>
</li> </li>
</ul> </ul>
@ -277,7 +277,7 @@
<script src="./registration.js"></script> <script src="./registration.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
$validations-cRed: #f04124; $validations-cRed: #f04124;
.registration-form { .registration-form {
@ -321,7 +321,7 @@ $validations-cRed: #f04124;
.form-group--error { .form-group--error {
animation-name: shakeError; animation-name: shakeError;
animation-duration: .6s; animation-duration: 0.6s;
animation-timing-function: ease-in-out; animation-timing-function: ease-in-out;
} }
@ -350,7 +350,7 @@ $validations-cRed: #f04124;
} }
form textarea { form textarea {
line-height:16px; line-height: 16px;
resize: vertical; resize: vertical;
} }

View file

@ -15,6 +15,3 @@
</template> </template>
<script src="./remote_user_resolver.js"></script> <script src="./remote_user_resolver.js"></script>
<style lang="scss">
</style>

View file

@ -51,8 +51,8 @@
<script src="./reply_button.js"></script> <script src="./reply_button.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
@import '../../_mixins.scss'; @import "../../mixins";
.ReplyButton { .ReplyButton {
display: flex; display: flex;
@ -86,6 +86,5 @@
} }
} }
} }
} }
</style> </style>

View file

@ -1,4 +1,4 @@
@import '../../_variables.scss'; @import "../../variables";
.Report { .Report {
.report-content { .report-content {

View file

@ -65,8 +65,8 @@
<script src="./retweet_button.js"></script> <script src="./retweet_button.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
@import '../../_mixins.scss'; @import "../../mixins";
.RetweetButton { .RetweetButton {
display: flex; display: flex;

View file

@ -1,7 +1,11 @@
@import "../../variables";
.RichContent { .RichContent {
blockquote { blockquote {
margin: 0.2em 0 0.2em 2em; margin: 0.2em 0 0.2em 0.2em;
font-style: italic; font-style: italic;
border-left: 0.2em solid var(--faint, $fallback--faint);
padding-left: 1em;
} }
pre { pre {
@ -17,11 +21,11 @@
} }
p { p {
margin: 0 0 1em 0; margin: 0 0 1em;
} }
p:last-child { p:last-child {
margin: 0 0 0 0; margin: 0;
} }
h1 { h1 {

View file

@ -64,10 +64,9 @@
<script src="./scope_selector.js"></script> <script src="./scope_selector.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import "../../variables";
.ScopeSelector { .ScopeSelector {
.scope { .scope {
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;

Some files were not shown because too many files have changed in this diff Show more