@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 { /* Slide switching is made using the `onTransitionEnd` event, so don't remove the animation */ 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; } .contentInner { width: 100%; } .name { width: calc(100% * var(--slide-translate-scale)); } } .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: 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; left: 0; width: 100%; top: 4rem; bottom: calc(4.25rem + env(safe-area-inset-bottom)); 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; } .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; 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: min(35rem, 80vh); } .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); &:hover { text-decoration: underline; } } } .headerTitle { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .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; } .fromPeer { display: flex; align-items: center; gap: 0.25rem; cursor: var(--custom-cursor, pointer); &:hover { text-decoration: underline; } }