Merge pull request #35 from Discours/share-popup

Share controls popup
This commit is contained in:
Igor Lobanov 2022-10-18 13:33:08 +02:00 committed by GitHub
commit 08ddd882f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 194 additions and 24 deletions

View File

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M2.8792 14.3342C1.67 13.125 1.67 11.1592 2.8792 9.94999L5.70771 7.12147L4.36417 5.77792L1.53565 8.60644C-0.416029 10.5581 -0.416029 13.7261 1.53565 15.6777C3.48733 17.6294 6.65527 17.6294 8.60695 15.6777L11.4355 12.8492L10.0919 11.5057L7.2634 14.3342C6.05421 15.5434 4.08839 15.5434 2.8792 14.3342ZM6.48498 12.1424L12.142 6.4854L10.7278 5.07114L5.07072 10.7282L6.48498 12.1424ZM5.77797 4.36412L8.60649 1.5356C10.5582 -0.416075 13.7261 -0.416075 15.6778 1.5356C17.6295 3.48728 17.6295 6.65522 15.6778 8.6069L12.8493 11.4354L11.5057 10.0919L14.3342 7.26335C15.5434 6.05416 15.5434 4.08834 14.3342 2.87915C13.125 1.66996 11.1592 1.66996 9.95003 2.87915L7.12151 5.70767L5.77797 4.36412Z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 812 B

View File

@ -33,3 +33,13 @@
transition: filter 0.2s;
}
}
.floor--group {
@include media-breakpoint-down(sm) {
.col-lg-6 {
.row {
margin: 0 0 0 divide(-$container-padding-x, 2);
}
}
}
}

View File

@ -11,7 +11,7 @@ interface GroupProps {
export default (props: GroupProps) => {
if (!props.articles) props.articles = []
return (
<div class="floor floor--important">
<div class="floor floor--important floor--group">
<Show when={props.articles.length > 4}>
<div class="wide-container row">
<div class="group__header col-12">{props.header}</div>

View File

@ -2,7 +2,7 @@
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
transform: translate(-50%, 0);
}
@keyframes spin {

View File

@ -20,6 +20,10 @@
}
}
.mainHeaderInner {
position: relative;
}
.headerFixed.headerScrolledBottom,
.headerFixed.headerScrolledTop {
.mainLogo {
@ -31,9 +35,26 @@
}
}
.popupShare {
opacity: 1;
transition: opacity 0.3s;
z-index: 1;
.headerScrolledTop & {
opacity: 0;
transition: opacity 0.3s, z-index 0s 0.3s;
z-index: -1;
}
}
.headerFixed {
position: fixed;
top: 0;
.fixed & {
bottom: 0;
margin-bottom: 0;
}
}
.headerInner {
@ -44,8 +65,7 @@
justify-content: space-between;
margin: 0;
&.fixed {
border-bottom: 4px solid #000;
.fixed & {
left: 0;
position: fixed;
right: 0;
@ -62,25 +82,33 @@
.mainLogo {
align-items: center;
display: inline-flex;
height: 70px;
height: 56px;
padding: 0 $container-padding-x 0 0;
position: relative;
transition: height 0.2s;
text-align: center;
z-index: 9;
@include media-breakpoint-up(md) {
height: 70px;
}
@include media-breakpoint-up(lg) {
height: 80px;
}
img {
height: 32px;
height: 20px;
object-fit: contain;
object-position: left;
transition: height 0.2s;
vertical-align: middle;
width: 100px;
@include media-breakpoint-up(md) {
height: 32px;
}
@include media-breakpoint-up(lg) {
width: 175px;
}
@ -113,6 +141,14 @@
padding-left: 0;
position: relative;
@include font-size(1.7rem);
@include media-breakpoint-down(md) {
display: none;
}
.fixed & {
display: block;
}
}
.mainNavigation {
@ -145,7 +181,7 @@
padding: divide($container-padding-x, 2);
}
&.fixed {
.fixed & {
display: inline-flex;
@include media-breakpoint-down(lg) {
@ -181,12 +217,8 @@
display: inline-flex;
float: right;
padding-right: 0;
padding-left: 0;
width: 2.2rem;
@include media-breakpoint-up(sm) {
padding-left: divide($container-padding-x, 2);
}
width: 2.2rem;
@include media-breakpoint-up(md) {
display: none;
@ -235,7 +267,7 @@
top: 0;
}
&.fixed {
.fixed & {
> div {
opacity: 0;
transition: opacity 0s;
@ -276,6 +308,10 @@
text-overflow: ellipsis;
white-space: nowrap;
width: 100%;
@include media-breakpoint-down(md) {
display: none;
}
}
.headerSearch {
@ -305,6 +341,7 @@
.articleControls {
display: flex;
justify-content: flex-end;
left: 0;
position: absolute;
top: 50%;

View File

@ -3,12 +3,14 @@ import Private from './Private'
import Notifications from './Notifications'
import { Icon } from './Icon'
import { Modal } from './Modal'
import { Popup } from './Popup'
import AuthModal from './AuthModal'
import { t } from '../../utils/intl'
import { useModalStore, showModal, useWarningsStore } from '../../stores/ui'
import {useModalStore, showModal, useWarningsStore, toggleModal} from '../../stores/ui'
import { useAuthStore } from '../../stores/auth'
import { handleClientRouteLinkClick, router, Routes, useRouter } from '../../stores/router'
import styles from './Header.module.scss'
import stylesPopup from './Popup.module.scss'
import privateStyles from './Private.module.scss'
import { getPagePath } from '@nanostores/router'
import { getLogger } from '../../utils/logger'
@ -49,11 +51,10 @@ export const Header = (props: Props) => {
const toggleFixed = () => setFixed(!fixed())
// effects
createEffect(() => {
if (fixed() || getModal()) {
document.body.classList.add('fixed')
} else {
document.body.classList.remove('fixed')
}
const isFixed = fixed() || (getModal() && getModal() !== 'share');
document.body.classList.toggle('fixed', isFixed);
document.body.classList.toggle(styles.fixed, isFixed);
}, [fixed(), getModal()])
// derived
@ -71,8 +72,6 @@ export const Header = (props: Props) => {
onMount(() => {
let scrollTop = window.scrollY
// window.console.log(props.title)
const handleScroll = () => {
setIsScrollingBottom(window.scrollY > scrollTop)
setIsScrolled(window.scrollY > 0)
@ -98,7 +97,43 @@ export const Header = (props: Props) => {
<Modal name="auth">
<AuthModal />
</Modal>
<div class="wide-container">
<div class={clsx(styles.mainHeaderInner, 'wide-container')}>
<Popup name="share" class={clsx(styles.popupShare, stylesPopup.popupShare)}>
<ul class="nodash">
<li>
<a href="#">
<Icon name="vk-white" class={stylesPopup.icon}/>
VK
</a>
</li>
<li>
<a href="#">
<Icon name="facebook-white" class={stylesPopup.icon}/>
Facebook
</a>
</li>
<li>
<a href="#">
<Icon name="twitter-white" class={stylesPopup.icon}/>
Twitter
</a>
</li>
<li>
<a href="#">
<Icon name="telegram-white" class={stylesPopup.icon}/>
Telegram
</a>
</li>
<li>
<a href="#">
<Icon name="link-white" class={stylesPopup.icon}/>
{t('Copy link')}
</a>
</li>
</ul>
</Popup>
<nav class={clsx(styles.headerInner, 'row')} classList={{ fixed: fixed() }}>
<div class={clsx(styles.mainLogo, 'col-auto')}>
<a href={getPagePath(router, 'home')} onClick={handleClientRouteLinkClick}>
@ -162,7 +197,9 @@ export const Header = (props: Props) => {
</div>
<Show when={props.title}>
<div class={styles.articleControls}>
<Icon name="share-outline" class={styles.icon} />
<button onClick={() => {toggleModal('share')}}>
<Icon name="share-outline" class={styles.icon}/>
</button>
<a href="#comments">
<Icon name="comments-outline" class={styles.icon} />
</a>

View File

@ -0,0 +1,46 @@
.popup {
background: #fff;
border: 2px solid #000;
@include font-size(1.6rem);
padding: 2.4rem 2.4rem 2.4rem 1.6rem;
position: absolute;
z-index: 10;
ul {
margin-bottom: 0;
}
li {
margin-bottom: 1.6rem;
padding-left: 3.6rem;
position: relative;
&:last-child {
margin-bottom: 0;
}
}
a {
border: none;
}
img {
filter: invert(1);
max-height: 2rem;
max-width: 2rem;
}
.icon {
left: 1.5rem;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}
}
.popupShare {
right: 1em;
top: 4.5rem;
}

View File

@ -0,0 +1,33 @@
import { createEffect, createSignal, onMount, Show } from 'solid-js'
import style from './Popup.module.scss'
import { hideModal, useModalStore } from '../../stores/ui'
import {clsx} from 'clsx';
interface PopupProps {
name: string
children: any
class?: string
}
export const Popup = (props: PopupProps) => {
const { getModal } = useModalStore()
onMount(() => {
window.addEventListener('keydown', (e: KeyboardEvent) => {
if (e.key === 'Escape') hideModal()
})
})
const [visible, setVisible] = createSignal(false)
createEffect(() => {
setVisible(getModal() === props.name)
})
return (
<Show when={visible()}>
<div class={clsx(style.popup, props.class)}>
{props.children}
</div>
</Show>
)
}

View File

@ -20,6 +20,7 @@
"Comments": "Комментарии",
"Communities": "Сообщества",
"Create account": "Создать аккаунт",
"Copy link": "Скопировать ссылку",
"Delete": "Удалить",
"Discours": "Дискурс",
"Discours is an intellectual environment, a web space and tools that allows authors to collaborate with readers and come together to co-create publications and media projects": "Дискурс — это интеллектуальная среда, веб-пространство и инструменты, которые позволяют авторам сотрудничать с читателями и объединяться для совместного создания публикаций и медиапроектов",

View File

@ -19,8 +19,9 @@ const modal = atom<ModalType>(null)
const warnings = atom<Warning[]>([])
export const showModal = (modalType: ModalType) => modal.set(modalType)
export const hideModal = () => modal.set(null)
export const toggleModal = (modalType) => modal.get() ? hideModal() : showModal(modalType)
export const clearWarns = () => warnings.set([])
export const warn = (warning: Warning) => warnings.set([...warnings.get(), warning])

View File

@ -534,6 +534,7 @@ astro-island {
.main-content {
flex: 1 100%;
min-height: 300px;
padding-top: 100px;
position: relative;
transition: all 1s ease;