Skip to content
Snippets Groups Projects
Commit 71863061 authored by HJ's avatar HJ :fire:
Browse files

fixed tons of stuff, at least it looks normalish on desktop

parent 0e83ced2
No related branches found
No related tags found
No related merge requests found
Showing
with 320 additions and 327 deletions
...@@ -81,11 +81,7 @@ export default { ...@@ -81,11 +81,7 @@ export default {
}, },
isMobileLayout () { return this.$store.state.interface.mobileLayout }, isMobileLayout () { return this.$store.state.interface.mobileLayout },
privateMode () { return this.$store.state.instance.private }, privateMode () { return this.$store.state.instance.private },
sidebarAlign () { reverseLayout () { return this.$store.getters.mergedConfig.sidebarRight },
return {
'order': this.$store.getters.mergedConfig.sidebarRight ? 99 : 0
}
},
...mapGetters(['mergedConfig']) ...mapGetters(['mergedConfig'])
}, },
methods: { methods: {
......
// stylelint-disable rscss/class-format
@import './_variables.scss'; @import './_variables.scss';
html {
font-size: 14px;
overflow: hidden;
max-height: 100vh;
}
body { body {
overflow: hidden; overflow: hidden;
max-height: 100vh;
max-width: 100vw;
font-family: sans-serif;
font-family: var(--interfaceFont, sans-serif);
margin: 0;
color: $fallback--text;
color: var(--text, $fallback--text);
overflow-x: hidden;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
&.hidden {
display: none;
}
}
a {
text-decoration: none;
color: $fallback--link;
color: var(--link, $fallback--link);
}
h4 {
margin: 0;
}
nav {
z-index: 1000;
color: var(--topBarText);
background-color: $fallback--fg;
background-color: var(--topBar, $fallback--fg);
color: $fallback--faint;
color: var(--faint, $fallback--faint);
box-shadow: 0 0 4px rgba(0, 0, 0, 0.6);
box-shadow: var(--topBarShadow);
box-sizing: border-box;
height: var(--navbar-height);
} }
#app-loaded { #app-loaded {
...@@ -12,14 +56,29 @@ body { ...@@ -12,14 +56,29 @@ body {
--navbar-height: 50px; --navbar-height: 50px;
} }
.navbar { #content {
height: var(--navbar-height); overscroll-behavior-y: none;
overflow-y: auto;
position: sticky;
}
#sidebar {
display: grid;
grid-template-columns: 100%;
row-gap: 1em;
grid-area: sidebar;
align-content: start;
}
#main-scroller {
grid-area: content;
} }
.app-bg-wrapper { .app-bg-wrapper {
position: fixed; position: fixed;
z-index: -1;
height: 100%; height: 100%;
top: var(--navbar-height);
z-index: -1000;
left: 0; left: 0;
right: -20px; right: -20px;
background-size: cover; background-size: cover;
...@@ -29,69 +88,66 @@ body { ...@@ -29,69 +88,66 @@ body {
background-position: 50%; background-position: 50%;
} }
h4 {
margin: 0;
}
#content {
overflow-y: auto;
position: sticky;
}
.app-layout { .app-layout {
position: relative; position: relative;
display: grid; display: grid;
grid-template-columns: auto auto; grid-template-columns: auto minmax(auto, 1fr);
grid-template-areas: "sidebar content";
grid-template-rows: 1fr; grid-template-rows: 1fr;
box-sizing: border-box; box-sizing: border-box;
margin: 0 auto; margin: 0 auto;
height: 100vh; height: calc(100vh - var(--navbar-height));
align-content: flex-start; align-content: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
padding: 0 10px 0 10px; padding: 0 10px 0 10px;
grid-template-columns: auto auto;
justify-content: center; justify-content: center;
&.-reverse {
grid-template-columns: minmax(auto, 1fr) auto;
grid-template-areas: "content sidebar";
}
} }
.underlay { .underlay {
height: 100%;
width: 100%;
grid-column-start: 1; grid-column-start: 1;
grid-column-end: 3; grid-column-end: span 2;
grid-row-start: 1; grid-row-start: 1;
grid-row-end: 1; grid-row-end: 1;
margin: -0.5em; margin: 0 -0.5em;
padding: 0.5em; padding: 0 0.5em;
pointer-events: none;
background-color: rgba(0, 0, 0, 0.15);
background-color: var(--underlay, rgba(0, 0, 0, 0.15));
z-index: -2000;
} }
.column { .column {
box-sizing: border-box;
max-width: 615px; max-width: 615px;
padding-top: 10px; padding-top: 10px;
grid-row-start: 1; grid-row-start: 1;
grid-row-end: 1; grid-row-end: 1;
margin: 0 0.5em;
&:nth-child(2) {
grid-column: 1;
}
&:nth-child(3) {
grid-column: 2;
}
&.-mini { &.-mini {
max-width: 345px; max-width: 345px;
} }
&.-scrollable { &.-scrollable {
padding-top: 10px;
position: sticky; position: sticky;
top: 0; top: 0;
margin-top: calc(-1 * var(--navbar-padding)); max-height: calc(100vh - var(--navbar-height));
max-height: 100vh;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden;
.panel-heading.-sticky {
top: -10px;
}
} }
} }
body, #content,
.column.-scrollable { .column.-scrollable {
&::-webkit-scrollbar { &::-webkit-scrollbar {
display: block; display: block;
...@@ -99,42 +155,10 @@ body, ...@@ -99,42 +155,10 @@ body,
} }
} }
.underlay {
background-color: rgba(0,0,0,0.15);
background-color: var(--underlay, rgba(0,0,0,0.15));
}
.text-center { .text-center {
text-align: center; text-align: center;
} }
html {
font-size: 14px;
}
body {
overscroll-behavior-y: none;
font-family: sans-serif;
font-family: var(--interfaceFont, sans-serif);
margin: 0;
color: $fallback--text;
color: var(--text, $fallback--text);
max-width: 100vw;
overflow-x: hidden;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
&.hidden {
display: none;
}
}
a {
text-decoration: none;
color: $fallback--link;
color: var(--link, $fallback--link);
}
.button-default { .button-default {
user-select: none; user-select: none;
color: $fallback--text; color: $fallback--text;
...@@ -166,12 +190,12 @@ a { ...@@ -166,12 +190,12 @@ a {
} }
&:hover { &:hover {
box-shadow: 0px 0px 4px rgba(255, 255, 255, 0.3); box-shadow: 0 0 4px rgba(255, 255, 255, 0.3);
box-shadow: var(--buttonHoverShadow); box-shadow: var(--buttonHoverShadow);
} }
&:active { &:active {
box-shadow: 0px 0px 4px 0px rgba(255, 255, 255, 0.3), 0px 1px 0px 0px rgba(0, 0, 0, 0.2) inset, 0px -1px 0px 0px rgba(255, 255, 255, 0.2) inset; 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: var(--buttonPressedShadow); box-shadow: var(--buttonPressedShadow);
color: $fallback--text; color: $fallback--text;
color: var(--btnPressedText, $fallback--text); color: var(--btnPressedText, $fallback--text);
...@@ -204,7 +228,7 @@ a { ...@@ -204,7 +228,7 @@ a {
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: 0px 0px 4px 0px rgba(255, 255, 255, 0.3), 0px 1px 0px 0px rgba(0, 0, 0, 0.2) inset, 0px -1px 0px 0px rgba(255, 255, 255, 0.2) inset; 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: var(--buttonPressedShadow); box-shadow: var(--buttonPressedShadow);
svg, svg,
...@@ -254,8 +278,9 @@ a { ...@@ -254,8 +278,9 @@ a {
} }
} }
input, textarea, .input { input,
textarea,
.input {
&.unstyled { &.unstyled {
border-radius: 0; border-radius: 0;
background: none; background: none;
...@@ -266,7 +291,7 @@ input, textarea, .input { ...@@ -266,7 +291,7 @@ input, textarea, .input {
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: 0px 1px 0px 0px rgba(0, 0, 0, 0.2) inset, 0px -1px 0px 0px rgba(255, 255, 255, 0.2) inset, 0px 0px 2px 0px rgba(0, 0, 0, 1) inset; 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: 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);
...@@ -282,9 +307,11 @@ input, textarea, .input { ...@@ -282,9 +307,11 @@ input, textarea, .input {
height: 28px; height: 28px;
line-height: 16px; line-height: 16px;
hyphens: none; hyphens: none;
padding: 8px .5em; padding: 8px 0.5em;
&:disabled, &[disabled=disabled], &.disabled { &:disabled,
&[disabled=disabled],
&.disabled {
cursor: not-allowed; cursor: not-allowed;
opacity: 0.5; opacity: 0.5;
} }
...@@ -299,18 +326,21 @@ input, textarea, .input { ...@@ -299,18 +326,21 @@ input, textarea, .input {
&[type=radio] { &[type=radio] {
display: none; display: none;
&:checked + label::before { &:checked + label::before {
box-shadow: 0px 0px 2px black inset, 0px 0px 0px 4px $fallback--fg inset; box-shadow: 0 0 2px black inset, 0 0 0 4px $fallback--fg inset;
box-shadow: var(--inputShadow), 0px 0px 0px 4px var(--fg, $fallback--fg) inset; box-shadow: var(--inputShadow), 0 0 0 4px var(--fg, $fallback--fg) inset;
background-color: var(--accent, $fallback--link); background-color: var(--accent, $fallback--link);
} }
&:disabled { &:disabled {
&, &,
& + label, & + label,
& + label::before { & + label::before {
opacity: .5; opacity: 0.5;
} }
} }
+ label::before { + label::before {
flex-shrink: 0; flex-shrink: 0;
display: inline-block; display: inline-block;
...@@ -319,9 +349,9 @@ input, textarea, .input { ...@@ -319,9 +349,9 @@ input, textarea, .input {
width: 1.1em; width: 1.1em;
height: 1.1em; height: 1.1em;
border-radius: 100%; // Radio buttons should always be circle border-radius: 100%; // Radio buttons should always be circle
box-shadow: 0px 0px 2px black inset; box-shadow: 0 0 2px black inset;
box-shadow: var(--inputShadow); box-shadow: var(--inputShadow);
margin-right: .5em; margin-right: 0.5em;
background-color: $fallback--fg; background-color: $fallback--fg;
background-color: var(--input, $fallback--fg); background-color: var(--input, $fallback--fg);
vertical-align: top; vertical-align: top;
...@@ -337,17 +367,20 @@ input, textarea, .input { ...@@ -337,17 +367,20 @@ input, textarea, .input {
&[type=checkbox] { &[type=checkbox] {
display: none; display: none;
&:checked + label::before { &:checked + label::before {
color: $fallback--text; color: $fallback--text;
color: var(--inputText, $fallback--text); color: var(--inputText, $fallback--text);
} }
&:disabled { &:disabled {
&, &,
& + label, & + label,
& + label::before { & + label::before {
opacity: .5; opacity: 0.5;
} }
} }
+ label::before { + label::before {
flex-shrink: 0; flex-shrink: 0;
display: inline-block; display: inline-block;
...@@ -357,9 +390,9 @@ input, textarea, .input { ...@@ -357,9 +390,9 @@ input, textarea, .input {
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);
margin-right: .5em; margin-right: 0.5em;
background-color: $fallback--fg; background-color: $fallback--fg;
background-color: var(--input, $fallback--fg); background-color: var(--input, $fallback--fg);
vertical-align: top; vertical-align: top;
...@@ -387,6 +420,7 @@ option { ...@@ -387,6 +420,7 @@ option {
.hide-number-spinner { .hide-number-spinner {
-moz-appearance: textfield; -moz-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;
...@@ -394,7 +428,8 @@ option { ...@@ -394,7 +428,8 @@ option {
} }
} }
i[class*=icon-], .svg-inline--fa { i[class*=icon-],
.svg-inline--fa {
color: $fallback--icon; color: $fallback--icon;
color: var(--icon, $fallback--icon); color: var(--icon, $fallback--icon);
} }
...@@ -426,10 +461,6 @@ i[class*=icon-], .svg-inline--fa { ...@@ -426,10 +461,6 @@ i[class*=icon-], .svg-inline--fa {
} }
.auto-size { .auto-size {
flex: 1
}
main-router {
flex: 1; flex: 1;
} }
...@@ -439,23 +470,21 @@ main-router { ...@@ -439,23 +470,21 @@ main-router {
p { p {
margin: 0; margin: 0;
font-size: 0.8em font-size: 0.8em;
} }
} }
/* Panel */ /* Panel */
.panel { .panel {
display: flex;
position: relative; position: relative;
display: flex;
flex-direction: column; flex-direction: column;
margin: 0.5em; z-index: 0;
background-color: $fallback--bg; background-color: $fallback--bg;
background-color: var(--bg, $fallback--bg); background-color: var(--bg, $fallback--bg);
&::after, & { &::after,
& {
border-radius: $fallback--panelRadius; border-radius: $fallback--panelRadius;
border-radius: var(--panelRadius, $fallback--panelRadius); border-radius: var(--panelRadius, $fallback--panelRadius);
} }
...@@ -463,16 +492,14 @@ main-router { ...@@ -463,16 +492,14 @@ main-router {
&::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: 2;
pointer-events: none; box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6);
box-shadow: 1px 1px 4px rgba(0,0,0,.6);
box-shadow: var(--panelShadow); box-shadow: var(--panelShadow);
pointer-events: none;
} }
} }
...@@ -484,19 +511,67 @@ main-router { ...@@ -484,19 +511,67 @@ main-router {
} }
.panel-heading { .panel-heading {
position: relative;
box-sizing: border-box;
display: flex; display: flex;
flex: none; flex: none;
border-radius: $fallback--panelRadius $fallback--panelRadius 0 0; border-radius: $fallback--panelRadius $fallback--panelRadius 0 0;
border-radius: var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius) 0 0; border-radius: var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius) 0 0;
background-size: cover; background-size: cover;
padding: .6em .6em; padding: 0.6em 0.6em;
text-align: left; text-align: left;
line-height: 28px; line-height: 28px;
color: var(--panelText); color: var(--panelText);
background-color: $fallback--fg; background-color: $fallback--bg;
background-color: var(--panel, $fallback--fg); background-color: var(--bg, $fallback--bg);
align-items: baseline; align-items: baseline;
box-shadow: var(--panelHeaderShadow); height: var(--panelHeadingHeight);
z-index: -2;
--panelHeadingHeight: 45px;
&.-flexible-height {
--panelHeadingHeight: auto;
&::after,
&::before {
display: none;
}
}
&.-sticky {
position: sticky;
top: 0;
z-index: 2;
}
&::after,
&::before {
content: '';
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
pointer-events: none;
}
&::after {
background-color: $fallback--fg;
background-color: var(--panel, $fallback--fg);
z-index: -2;
border-radius: $fallback--panelRadius $fallback--panelRadius 0 0;
border-radius: var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius) 0 0;
box-shadow: var(--panelHeaderShadow);
}
&::before {
bottom: -20px;
z-index: -1;
border-radius: $fallback--panelRadius $fallback--panelRadius 0 0;
border-radius: var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius) 0 0;
mask: linear-gradient(to bottom, white var(--panelHeadingHeight), transparent var(--panelHeadingHeight));
}
.title { .title {
flex: 1 0 auto; flex: 1 0 auto;
...@@ -527,7 +602,7 @@ main-router { ...@@ -527,7 +602,7 @@ main-router {
min-height: 0; min-height: 0;
box-sizing: border-box; box-sizing: border-box;
margin: 0; margin: 0;
margin-left: .5em; margin-left: 0.5em;
min-width: 1px; min-width: 1px;
align-self: stretch; align-self: stretch;
} }
...@@ -562,7 +637,7 @@ main-router { ...@@ -562,7 +637,7 @@ main-router {
a, a,
.-link { .-link {
color: $fallback--link; color: $fallback--link;
color: var(--panelLink, $fallback--link) color: var(--panelLink, $fallback--link);
} }
} }
...@@ -574,7 +649,7 @@ main-router { ...@@ -574,7 +649,7 @@ main-router {
/* TODO Should remove timeline-footer from here when we refactor panels into /* TODO Should remove timeline-footer from here when we refactor panels into
* separate component and utilize slots * separate component and utilize slots
*/ */
.panel-footer, .timeline-footer { .panel-footer {
display: flex; display: flex;
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);
...@@ -605,37 +680,18 @@ main-router { ...@@ -605,37 +680,18 @@ main-router {
margin: 0; margin: 0;
} }
.container > * {
min-width: 0px;
}
.fa { .fa {
color: grey; color: grey;
} }
nav { .fade-enter-active,
z-index: 1000; .fade-leave-active {
color: var(--topBarText); transition: opacity 0.2s;
background-color: $fallback--fg;
background-color: var(--topBar, $fallback--fg);
color: $fallback--faint;
color: var(--faint, $fallback--faint);
box-shadow: 0px 0px 4px rgba(0,0,0,.6);
box-shadow: var(--topBarShadow);
box-sizing: border-box;
}
.fade-enter-active, .fade-leave-active {
transition: opacity .2s
}
.fade-enter-from, .fade-leave-active {
opacity: 0
} }
.main { .fade-enter-from,
flex-basis: 50%; .fade-leave-active {
flex-grow: 1; opacity: 0;
flex-shrink: 1;
} }
.sidebar-bounds { .sidebar-bounds {
...@@ -653,34 +709,6 @@ nav { ...@@ -653,34 +709,6 @@ nav {
display: none; display: none;
} }
@media all and (min-width: 800px) {
.sidebar-bounds {
overflow: hidden;
max-height: 100vh;
width: 345px;
position: fixed;
margin-top: -10px;
.sidebar-scroller {
height: 96vh;
width: 365px;
padding-top: 10px;
padding-right: 50px;
overflow-x: hidden;
overflow-y: scroll;
}
.sidebar {
width: 345px;
}
}
.sidebar-flexer {
max-height: 96vh;
flex-shrink: 0;
flex-grow: 0;
}
}
.badge { .badge {
box-sizing: border-box; box-sizing: border-box;
display: inline-block; display: inline-block;
...@@ -764,7 +792,7 @@ nav { ...@@ -764,7 +792,7 @@ nav {
} }
.visibility-notice { .visibility-notice {
padding: .5em; padding: 0.5em;
border: 1px solid $fallback--faint; border: 1px solid $fallback--faint;
border: 1px solid var(--faint, $fallback--faint); border: 1px solid var(--faint, $fallback--faint);
border-radius: $fallback--inputRadius; border-radius: $fallback--inputRadius;
...@@ -779,7 +807,7 @@ nav { ...@@ -779,7 +807,7 @@ nav {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
padding: .5em; padding: 0.5em;
color: inherit; color: inherit;
} }
} }
...@@ -796,30 +824,57 @@ nav { ...@@ -796,30 +824,57 @@ nav {
} }
} }
@keyframes shakeError { .login-hint {
0% { text-align: center;
transform: translateX(0);
} @media all and (min-width: 801px) {
15% { display: none;
transform: translateX(0.375rem);
}
30% {
transform: translateX(-0.375rem);
}
45% {
transform: translateX(0.375rem);
}
60% {
transform: translateX(-0.375rem);
} }
75% {
transform: translateX(0.375rem); a {
display: inline-block;
padding: 1em 0;
width: 100%;
} }
90% { }
transform: translateX(-0.375rem);
.btn.button-default {
min-height: 28px;
}
.new-status-notification {
position: relative;
font-size: 1.1em;
z-index: 1;
flex: 1;
}
@media all and (min-width: 800px) {
.sidebar-bounds {
overflow: hidden;
max-height: 100vh;
width: 345px;
position: fixed;
margin-top: -10px;
.sidebar-scroller {
height: 96vh;
width: 365px;
padding-top: 10px;
padding-right: 50px;
overflow-x: hidden;
overflow-y: scroll;
}
.sidebar {
width: 345px;
}
} }
100% {
transform: translateX(0); .sidebar-flexer {
max-height: 96vh;
flex-shrink: 0;
flex-grow: 0;
} }
} }
...@@ -832,14 +887,6 @@ nav { ...@@ -832,14 +887,6 @@ nav {
display: flex; display: flex;
} }
.container {
padding: 0;
}
.panel {
margin: 0.5em 0 0.5em 0;
}
.menu-button { .menu-button {
display: block; display: block;
margin-right: 0.8em; margin-right: 0.8em;
...@@ -850,41 +897,6 @@ nav { ...@@ -850,41 +897,6 @@ nav {
} }
} }
.setting-list,
.option-list{
list-style-type: none;
padding-left: 2em;
li {
margin-bottom: 0.5em;
}
.suboptions {
margin-top: 0.3em
}
}
.login-hint {
text-align: center;
@media all and (min-width: 801px) {
display: none;
}
a {
display: inline-block;
padding: 1em 0px;
width: 100%;
}
}
.btn.button-default {
min-height: 28px;
}
.animate-spin {
animation: spin 2s infinite linear;
display: inline-block;
}
@keyframes spin { @keyframes spin {
0% { 0% {
transform: rotate(0deg); transform: rotate(0deg);
...@@ -895,45 +907,36 @@ nav { ...@@ -895,45 +907,36 @@ nav {
} }
} }
.new-status-notification { @keyframes shakeError {
position: relative; 0% {
font-size: 1.1em; transform: translateX(0);
z-index: 1; }
flex: 1;
}
.chat-layout { 15% {
// Needed for smoother chat navigation in the desktop Safari (otherwise the chat layout "jumps" as the chat opens). transform: translateX(0.375rem);
overflow: hidden; }
height: 100%;
// Get rid of scrollbar on body as scrolling happens on different element 30% {
// Ensures the fixed position of the mobile browser bars on scroll up / down events. transform: translateX(-0.375rem);
// Prevents the mobile browser bars from overlapping or hiding the message posting form. }
@media all and (max-width: 800px) {
body {
height: 100%;
}
#app { 45% {
height: 100%; transform: translateX(0.375rem);
overflow: hidden; }
min-height: auto;
}
#app_bg_wrapper { 60% {
overflow: hidden; transform: translateX(-0.375rem);
} }
.main { 75% {
overflow: hidden; transform: translateX(0.375rem);
height: 100%; }
}
#content { 90% {
padding-top: 0; transform: translateX(-0.375rem);
height: 100%; }
overflow: visible;
} 100% {
transform: translateX(0);
} }
} }
...@@ -7,28 +7,28 @@ ...@@ -7,28 +7,28 @@
id="app_bg_wrapper" id="app_bg_wrapper"
class="app-bg-wrapper" class="app-bg-wrapper"
/> />
<MobileNav class="navbar" v-if="isMobileLayout" /> <MobileNav v-if="isMobileLayout" />
<DesktopNav class="navbar" v-else /> <DesktopNav v-else />
<div class="app-bg-wrapper app-container-wrapper" />
<div <div
id="content" id="content"
class="app-layout container" class="app-layout container"
:class="{ '-reverse': reverseLayout }"
> >
<div class="underlay"/> <div class="underlay"/>
<div <div
id="sidebar"
class="column -scrollable -mini mobile-hidden" class="column -scrollable -mini mobile-hidden"
:style="sidebarAlign"
> >
<user-panel /> <user-panel />
<div v-if="!isMobileLayout"> <template v-if="!isMobileLayout">
<nav-panel /> <nav-panel />
<instance-specific-panel v-if="showInstanceSpecificPanel" /> <instance-specific-panel v-if="showInstanceSpecificPanel" />
<features-panel v-if="!currentUser && showFeaturesPanel" /> <features-panel v-if="!currentUser && showFeaturesPanel" />
<who-to-follow-panel v-if="currentUser && suggestionsEnabled" /> <who-to-follow-panel v-if="currentUser && suggestionsEnabled" />
<notifications v-if="currentUser" /> <notifications v-if="currentUser" />
</div> </template>
</div> </div>
<div class="column main"> <div id="main-scroller" class="column main">
<div <div
v-if="!currentUser" v-if="!currentUser"
class="login-hint panel panel-default" class="login-hint panel panel-default"
......
...@@ -6,7 +6,7 @@ import PostStatusForm from '../post_status_form/post_status_form.vue' ...@@ -6,7 +6,7 @@ import PostStatusForm from '../post_status_form/post_status_form.vue'
import ChatTitle from '../chat_title/chat_title.vue' import ChatTitle from '../chat_title/chat_title.vue'
import chatService from '../../services/chat_service/chat_service.js' import chatService from '../../services/chat_service/chat_service.js'
import { promiseInterval } from '../../services/promise_interval/promise_interval.js' import { promiseInterval } from '../../services/promise_interval/promise_interval.js'
import { getScrollPosition, getNewTopPosition, isBottomedOut, scrollableContainerHeight, isScrollable } from './chat_layout_utils.js' import { getScrollPosition, getNewTopPosition, isBottomedOut } from './chat_layout_utils.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
faChevronDown, faChevronDown,
...@@ -20,7 +20,7 @@ library.add( ...@@ -20,7 +20,7 @@ library.add(
) )
const BOTTOMED_OUT_OFFSET = 10 const BOTTOMED_OUT_OFFSET = 10
const JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET = 150 const JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET = 10
const SAFE_RESIZE_TIME_OFFSET = 100 const SAFE_RESIZE_TIME_OFFSET = 100
const MARK_AS_READ_DELAY = 1500 const MARK_AS_READ_DELAY = 1500
const MAX_RETRIES = 10 const MAX_RETRIES = 10
...@@ -52,7 +52,6 @@ const Chat = { ...@@ -52,7 +52,6 @@ const Chat = {
} }
this.$nextTick(() => { this.$nextTick(() => {
this.updateScrollableContainerHeight()
this.handleResize() this.handleResize()
}) })
this.setChatLayout() this.setChatLayout()
...@@ -132,7 +131,6 @@ const Chat = { ...@@ -132,7 +131,6 @@ const Chat = {
onFilesDropped () { onFilesDropped () {
this.$nextTick(() => { this.$nextTick(() => {
this.handleResize() this.handleResize()
this.updateScrollableContainerHeight()
}) })
}, },
handleVisibilityChange () { handleVisibilityChange () {
...@@ -154,10 +152,6 @@ const Chat = { ...@@ -154,10 +152,6 @@ const Chat = {
if (html) { if (html) {
html.classList.add('chat-layout') html.classList.add('chat-layout')
} }
this.$nextTick(() => {
this.updateScrollableContainerHeight()
})
}, },
unsetChatLayout () { unsetChatLayout () {
let html = document.querySelector('html') let html = document.querySelector('html')
...@@ -167,17 +161,9 @@ const Chat = { ...@@ -167,17 +161,9 @@ const Chat = {
}, },
handleLayoutChange () { handleLayoutChange () {
this.$nextTick(() => { this.$nextTick(() => {
this.updateScrollableContainerHeight()
this.scrollDown() this.scrollDown()
}) })
}, },
// Ensures the proper position of the posting form in the mobile layout (the mobile browser panel does not overlap or hide it)
updateScrollableContainerHeight () {
const header = this.$refs.header
const footer = this.$refs.footer
const inner = this.mobileLayout ? window.document.body : this.$refs.inner
this.scrollableContainerHeight = scrollableContainerHeight(inner, header, footer) + 'px'
},
// Preserves the scroll position when OSK appears or the posting form changes its height. // Preserves the scroll position when OSK appears or the posting form changes its height.
handleResize (opts = {}) { handleResize (opts = {}) {
const { expand = false, delayed = false } = opts const { expand = false, delayed = false } = opts
...@@ -190,17 +176,14 @@ const Chat = { ...@@ -190,17 +176,14 @@ const Chat = {
} }
this.$nextTick(() => { this.$nextTick(() => {
this.updateScrollableContainerHeight()
const { offsetHeight = undefined } = this.lastScrollPosition const { offsetHeight = undefined } = this.lastScrollPosition
this.lastScrollPosition = getScrollPosition(this.$refs.scrollable) this.lastScrollPosition = getScrollPosition(document.getElementById('content'))
const diff = this.lastScrollPosition.offsetHeight - offsetHeight const diff = this.lastScrollPosition.offsetHeight - offsetHeight
if (diff < 0 || (!this.bottomedOut() && expand)) { if (diff < 0 || (!this.bottomedOut() && expand)) {
this.$nextTick(() => { this.$nextTick(() => {
this.updateScrollableContainerHeight() document.getElementById('content').scrollTo({
this.$refs.scrollable.scrollTo({ top: document.getElementById('content').scrollTop - diff,
top: this.$refs.scrollable.scrollTop - diff,
left: 0 left: 0
}) })
}) })
...@@ -209,7 +192,7 @@ const Chat = { ...@@ -209,7 +192,7 @@ const Chat = {
}, },
scrollDown (options = {}) { scrollDown (options = {}) {
const { behavior = 'auto', forceRead = false } = options const { behavior = 'auto', forceRead = false } = options
const scrollable = this.$refs.scrollable const scrollable = document.getElementById('content')
if (!scrollable) { return } if (!scrollable) { return }
this.$nextTick(() => { this.$nextTick(() => {
scrollable.scrollTo({ top: scrollable.scrollHeight, left: 0, behavior }) scrollable.scrollTo({ top: scrollable.scrollHeight, left: 0, behavior })
...@@ -228,10 +211,10 @@ const Chat = { ...@@ -228,10 +211,10 @@ const Chat = {
}) })
}, },
bottomedOut (offset) { bottomedOut (offset) {
return isBottomedOut(this.$refs.scrollable, offset) return isBottomedOut(document.getElementById('content'), offset)
}, },
reachedTop () { reachedTop () {
const scrollable = this.$refs.scrollable const scrollable = document.getElementById('content')
return scrollable && scrollable.scrollTop <= 0 return scrollable && scrollable.scrollTop <= 0
}, },
cullOlderCheck () { cullOlderCheck () {
...@@ -263,7 +246,7 @@ const Chat = { ...@@ -263,7 +246,7 @@ const Chat = {
} }
}, 200), }, 200),
handleScrollUp (positionBeforeLoading) { handleScrollUp (positionBeforeLoading) {
const positionAfterLoading = getScrollPosition(this.$refs.scrollable) const positionAfterLoading = getScrollPosition(document.getElementById('content'))
this.$refs.scrollable.scrollTo({ this.$refs.scrollable.scrollTo({
top: getNewTopPosition(positionBeforeLoading, positionAfterLoading), top: getNewTopPosition(positionBeforeLoading, positionAfterLoading),
left: 0 left: 0
...@@ -285,22 +268,18 @@ const Chat = { ...@@ -285,22 +268,18 @@ const Chat = {
chatService.clear(chatMessageService) chatService.clear(chatMessageService)
} }
const positionBeforeUpdate = getScrollPosition(this.$refs.scrollable) const positionBeforeUpdate = getScrollPosition(document.getElementById('content'))
this.$store.dispatch('addChatMessages', { chatId, messages }).then(() => { this.$store.dispatch('addChatMessages', { chatId, messages }).then(() => {
this.$nextTick(() => { this.$nextTick(() => {
if (fetchOlderMessages) { if (fetchOlderMessages) {
this.handleScrollUp(positionBeforeUpdate) this.handleScrollUp(positionBeforeUpdate)
} }
if (isFirstFetch) {
this.updateScrollableContainerHeight()
}
// In vertical screens, the first batch of fetched messages may not always take the // In vertical screens, the first batch of fetched messages may not always take the
// full height of the scrollable container. // full height of the scrollable container.
// If this is the case, we want to fetch the messages until the scrollable container // If this is the case, we want to fetch the messages until the scrollable container
// is fully populated so that the user has the ability to scroll up and load the history. // is fully populated so that the user has the ability to scroll up and load the history.
if (!isScrollable(this.$refs.scrollable) && messages.length > 0) { if (messages.length > 0) {
this.fetchChat({ maxId: this.currentChatMessageService.minId }) this.fetchChat({ maxId: this.currentChatMessageService.minId })
} }
}) })
...@@ -336,9 +315,6 @@ const Chat = { ...@@ -336,9 +315,6 @@ const Chat = {
this.handleResize() this.handleResize()
// When the posting form size changes because of a media attachment, we need an extra resize // When the posting form size changes because of a media attachment, we need an extra resize
// to account for the potential delay in the DOM update. // to account for the potential delay in the DOM update.
setTimeout(() => {
this.updateScrollableContainerHeight()
}, SAFE_RESIZE_TIME_OFFSET)
this.scrollDown({ forceRead: true }) this.scrollDown({ forceRead: true })
}) })
}, },
......
.chat-view { .chat-view {
display: flex; display: flex;
height: calc(100vh - 60px); height: 100%;
width: 100%;
.chat-title {
// prevents chat header jumping on when the user avatar loads
height: 28px;
}
.chat-view-inner { .chat-view-inner {
height: auto; height: auto;
width: 100%; width: 100%;
overflow: visible; overflow: visible;
display: flex; display: flex;
margin: 0.5em 0.5em 0 0.5em;
} }
.chat-view-body { .chat-view-body {
...@@ -32,11 +25,9 @@ ...@@ -32,11 +25,9 @@
} }
} }
.scrollable-message-list { .message-list {
padding: 0 0.8em; padding: 0 0.8em;
height: 100%; height: 100%;
overflow-y: scroll;
overflow-x: hidden;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
...@@ -44,12 +35,13 @@ ...@@ -44,12 +35,13 @@
.footer { .footer {
position: sticky; position: sticky;
bottom: 0; bottom: 0;
background-color: $fallback--bg;
background-color: var(--bg, $fallback--bg);
} }
.chat-view-heading { .chat-view-heading {
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
top: 50px;
display: flex; display: flex;
z-index: 2; z-index: 2;
position: sticky; position: sticky;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
> >
<div <div
ref="header" ref="header"
class="panel-heading chat-view-heading mobile-hidden" class="panel-heading -sticky chat-view-heading mobile-hidden"
> >
<a <a
class="go-back-button" class="go-back-button"
...@@ -27,10 +27,8 @@ ...@@ -27,10 +27,8 @@
</div> </div>
</div> </div>
<div <div
ref="scrollable" class="message-list"
class="scrollable-message-list"
:style="{ height: scrollableContainerHeight }" :style="{ height: scrollableContainerHeight }"
@scroll="handleScroll"
> >
<template v-if="!errorLoadingChat"> <template v-if="!errorLoadingChat">
<ChatMessage <ChatMessage
......
// Captures a scroll position // Captures a scroll position
export const getScrollPosition = (el) => { export const getScrollPosition = (el) => {
console.log(el)
return { return {
scrollTop: el.scrollTop, scrollTop: el.scrollTop,
scrollHeight: el.scrollHeight, scrollHeight: el.scrollHeight,
......
...@@ -181,7 +181,7 @@ ...@@ -181,7 +181,7 @@
.mobile-notifications { .mobile-notifications {
margin-top: 50px; margin-top: 50px;
width: 100vw; width: 100vw;
height: calc(100vh - 50px); height: calc(100vh - var(--navbar-height));
overflow-x: hidden; overflow-x: hidden;
overflow-y: scroll; overflow-y: scroll;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<div :class="mainClass"> <div :class="mainClass">
<div <div
v-if="!noHeading" v-if="!noHeading"
class="panel-heading" class="notifications-heading panel-heading -sticky"
> >
<div class="title"> <div class="title">
{{ $t('notifications.notifications') }} {{ $t('notifications.notifications') }}
......
...@@ -91,6 +91,9 @@ ...@@ -91,6 +91,9 @@
flex-direction: column; flex-direction: column;
margin-top: 0.6em; margin-top: 0.6em;
max-width: 18rem; max-width: 18rem;
> * {
min-width: 0;
}
} }
.form-group { .form-group {
......
...@@ -271,7 +271,10 @@ $validations-cRed: #f04124; ...@@ -271,7 +271,10 @@ $validations-cRed: #f04124;
.container { .container {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
//margin-bottom: 1em;
> * {
min-width: 0;
}
} }
.terms-of-service { .terms-of-service {
......
...@@ -2,6 +2,18 @@ ...@@ -2,6 +2,18 @@
.settings-modal { .settings-modal {
overflow: hidden; overflow: hidden;
.setting-list,
.option-list {
list-style-type: none;
padding-left: 2em;
li {
margin-bottom: 0.5em;
}
.suboptions {
margin-top: 0.3em
}
}
&.peek { &.peek {
.settings-modal-panel { .settings-modal-panel {
/* Explanation: /* Explanation:
......
...@@ -42,6 +42,10 @@ ...@@ -42,6 +42,10 @@
display: flex; display: flex;
padding: var(--status-margin, $status-margin); padding: var(--status-margin, $status-margin);
> * {
min-width: 0;
}
&.-repeat { &.-repeat {
padding-top: 0; padding-top: 0;
} }
......
...@@ -64,7 +64,7 @@ const Timeline = { ...@@ -64,7 +64,7 @@ const Timeline = {
if (this.blockingClicks) rootClasses = rootClasses.concat(['-blocked', '_misclick-prevention']) if (this.blockingClicks) rootClasses = rootClasses.concat(['-blocked', '_misclick-prevention'])
return { return {
root: rootClasses, root: rootClasses,
header: ['timeline-heading'].concat(!this.embedded ? ['panel-heading'] : []), header: ['timeline-heading'].concat(!this.embedded ? ['panel-heading', '-sticky'] : []),
body: ['timeline-body'].concat(!this.embedded ? ['panel-body'] : []), body: ['timeline-body'].concat(!this.embedded ? ['panel-body'] : []),
footer: ['timeline-footer'].concat(!this.embedded ? ['panel-footer'] : []) footer: ['timeline-footer'].concat(!this.embedded ? ['panel-footer'] : [])
} }
...@@ -89,7 +89,7 @@ const Timeline = { ...@@ -89,7 +89,7 @@ const Timeline = {
const credentials = store.state.users.currentUser.credentials const credentials = store.state.users.currentUser.credentials
const showImmediately = this.timeline.visibleStatuses.length === 0 const showImmediately = this.timeline.visibleStatuses.length === 0
window.addEventListener('scroll', this.handleScroll) document.getElementById('content').addEventListener('scroll', this.handleScroll)
if (store.state.api.fetchers[this.timelineName]) { return false } if (store.state.api.fetchers[this.timelineName]) { return false }
...@@ -111,7 +111,7 @@ const Timeline = { ...@@ -111,7 +111,7 @@ const Timeline = {
setTimeout(this.determineVisibleStatuses, 250) setTimeout(this.determineVisibleStatuses, 250)
}, },
unmounted () { unmounted () {
window.removeEventListener('scroll', this.handleScroll) document.getElementById('content').removeEventListener('scroll', this.handleScroll)
window.removeEventListener('keydown', this.handleShortKey) window.removeEventListener('keydown', this.handleShortKey)
if (typeof document.hidden !== 'undefined') document.removeEventListener('visibilitychange', this.handleVisibilityChange, false) if (typeof document.hidden !== 'undefined') document.removeEventListener('visibilitychange', this.handleVisibilityChange, false)
this.$store.commit('setLoading', { timeline: this.timelineName, value: false }) this.$store.commit('setLoading', { timeline: this.timelineName, value: false })
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
max-width: 100%; max-width: 100%;
flex-wrap: nowrap; flex-wrap: nowrap;
align-items: center; align-items: center;
position: relative;
.loadmore-button { .loadmore-button {
flex-shrink: 0; flex-shrink: 0;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
:style="style" :style="style"
class="background-image" class="background-image"
/> />
<div class="panel-heading"> <div class="panel-heading -flexible-height">
<div class="user-info"> <div class="user-info">
<div class="container"> <div class="container">
<a <a
...@@ -331,6 +331,7 @@ ...@@ -331,6 +331,7 @@
border-top-left-radius: calc(var(--panelRadius) - 1px); border-top-left-radius: calc(var(--panelRadius) - 1px);
border-top-right-radius: calc(var(--panelRadius) - 1px); border-top-right-radius: calc(var(--panelRadius) - 1px);
background-color: var(--profileBg); background-color: var(--profileBg);
z-index: -2;
&.hide-bio { &.hide-bio {
mask-size: 100% 40px; mask-size: 100% 40px;
...@@ -385,11 +386,16 @@ ...@@ -385,11 +386,16 @@
padding: 0 26px; padding: 0 26px;
.container { .container {
min-width: 0;
padding: 16px 0 6px; padding: 16px 0 6px;
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
max-height: 56px; max-height: 56px;
> * {
min-width: 0;
}
.Avatar { .Avatar {
--_avatarShadowBox: var(--avatarShadow); --_avatarShadowBox: var(--avatarShadow);
--_avatarShadowFilter: var(--avatarShadowFilter); --_avatarShadowFilter: var(--avatarShadowFilter);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment