TelegramPWA/src/components/story/StoryViewer.module.scss

767 lines
13 KiB
SCSS

@use "../../styles/mixins";
.root {
--color-story-meta: rgb(242, 242, 242);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: var(--z-story-viewer);
transform-origin: 50% 50%;
// Potential perf improvement
&:not(:global(.shown)) {
display: block !important;
transform: scale(0);
}
&:global(.opacity-transition) {
transition: opacity 250ms;
}
:global(.text-entity-link) {
--color-links: var(--color-white);
text-decoration: underline !important;
&:hover {
text-decoration: none !important;
}
}
}
.fullSize, .backdrop, .captionBackdrop {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.captionBackdrop {
background-color: rgba(0, 0, 0, 0.5);
}
.backdrop {
background-color: rgba(0, 0, 0, 0.9);
z-index: 0;
@media (max-width: 600px) {
background: rgba(0, 0, 0, 1);
}
}
.backdropNonInteractive {
position: absolute;
top: 50%;
left: 0;
right: 0;
transform: translateY(-50%);
}
.close {
position: absolute;
right: 1rem;
top: 1rem;
z-index: 3;
@media (max-width: 600px) {
display: none;
}
}
.wrapper {
position: absolute;
top: 0;
left: 50%;
width: 100vw;
height: 100%;
overflow: hidden;
transform: translateX(-50%);
max-width: calc(73.5rem * var(--story-viewer-scale));
z-index: 2;
@media (max-width: 600px) {
max-width: 100%;
}
}
.slideAnimation {
transition: transform 350ms ease-in-out !important;
}
.slideAnimationToActive {
--border-radius-default-small: 0.25rem;
&::before {
pointer-events: none;
content: "";
position: absolute;
left: 0;
top: 0;
right: 0;
height: 4.5rem;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
z-index: 1;
}
.content {
opacity: 0;
}
}
.slideAnimationFromActive {
.storyHeader,
.composer,
.caption,
.captionGradient,
.captionBackdrop{
transition: opacity 250ms ease-in-out;
opacity: 0;
}
.media:not(.mediaPreview) {
opacity: 0 !important;
}
.mediaPreview {
opacity: 1;
}
.content {
opacity: 1 !important;
visibility: visible;
}
}
.slide {
position: absolute;
top: 50%;
left: 50%;
transform: translate3d(
calc(var(--slide-x, -50%) - var(--slide-translate-x, 0px)),
calc(-50% - var(--slide-translate-y, 0px)),
0
) scale(var(--slide-translate-scale, 1));
transform-origin: 0 50%;
border-radius: var(--border-radius-default-small);
@for $i from -4 through 4 {
$slideWidth: 10.875rem;
$basis: 4.25rem;
@if $i < 0 {
$basis: -12.625rem;
}
$offset: $basis + $i * $slideWidth;
&:global(.slide-#{$i}) {
--slide-x: calc(#{$offset} * var(--story-viewer-scale));
}
}
}
.mobileSlide {
width: 100%;
height: 100%;
transform: translateY(var(--slide-translate-y, 0px));
}
.slidePreview {
overflow: hidden;
transition: opacity 200ms ease-in-out;
&.slideAnimationToActive::before {
transition: opacity 350ms ease-in-out !important;
opacity: 0;
}
.root:global(.not-open) &,
:global(body.ghost-animating) & {
opacity: 0;
}
}
.activeSlide {
height: calc(var(--slide-media-height) + 3.5rem);
z-index: 1;
&::before {
pointer-events: none;
content: "";
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 3.5rem;
background: rgba(0, 0, 0, 0.5);
opacity: 0;
z-index: 3;
}
.content {
transform: scale(var(--slide-content-scale, 1));
opacity: 0;
}
}
.slideInner {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.mediaWrapper {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: #000;
border-radius: var(--border-radius-default-small);
overflow: hidden;
@media (max-width: 600px) {
width: calc(100% - 1rem) !important;
height: auto !important;
margin: 0.5rem;
bottom: 3.5rem;
@supports (bottom: calc(3.5rem + env(safe-area-inset-bottom))) {
bottom: calc(3.5rem + env(safe-area-inset-bottom));
}
}
:global(body.ghost-animating) & {
visibility: hidden;
}
}
.media {
position: absolute;
left: 0;
top: 0;
object-fit: cover;
width: inherit;
height: inherit;
border-radius: var(--border-radius-default-small);
transition: opacity 300ms;
@media (max-width: 600px) {
bottom: 0;
width: 100%;
height: 100%;
}
:global(body.ghost-animating) .activeSlide & {
visibility: hidden;
}
}
.content {
pointer-events: none;
position: absolute;
left: 0;
top: 0;
right: 0;
height: 100%;
background: rgba(0, 0, 0, 0.5);
transition: opacity 250ms ease-in-out;
z-index: 1;
}
.contentInner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
max-width: 90%;
}
.name {
margin-top: 0.25rem;
color: var(--color-white);
font-size: 1rem;
font-weight: 500;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.forward {
position: absolute;
right: 0.75rem;
bottom: 4.25rem;
opacity: 0.5;
z-index: 2;
transition: opacity 300ms;
&:hover {
opacity: 1;
}
@media (max-width: 600px) {
bottom: 4.75rem;
}
}
// Shared styles for the header that are also used in ghost animation
@mixin story-header {
position: absolute;
width: 100%;
content: "";
left: 0;
top: 0;
right: 0;
height: 5rem;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0));
z-index: 1;
border-radius: var(--border-radius-default-small) var(--border-radius-default-small) 0 0;
}
.storyHeader {
@include story-header;
@media (max-width: 600px) {
width: auto;
left: 0.5rem;
top: 0.5rem;
right: 0.5rem;
}
:global(body.ghost-animating) & {
background: none;
}
}
.storyIndicators {
position: absolute;
width: 100%;
height: 0.125rem;
padding: 0 0.375rem;
z-index: 2;
display: flex;
top: 0.5rem;
left: 0;
}
.sender {
position: absolute;
z-index: 2;
right: 0.5rem;
left: 1rem;
top: 1.25rem;
display: flex;
color: var(--color-white);
align-items: center;
}
.senderInfoTransition {
position: absolute;
}
.senderInfo {
display: flex;
align-items: center;
}
.senderMeta {
display: flex;
flex-direction: column;
margin-left: 0.75rem;
line-height: 1.25rem;
overflow: hidden;
}
.senderName {
font-size: 1rem;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
white-space: nowrap;
cursor: var(--custom-cursor, pointer);
}
.storyMetaRow {
display: flex;
align-items: center;
overflow: hidden;
}
.storyMeta {
font-size: 0.875rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: var(--color-story-meta);
& + & {
margin-left: 0.375rem;
&::before {
content: "";
width: 0.25rem;
height: 0.25rem;
border-radius: 50%;
background-color: var(--color-white);
display: inline-block;
margin-inline-end: 0.375rem;
position: relative;
top: -0.125rem;
}
}
}
.closeButton {
display: none;
@media (max-width: 600px) {
display: flex;
}
}
.actions {
margin-inline-start: auto;
display: flex;
align-items: center;
:global(.Button) {
color: white;
@media (max-width: 600px) {
display: flex;
&:active,
&.active,
&:hover,
&:focus {
background: none !important;
}
}
}
}
.visibilityButton {
min-width: 1.5rem;
height: 1.5rem;
border-radius: 1.5rem;
display: inline-flex;
align-items: center;
justify-content: center;
background: linear-gradient(180deg, var(--color-from) 0%, var(--color-to) 100%);
color: #fff;
font-size: 0.75rem;
cursor: var(--custom-cursor, pointer);
margin: 0 0.375rem;
> :global(.icon + .icon) {
margin-left: 0.125rem;
}
}
.visibilityButtonSelf {
padding: 0 0.25rem 0 0.375rem;
}
.button {
margin-left: 0.5rem;
> :global(.icon) {
font-size: 1.5rem !important;
}
}
.buttonMenu :global(.MenuItem:not(.destructive)) {
color: var(--color-text) !important;
}
.buttonMenu > :global(.Button.translucent) {
color: var(--color-white);
opacity: 0.5;
width: 2.25rem;
height: 2.25rem;
&:hover {
opacity: 1;
}
}
.captionGradient {
position: absolute;
bottom: 3.5rem;
left: 0;
right: 0;
height: 7rem;
overflow: hidden;
background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, transparent 100%);
border-radius: 0 0 var(--border-radius-default-small) var(--border-radius-default-small);
pointer-events: none;
}
.caption {
position: absolute;
bottom: 5rem;
left: 0;
width: 100%;
top: 4rem;
display: flex;
flex-direction: column;
justify-content: flex-end;
border-radius: 0 0 var(--border-radius-default-small) var(--border-radius-default-small);
overflow: hidden;
pointer-events: none;
@supports (bottom: env(safe-area-inset-bottom)) {
bottom: calc(4.25rem + env(safe-area-inset-bottom));
}
}
.captionInner {
position: relative;
word-break: break-word;
white-space: pre-wrap;
line-height: 1.25rem;
text-align: initial;
unicode-bidi: plaintext;
padding: 2rem 1rem 0;
overflow-x: hidden;
overflow-y: scroll;
scrollbar-gutter: stable;
@include mixins.adapt-padding-to-scrollbar(2rem);
}
.captionContent {
width: 100%;
color: var(--color-white);
font-size: var(--message-text-size, 1rem);
display: flex;
flex-direction: column;
min-height: 0;
pointer-events: all;
}
.captionText :global(.custom-emoji) {
vertical-align: middle;
}
.hasOverflow {
--_overflow-shift: 5.75rem;
transform: translateY(calc(100% - var(--_overflow-shift)));
}
.expanded {
transition: transform 400ms;
@include mixins.gradient-border-top(2rem);
&::before {
opacity: 1;
}
}
.animate {
transform: translateY(0) !important;
}
.withShowMore {
cursor: var(--custom-cursor, pointer);
.captionInner {
overflow-y: hidden;
mask-image: linear-gradient(to top, black 0%, black 0%), linear-gradient(to left, black 75%, transparent 100%);
mask-position: 100% 100%, 100% calc(var(--_overflow-shift) - 1.25rem);
mask-size: 100% 100%, calc(var(--expand-button-width, 0%) + 4rem) 1.25em;
mask-repeat: no-repeat;
-webkit-mask-composite: xor;
mask-composite: exclude;
}
}
.captionShowMore {
position: absolute;
bottom: -0.25rem;
right: 0.5rem;
color: var(--color-white);
font-weight: 500;
cursor: var(--custom-cursor, pointer);
}
.composer {
--color-background: #212121;
--color-placeholders: #707478;
--color-composer-button: #707478;
position: absolute;
height: 3rem;
bottom: 0;
left: 0;
margin-bottom: 0;
z-index: 3;
transition: transform var(--layer-transition), opacity 0.15s ease;
&:global(.Composer) {
--base-height: 3rem;
@media (max-width: 600px) {
padding: 0 0.5rem 0.5rem;
@supports (margin-bottom: env(safe-area-inset-bottom)) {
margin-bottom: env(safe-area-inset-bottom);
}
}
}
:global(.SymbolMenu .bubble) {
--offset-y: 3.25rem;
--offset-x: 4%;
--color-background-compact-menu: rgba(0, 0, 0, 0.3);
--color-interactive-element-hover: rgba(255, 255, 255, 0.1);
--color-text-secondary: #aaa;
--color-text-secondary-rgb: 255, 255, 255;
--color-text-lighter: #ccc;
--color-text: #fff;
--color-default-shadow: rgba(0, 0, 0, 0.3);
--color-background-selected: rgba(0, 0, 0, 0.2);
}
:global(.composer-wrapper) {
max-width: 100%;
}
:global(.message-input-wrapper .recording-state) {
color: #fff;
}
:global(.SymbolMenu-footer .Button.activated) {
--color-text: #fff;
}
:global(.input-scroller) {
--color-text: #fff;
max-height: 8rem;
}
:global(.is-symbol-menu-open) & {
transform: translate3d(0, calc(-1 * (var(--symbol-menu-height))), 0);
}
}
.navigate {
position: absolute;
top: 0;
bottom: 0;
width: 50%;
background: none;
padding: 0;
margin: 0;
border: none;
outline: none !important;
cursor: var(--custom-cursor, pointer);
}
.prev {
left: 0;
}
.next {
right: 0;
}
.modal :global(.modal-content) {
padding: 0.5rem !important;
max-height: 35rem;
@supports (max-height: min(80vh, 35rem)) {
max-height: min(80vh, 35rem);
}
}
.thumbnail {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: block;
object-fit: cover;
@media (max-width: 600px) {
border-radius: var(--border-radius-default-small);
}
}
.ghost {
position: absolute;
z-index: 1;
overflow: hidden;
transition: transform 200ms ease;
border-radius: var(--border-radius-default-small);
&:before {
@include story-header;
}
}
.ghost2 {
position: absolute;
z-index: 1;
overflow: hidden;
border-radius: 50%;
opacity: 0;
transition: transform 200ms ease, opacity 200ms ease;
}
.ghostImage {
width: 100%;
height: 100%;
user-select: none;
-webkit-user-select: none;
object-fit: cover;
}
.forwardHeader {
display: flex;
align-items: center;
gap: 0.125rem;
&.clickable {
cursor: var(--custom-cursor, pointer);
}
}
.forwardHeaderText {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.forwardHeader.clickable:hover & {
text-decoration: underline;
}
}
.forwardInfo {
--accent-color: var(--color-white);
--accent-background-color: rgba(0, 0, 0, 0.5);
width: fit-content;
max-width: 100%;
margin-bottom: 0.5rem;
z-index: 1;
}