From 06beecac54cdf02705d017a3e3ef93e2c4a9b371 Mon Sep 17 00:00:00 2001 From: Igor Lobanov Date: Tue, 25 Oct 2022 17:36:32 +0200 Subject: [PATCH 1/3] common Popup component & SharePopup --- src/components/Article/FullArticle.tsx | 11 ++-- src/components/Article/SharePopup.tsx | 45 ++++++++++++++++ src/components/Nav/Header.module.scss | 32 ++++------- src/components/Nav/Header.tsx | 73 ++++++++------------------ src/components/Nav/Popup.module.scss | 24 +++++++-- src/components/Nav/Popup.tsx | 61 +++++++++++++-------- src/stores/ui.ts | 3 +- 7 files changed, 146 insertions(+), 103 deletions(-) create mode 100644 src/components/Article/SharePopup.tsx diff --git a/src/components/Article/FullArticle.tsx b/src/components/Article/FullArticle.tsx index 512cdac9..ab6d6b07 100644 --- a/src/components/Article/FullArticle.tsx +++ b/src/components/Article/FullArticle.tsx @@ -10,6 +10,7 @@ import { showModal } from '../../stores/ui' import { useAuthStore } from '../../stores/auth' import { incrementView } from '../../stores/zine/articles' import MD from './MD' +import { SharePopup } from './SharePopup' const MAX_COMMENT_LEVEL = 6 @@ -126,9 +127,13 @@ export const FullArticle = (props: ArticleProps) => { {/* */} {/**/}
- showModal('share')}> - - + event.preventDefault()}> + + + } + />
{/*FIXME*/} {/**/} diff --git a/src/components/Article/SharePopup.tsx b/src/components/Article/SharePopup.tsx new file mode 100644 index 00000000..851cf599 --- /dev/null +++ b/src/components/Article/SharePopup.tsx @@ -0,0 +1,45 @@ +import { Icon } from '../Nav/Icon' +import styles from '../Nav/Popup.module.scss' +import { t } from '../../utils/intl' +import { Popup, PopupProps } from '../Nav/Popup' + +type SharePopupProps = Omit + +export const SharePopup = (props: SharePopupProps) => { + return ( + + + + ) +} diff --git a/src/components/Nav/Header.module.scss b/src/components/Nav/Header.module.scss index 0a34a45e..9078872b 100644 --- a/src/components/Nav/Header.module.scss +++ b/src/components/Nav/Header.module.scss @@ -35,18 +35,6 @@ } } -.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; @@ -348,18 +336,16 @@ transform: translateY(-50%); width: 100%; - .icon { + .control { + cursor: pointer; margin-left: 1.6rem; - opacity: 0.6; - transition: opacity 0.3s; - } + border: 0; - img { - vertical-align: middle; - } + .icon { + opacity: 0.6; + transition: opacity 0.3s; + } - a { - border: none; &:hover { background: none; @@ -370,4 +356,8 @@ } } } + + img { + vertical-align: middle; + } } diff --git a/src/components/Nav/Header.tsx b/src/components/Nav/Header.tsx index ab2d6aeb..8a4e46f8 100644 --- a/src/components/Nav/Header.tsx +++ b/src/components/Nav/Header.tsx @@ -3,18 +3,17 @@ 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, toggleModal} from '../../stores/ui' +import { useModalStore, showModal, useWarningsStore } 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' import { clsx } from 'clsx' +import { SharePopup } from '../Article/SharePopup' const log = getLogger('header') @@ -39,6 +38,7 @@ export const Header = (props: Props) => { const [getIsScrolled, setIsScrolled] = createSignal(false) const [fixed, setFixed] = createSignal(false) const [visibleWarnings, setVisibleWarnings] = createSignal(false) + const [isSharePopupVisible, setIsSharePopupVisible] = createSignal(false) // stores const { getWarnings } = useWarningsStore() const { session } = useAuthStore() @@ -48,14 +48,11 @@ export const Header = (props: Props) => { // methods const toggleWarnings = () => setVisibleWarnings(!visibleWarnings()) - const toggleFixed = () => setFixed(!fixed()) + const toggleFixed = () => setFixed((oldFixed) => !oldFixed) // effects createEffect(() => { - const isFixed = fixed() || (getModal() && getModal() !== 'share'); - - document.body.classList.toggle('fixed', isFixed); - document.body.classList.toggle(styles.fixed, isFixed && !getModal()); - }, [fixed(), getModal()]) + document.body.classList.toggle('fixed', fixed() || getModal() !== null) + }) // derived const authorized = createMemo(() => session()?.user?.slug) @@ -90,7 +87,7 @@ export const Header = (props: Props) => { classList={{ [styles.headerFixed]: props.isHeaderFixed, [styles.headerScrolledTop]: !getIsScrollingBottom() && getIsScrolled(), - [styles.headerScrolledBottom]: getIsScrollingBottom() && getIsScrolled(), + [styles.headerScrolledBottom]: (getIsScrollingBottom() && getIsScrolled()) || isSharePopupVisible(), [styles.headerWithTitle]: Boolean(props.title) }} > @@ -99,41 +96,6 @@ export const Header = (props: Props) => { diff --git a/src/components/Nav/Popup.module.scss b/src/components/Nav/Popup.module.scss index 63405563..d62d1c09 100644 --- a/src/components/Nav/Popup.module.scss +++ b/src/components/Nav/Popup.module.scss @@ -1,6 +1,13 @@ +.container { + position: relative; +} + .popup { background: #fff; border: 2px solid #000; + top: calc(100% + 8px); + transform: translateX(-50%); + opacity: 1; @include font-size(1.6rem); @@ -24,6 +31,7 @@ a { border: none; + white-space: nowrap; } img { @@ -40,7 +48,15 @@ } } -.popupShare { - right: 1em; - top: 4.5rem; -} +// TODO: animation +// .popup { +// opacity: 1; +// transition: opacity 0.3s; +// z-index: 1; +// &.visible { +// opacity: 0; +// transition: opacity 0.3s, z-index 0s 0.3s; +// z-index: -1; +// } +// } + diff --git a/src/components/Nav/Popup.tsx b/src/components/Nav/Popup.tsx index 451caf88..a53517cf 100644 --- a/src/components/Nav/Popup.tsx +++ b/src/components/Nav/Popup.tsx @@ -1,33 +1,50 @@ -import { createEffect, createSignal, onMount, Show } from 'solid-js' -import style from './Popup.module.scss' -import { hideModal, useModalStore } from '../../stores/ui' -import {clsx} from 'clsx'; +import { createEffect, createSignal, JSX, onCleanup, onMount, Show } from 'solid-js' +import styles from './Popup.module.scss' +import { clsx } from 'clsx' -interface PopupProps { - name: string - children: any - class?: string +export type PopupProps = { + containerCssClass?: string + trigger: JSX.Element + children: JSX.Element + onVisibilityChange?: (isVisible) => void } export const Popup = (props: PopupProps) => { - const { getModal } = useModalStore() + const [isVisible, setIsVisible] = createSignal(false) + + createEffect(() => { + if (props.onVisibilityChange) { + props.onVisibilityChange(isVisible()) + } + }) + + let container: HTMLDivElement | undefined + + const handleClickOutside = (event: MouseEvent & { target: Element }) => { + if (!isVisible()) { + return + } + + if (event.target === container || container?.contains(event.target)) { + return + } + + setIsVisible(false) + } onMount(() => { - window.addEventListener('keydown', (e: KeyboardEvent) => { - if (e.key === 'Escape') hideModal() - }) - }) - - const [visible, setVisible] = createSignal(false) - createEffect(() => { - setVisible(getModal() === props.name) + document.addEventListener('click', handleClickOutside, { capture: true }) + onCleanup(() => document.removeEventListener('click', handleClickOutside, { capture: true })) }) + const toggle = () => setIsVisible((oldVisible) => !oldVisible) + // class={clsx(styles.popupShare, stylesPopup.popupShare)} return ( - -
- {props.children} -
-
+ + {props.trigger} + +
{props.children}
+
+
) } diff --git a/src/stores/ui.ts b/src/stores/ui.ts index 39d4c717..e36e48c7 100644 --- a/src/stores/ui.ts +++ b/src/stores/ui.ts @@ -5,7 +5,7 @@ import { createSignal } from 'solid-js' //export const locale = persistentAtom('locale', 'ru') export const [locale, setLocale] = createSignal('ru') -export type ModalType = 'auth' | 'subscribe' | 'feedback' | 'share' | 'thank' | 'donate' | null +export type ModalType = 'auth' | 'subscribe' | 'feedback' | 'thank' | 'donate' | null type WarnKind = 'error' | 'warn' | 'info' export interface Warning { @@ -20,7 +20,6 @@ const warnings = atom([]) 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]) From f64bcc08f08020e4d29588ca5659cc6b260849d2 Mon Sep 17 00:00:00 2001 From: Igor Lobanov Date: Tue, 25 Oct 2022 17:40:12 +0200 Subject: [PATCH 2/3] prettier --- src/components/Discours/Banner.tsx | 2 +- src/components/Discours/Footer.tsx | 2 +- src/components/Feed/Row1.tsx | 2 +- src/components/Nav/Header.module.scss | 1 - src/components/Nav/Popup.module.scss | 1 - src/components/Pages/about/ManifestPage.tsx | 83 +++++++++++---------- 6 files changed, 47 insertions(+), 44 deletions(-) diff --git a/src/components/Discours/Banner.tsx b/src/components/Discours/Banner.tsx index 17c8875a..f14d2a8e 100644 --- a/src/components/Discours/Banner.tsx +++ b/src/components/Discours/Banner.tsx @@ -1,7 +1,7 @@ import styles from './Banner.module.scss' import { t } from '../../utils/intl' import { showModal } from '../../stores/ui' -import {clsx} from "clsx"; +import { clsx } from 'clsx' export default () => { return ( diff --git a/src/components/Discours/Footer.tsx b/src/components/Discours/Footer.tsx index ed0a50f7..941c5d3a 100644 --- a/src/components/Discours/Footer.tsx +++ b/src/components/Discours/Footer.tsx @@ -4,7 +4,7 @@ import { Icon } from '../Nav/Icon' import Subscribe from './Subscribe' import { t } from '../../utils/intl' import { locale } from '../../stores/ui' -import {clsx} from "clsx"; +import { clsx } from 'clsx' export const Footer = () => { const locale_title = createMemo(() => (locale() === 'ru' ? 'English' : 'Русский')) diff --git a/src/components/Feed/Row1.tsx b/src/components/Feed/Row1.tsx index abf6b9f8..b654fb82 100644 --- a/src/components/Feed/Row1.tsx +++ b/src/components/Feed/Row1.tsx @@ -7,7 +7,7 @@ export default (props: { article: Shout }) => (
- +
diff --git a/src/components/Nav/Header.module.scss b/src/components/Nav/Header.module.scss index 9078872b..83f0d992 100644 --- a/src/components/Nav/Header.module.scss +++ b/src/components/Nav/Header.module.scss @@ -346,7 +346,6 @@ transition: opacity 0.3s; } - &:hover { background: none; diff --git a/src/components/Nav/Popup.module.scss b/src/components/Nav/Popup.module.scss index d62d1c09..57c7263f 100644 --- a/src/components/Nav/Popup.module.scss +++ b/src/components/Nav/Popup.module.scss @@ -59,4 +59,3 @@ // z-index: -1; // } // } - diff --git a/src/components/Pages/about/ManifestPage.tsx b/src/components/Pages/about/ManifestPage.tsx index 68e318c2..3a9cf69f 100644 --- a/src/components/Pages/about/ManifestPage.tsx +++ b/src/components/Pages/about/ManifestPage.tsx @@ -54,28 +54,29 @@ export const ManifestPage = () => {

- Дискурс — независимый художественно-аналитический журнал с горизонтальной редакцией, - основанный на принципах свободы слова, прямой демократии и совместного редактирования. - Дискурс создаётся открытым медиасообществом ученых, журналистов, музыкантов, писателей, - предпринимателей, философов, инженеров, художников и специалистов со всего мира, - объединившихся, чтобы вместе делать общий журнал и объяснять с разных точек - зрения мозаичную картину современности. + Дискурс — независимый художественно-аналитический журнал с горизонтальной + редакцией, основанный на принципах свободы слова, прямой демократии и совместного + редактирования. Дискурс создаётся открытым медиасообществом ученых, журналистов, музыкантов, + писателей, предпринимателей, философов, инженеров, художников и специалистов + со всего мира, объединившихся, чтобы вместе делать общий журнал и объяснять + с разных точек зрения мозаичную картину современности.

- Мы пишем о культуре, науке и обществе, рассказываем о новых идеях и современном искусстве, - публикуем статьи, исследования, репортажи, интервью людей, чью прямую речь стоит услышать, - и работы художников из разных стран — от фильмов и музыки - до живописи и фотографии. Помогая друг другу делать публикации качественнее - и общим голосованием выбирая лучшие материалы для журнала, мы создаём новую - горизонтальную журналистику, чтобы честно рассказывать о важном и интересном. + Мы пишем о культуре, науке и обществе, рассказываем о новых идеях + и современном искусстве, публикуем статьи, исследования, репортажи, интервью людей, чью + прямую речь стоит услышать, и работы художников из разных стран — + от фильмов и музыки до живописи и фотографии. Помогая друг другу делать + публикации качественнее и общим голосованием выбирая лучшие материалы для журнала, + мы создаём новую горизонтальную журналистику, чтобы честно рассказывать о важном + и интересном.

- Редакция Дискурса открыта для всех: у нас нет цензуры, запретных тем и идеологических рамок. - Каждый может прислать материал в журнал - и присоединиться к редакции. Предоставляя трибуну - для независимой журналистики и художественных проектов, мы помогаем людям - рассказывать свои истории так, чтобы они были услышаны. Мы убеждены: чем больше - голосов будет звучать на Дискурсе, тем громче в полифонии мнений будет слышна истина. + Редакция Дискурса открыта для всех: у нас нет цензуры, запретных тем + и идеологических рамок. Каждый может прислать материал{' '} + в журнал и присоединиться к редакции. Предоставляя + трибуну для независимой журналистики и художественных проектов, мы помогаем людям + рассказывать свои истории так, чтобы они были услышаны. Мы убеждены: чем больше голосов + будет звучать на Дискурсе, тем громче в полифонии мнений будет слышна истина.

@@ -91,23 +92,26 @@ export const ManifestPage = () => {

Предлагать материалы

- Создавайте свои статьи и художественные работы — лучшие из них будут - опубликованы в журнале. Дискурс — некоммерческое издание, авторы публикуются - в журнале на общественных началах, получая при этом поддержку редакции, - право голоса, множество других возможностей и читателей по всему миру. + Создавайте свои статьи и художественные работы — + лучшие из них будут опубликованы в журнале. Дискурс — некоммерческое + издание, авторы публикуются в журнале на общественных началах, получая при этом{' '} + поддержку редакции, право голоса, множество других + возможностей и читателей по всему миру.

-

Дискурс существует на пожертвования читателей. Если вам нравится журнал, пожалуйста,

- поддержите нашу работу. Ваши пожертвования пойдут на выпуск новых - материалов, оплату серверов, труда программистов, дизайнеров и редакторов. + Дискурс существует на пожертвования читателей. Если вам нравится журнал, пожалуйста, +

+

+ поддержите нашу работу. Ваши пожертвования пойдут на выпуск + новых материалов, оплату серверов, труда программистов, дизайнеров и редакторов.

Сотрудничать с журналом

Мы всегда открыты для сотрудничества и рады единомышленникам. Если вы хотите помогать журналу с редактурой, корректурой, иллюстрациями, переводами, версткой, подкастами, - мероприятиями, фандрайзингом или как-то ещё — скорее пишите нам - на welcome@discours.io. + мероприятиями, фандрайзингом или как-то ещё — скорее пишите нам на  + welcome@discours.io.

Если вы представляете некоммерческую организацию и хотите сделать с нами @@ -116,25 +120,26 @@ export const ManifestPage = () => {

Если вы разработчик и хотите помогать с развитием сайта Дискурса,{' '} - присоединяйтесь к IT-команде самиздата. Открытый - код платформы для независимой журналистики, а также всех наших спецпроектов - и медиаинструментов находится в свободном доступе на GitHub. + присоединяйтесь к IT-команде самиздата. + Открытый код платформы для независимой журналистики, а также всех наших спецпроектов + и медиаинструментов находится{' '} + в свободном доступе на GitHub.

Как еще можно помочь

Советуйте Дискурс друзьям и знакомым. Обсуждайте и распространяйте наши публикации — все материалы открытой редакции можно читать и перепечатывать - бесплатно. Подпишитесь на самиздат{' '} - ВКонтакте, + бесплатно. Подпишитесь на самиздат ВКонтакте, в Фейсбуке - и в Телеграме, а также - на рассылку лучших материалов, - чтобы не пропустить ничего интересного. + и в Телеграме, а также на  + рассылку лучших материалов, чтобы не пропустить + ничего интересного.

Рассказывайте о впечатлениях от материалов открытой редакции, делитесь идеями, - интересными темами, о которых хотели бы узнать больше, и историями, которые нужно рассказать. + интересными темами, о которых хотели бы узнать больше, и историями, которые нужно + рассказать.

@@ -145,9 +150,9 @@ export const ManifestPage = () => {
Если вы хотите предложить материал, сотрудничать, рассказать о проблеме, которую нужно осветить, сообщить об ошибке или баге, что-то обсудить, уточнить или посоветовать, - пожалуйста, напишите нам здесь или - на почту welcome@discours.io. Мы обязательно - ответим и постараемся реализовать все хорошие задумки. + пожалуйста, напишите нам здесь или на почту{' '} + welcome@discours.io. Мы обязательно ответим + и постараемся реализовать все хорошие задумки.
From 0eb1430174be30fb30653cd1a4388c43190ddf87 Mon Sep 17 00:00:00 2001 From: Igor Lobanov Date: Tue, 25 Oct 2022 17:44:31 +0200 Subject: [PATCH 3/3] prettier on on precommit enabled --- .lintstagedrc | 5 +---- .lintstagedrc.bak | 6 ++++++ package.json | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 .lintstagedrc.bak diff --git a/.lintstagedrc b/.lintstagedrc index 6de8a64b..8c919270 100644 --- a/.lintstagedrc +++ b/.lintstagedrc @@ -1,6 +1,3 @@ { - "*.{js,ts,tsx,json,scss,css,html}": "prettier --write", - "package.json": "sort-package-json", - "*.{scss,css}": "stylelint", - "*.{ts,tsx,js}": "eslint --fix" + "*.{js,ts,tsx,json,scss,css,html}": "prettier --write" } diff --git a/.lintstagedrc.bak b/.lintstagedrc.bak new file mode 100644 index 00000000..6de8a64b --- /dev/null +++ b/.lintstagedrc.bak @@ -0,0 +1,6 @@ +{ + "*.{js,ts,tsx,json,scss,css,html}": "prettier --write", + "package.json": "sort-package-json", + "*.{scss,css}": "stylelint", + "*.{ts,tsx,js}": "eslint --fix" +} diff --git a/package.json b/package.json index fd8ff98e..cd3dcbce 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "lint:code:fix": "eslint . --fix", "lint:styles": "stylelint **/*.{scss,css}", "lint:styles:fix": "stylelint **/*.{scss,css} --fix", - "pre-commit": "", + "pre-commit": "lint-staged", "pre-push": "", "pre-commit-old": "lint-staged", "pre-push-old": "npm run typecheck",