diff --git a/src/components/Article/FullArticle.tsx b/src/components/Article/FullArticle.tsx index cbf023f2..247248af 100644 --- a/src/components/Article/FullArticle.tsx +++ b/src/components/Article/FullArticle.tsx @@ -6,7 +6,7 @@ import { createMemo, For, Match, onMount, Show, Switch } from 'solid-js' import type { Author, Shout } from '../../graphql/types.gen' import { t } from '../../utils/intl' import MD from './MD' -import { SharePopup } from './SharePopup' +import { getShareUrl, SharePopup } from './SharePopup' import { getDescription } from '../../utils/meta' import stylesHeader from '../Nav/Header.module.scss' import styles from '../../styles/Article.module.scss' @@ -174,7 +174,6 @@ export const FullArticle = (props: ArticleProps) => { title={props.article.title} description={getDescription(props.article.body)} imageUrl={props.article.cover} - shareUrl={location.href} containerCssClass={stylesHeader.control} trigger={} /> diff --git a/src/components/Article/SharePopup.tsx b/src/components/Article/SharePopup.tsx index 7b6f6a81..155a6dbe 100644 --- a/src/components/Article/SharePopup.tsx +++ b/src/components/Article/SharePopup.tsx @@ -1,7 +1,6 @@ import { Icon } from '../_shared/Icon' import { t } from '../../utils/intl' import { createSocialShare, TWITTER, VK, FACEBOOK, TELEGRAM } from '@solid-primitives/share' - import styles from '../_shared/Popup/Popup.module.scss' import type { PopupProps } from '../_shared/Popup' import { Popup } from '../_shared/Popup' @@ -13,6 +12,12 @@ type SharePopupProps = { description: string } & Omit +export const getShareUrl = (params: { pathname?: string } = {}) => { + if (typeof location === 'undefined') return '' + const pathname = params.pathname ?? location.pathname + return location.origin + pathname +} + export const SharePopup = (props: SharePopupProps) => { const [share] = createSocialShare(() => ({ title: props.title, @@ -20,7 +25,7 @@ export const SharePopup = (props: SharePopupProps) => { description: props.description })) const copyLink = async () => { - await navigator.clipboard.writeText(window.location.href) + await navigator.clipboard.writeText(props.shareUrl) } return ( diff --git a/src/components/Feed/Card.tsx b/src/components/Feed/Card.tsx index 76745344..44d9d88a 100644 --- a/src/components/Feed/Card.tsx +++ b/src/components/Feed/Card.tsx @@ -9,7 +9,7 @@ import { locale } from '../../stores/ui' import { clsx } from 'clsx' import { CardTopic } from './CardTopic' import { RatingControl } from '../Article/RatingControl' -import { SharePopup } from '../Article/SharePopup' +import { getShareUrl, SharePopup } from '../Article/SharePopup' import stylesHeader from '../Nav/Header.module.scss' import { getDescription } from '../../utils/meta' @@ -73,12 +73,6 @@ export const ArticleCard = (props: ArticleCardProps) => { const { cover, layout, slug, authors, stat } = props.article - const [url, setUrl] = createSignal(null) - onMount(() => { - const composeUrl = new URL(location.href) - setUrl(composeUrl.origin) - }) - return ( { title={props.article['title']} description={getDescription(props.article['body'])} imageUrl={props.article['cover']} - shareUrl={`${url()}/${slug}`} + shareUrl={getShareUrl({ pathname: `/${slug}` })} trigger={ diff --git a/src/components/Feed/Sidebar.module.scss b/src/components/Feed/Sidebar.module.scss index 0e1dc67c..ca81ac8d 100644 --- a/src/components/Feed/Sidebar.module.scss +++ b/src/components/Feed/Sidebar.module.scss @@ -1,3 +1,11 @@ +.sidebar { + max-height: calc(100vh - 120px); + overflow: auto; + padding-right: 1rem; + position: sticky; + top: 120px; +} + .counter { align-items: center; align-self: flex-start; @@ -29,6 +37,7 @@ .settings { display: flex; justify-content: space-between; + margin-bottom: 2em; } a { diff --git a/src/components/Feed/Sidebar.tsx b/src/components/Feed/Sidebar.tsx index cec0275c..8d50df10 100644 --- a/src/components/Feed/Sidebar.tsx +++ b/src/components/Feed/Sidebar.tsx @@ -29,7 +29,7 @@ export const FeedSidebar = (props: FeedSidebarProps) => { } return ( - <> + @@ -78,6 +78,7 @@ export const FeedSidebar = (props: FeedSidebarProps) => { уведомления + 283 @@ -119,6 +120,6 @@ export const FeedSidebar = (props: FeedSidebarProps) => { {t('Feed settings')} - > + ) } diff --git a/src/components/Nav/Header.module.scss b/src/components/Nav/Header.module.scss index 8867d332..b4dab49b 100644 --- a/src/components/Nav/Header.module.scss +++ b/src/components/Nav/Header.module.scss @@ -117,6 +117,10 @@ &:hover { background: none; + + img { + filter: none; + } } } } diff --git a/src/components/Nav/Header.tsx b/src/components/Nav/Header.tsx index b38f1474..0f2877d3 100644 --- a/src/components/Nav/Header.tsx +++ b/src/components/Nav/Header.tsx @@ -9,7 +9,7 @@ import styles from './Header.module.scss' import { getPagePath } from '@nanostores/router' import { clsx } from 'clsx' import { HeaderAuth } from './HeaderAuth' -import { SharePopup } from '../Article/SharePopup' +import { getShareUrl, SharePopup } from '../Article/SharePopup' import { getDescription } from '../../utils/meta' const resources: { name: string; route: keyof Routes }[] = [ @@ -128,7 +128,7 @@ export const Header = (props: Props) => { { setIsSharePopupVisible(isVisible) diff --git a/src/components/Views/Feed.module.scss b/src/components/Views/Feed.module.scss index 3806b2e8..f7d77325 100644 --- a/src/components/Views/Feed.module.scss +++ b/src/components/Views/Feed.module.scss @@ -14,16 +14,21 @@ } ul { - margin-bottom: 3rem; + margin: 0 0 3rem; } li { display: flex; justify-content: space-between; margin: 0 0 1rem; + white-space: nowrap; + width: 100%; a { margin-right: 0.5em; + position: relative; + overflow: hidden; + text-overflow: ellipsis; } } diff --git a/src/components/Views/Feed.tsx b/src/components/Views/Feed.tsx index 9b87b85e..d804c010 100644 --- a/src/components/Views/Feed.tsx +++ b/src/components/Views/Feed.tsx @@ -78,115 +78,118 @@ export const FeedView = () => { return ( <> - - + + - - - - - {t('My feed')} + + + + + + {t('My feed')} + + + + {t('Most read')} + + + {t('Top rated')} + + + {t('Most commented')} - - - {t('Most read')} - - - {t('Top rated')} - - - {t('Most commented')} - - - - 0}> - - {(article) => } - - - - {t('Popular authors')} - - {t('All authors')} - - - - - - - {(author) => ( - - - - )} - - - {(article) => } - - - + 0}> + + {(article) => } + - + + - - - - - Как устроен Дискурс - - - Как создать хороший текст - - - Правила конструктивных дискуссий - - - Принципы сообщества - - - - + 0}> + + {t('Topics')} + + {(topic) => ( + + {topic.title}{' '} + + )} + + + + + + + + + Как устроен Дискурс + + + Как создать хороший текст + + + Правила конструктивных дискуссий + + + Принципы сообщества + + + + + + diff --git a/src/components/_shared/CommentEditor/CommentEditor.tsx b/src/components/_shared/CommentEditor/CommentEditor.tsx index 74cb9ad9..de857fc1 100644 --- a/src/components/_shared/CommentEditor/CommentEditor.tsx +++ b/src/components/_shared/CommentEditor/CommentEditor.tsx @@ -2,7 +2,7 @@ import styles from './styles/CommentEditor.module.scss' import './styles/ProseMirrorOverrides.scss' import { clsx } from 'clsx' import Button from '../Button' -import { createEffect, createMemo, onMount } from 'solid-js' +import { createEffect, onMount, Show } from 'solid-js' import { t } from '../../../utils/intl' //ProseMirror deps import { schema } from './schema' @@ -16,6 +16,8 @@ import { baseKeymap } from 'prosemirror-commands' import { customKeymap } from '../../EditorNew/prosemirror/plugins/customKeymap' import { placeholder } from '../../EditorNew/prosemirror/plugins/placeholder' import { undo, redo, history } from 'prosemirror-history' +import { useSession } from '../../../context/session' +import { showModal } from '../../../stores/ui' type Props = { initialValue: string @@ -31,6 +33,7 @@ const getHtml = (state: EditorState) => { } const CommentEditor = (props: Props) => { + const { session } = useSession() const editorElRef: { current: HTMLDivElement } = { current: null } const menuElRef: { current: HTMLDivElement } = { current: null } const editorViewRef: { current: EditorView } = { current: null } @@ -65,7 +68,9 @@ const CommentEditor = (props: Props) => { } createEffect(() => { - if (props.clear) clearEditor() + if (props.clear) { + clearEditor() + } }) return ( @@ -78,12 +83,28 @@ const CommentEditor = (props: Props) => { (menuElRef.current = el)} /> - - + + + + {'"Cmd-Z": Undo, "Cmd-Y": Redo'} + + + {t('To write a comment, you must')} + { + evt.preventDefault() + showModal('auth') + }} + > + {t('sign up or sign in')} + + + > ) } diff --git a/src/components/_shared/CommentEditor/styles/CommentEditor.module.scss b/src/components/_shared/CommentEditor/styles/CommentEditor.module.scss index ea33f29d..0b1f8353 100644 --- a/src/components/_shared/CommentEditor/styles/CommentEditor.module.scss +++ b/src/components/_shared/CommentEditor/styles/CommentEditor.module.scss @@ -30,3 +30,21 @@ margin: 12px 0; font-style: italic; } + +.signInMessage { + background: #f1f2f3; + border-radius: 8px; + padding: 16px; + text-align: center; + font-size: 20px; + + .link { + color: #2638d9; + cursor: pointer; + transition: 0.3s ease-in-out; + + &:hover { + text-decoration: unset; + } + } +} diff --git a/src/styles/Feed.scss b/src/styles/Feed.scss index 93ce4616..fb5f923c 100644 --- a/src/styles/Feed.scss +++ b/src/styles/Feed.scss @@ -57,8 +57,8 @@ .feed-filter { display: flex; + flex-wrap: wrap; @include font-size(1.7rem); - font-weight: 500; list-style: none; margin: 0 0 1.6rem; @@ -66,7 +66,7 @@ li { border-bottom: 4px solid transparent; - margin: 0 1.4em 1em 0; + margin: 0 1.4em 0.5em 0; &:last-child { margin-right: 0; diff --git a/src/styles/app.scss b/src/styles/app.scss index 3ae381c7..c87ca4bd 100644 --- a/src/styles/app.scss +++ b/src/styles/app.scss @@ -691,11 +691,11 @@ astro-island { .left-col { height: 100%; padding-right: 2rem; - position: absolute; right: 100%; top: 0; @include media-breakpoint-up(md) { + position: absolute; width: 161px; } diff --git a/src/utils/meta.ts b/src/utils/meta.ts index e6ddd1ae..a411f676 100644 --- a/src/utils/meta.ts +++ b/src/utils/meta.ts @@ -1,7 +1,9 @@ -export const getDescription = (body: string) => { - if (!body) return null +export const getDescription = (body: string): string => { + if (!body) { + return '' + } const descriptionWordsArray = body - .slice(0, 150) + .slice(0, 150) // meta description is roughly 155 characters long .replaceAll(/<[^>]*>/g, '') .split(' ') return descriptionWordsArray.splice(0, descriptionWordsArray.length - 1).join(' ') + '...'
diff --git a/src/components/_shared/CommentEditor/CommentEditor.tsx b/src/components/_shared/CommentEditor/CommentEditor.tsx index 74cb9ad9..de857fc1 100644 --- a/src/components/_shared/CommentEditor/CommentEditor.tsx +++ b/src/components/_shared/CommentEditor/CommentEditor.tsx @@ -2,7 +2,7 @@ import styles from './styles/CommentEditor.module.scss' import './styles/ProseMirrorOverrides.scss' import { clsx } from 'clsx' import Button from '../Button' -import { createEffect, createMemo, onMount } from 'solid-js' +import { createEffect, onMount, Show } from 'solid-js' import { t } from '../../../utils/intl' //ProseMirror deps import { schema } from './schema' @@ -16,6 +16,8 @@ import { baseKeymap } from 'prosemirror-commands' import { customKeymap } from '../../EditorNew/prosemirror/plugins/customKeymap' import { placeholder } from '../../EditorNew/prosemirror/plugins/placeholder' import { undo, redo, history } from 'prosemirror-history' +import { useSession } from '../../../context/session' +import { showModal } from '../../../stores/ui' type Props = { initialValue: string @@ -31,6 +33,7 @@ const getHtml = (state: EditorState) => { } const CommentEditor = (props: Props) => { + const { session } = useSession() const editorElRef: { current: HTMLDivElement } = { current: null } const menuElRef: { current: HTMLDivElement } = { current: null } const editorViewRef: { current: EditorView } = { current: null } @@ -65,7 +68,9 @@ const CommentEditor = (props: Props) => { } createEffect(() => { - if (props.clear) clearEditor() + if (props.clear) { + clearEditor() + } }) return ( @@ -78,12 +83,28 @@ const CommentEditor = (props: Props) => { (menuElRef.current = el)} /> - - + + + + {'"Cmd-Z": Undo, "Cmd-Y": Redo'} + + + {t('To write a comment, you must')} + { + evt.preventDefault() + showModal('auth') + }} + > + {t('sign up or sign in')} + + + > ) } diff --git a/src/components/_shared/CommentEditor/styles/CommentEditor.module.scss b/src/components/_shared/CommentEditor/styles/CommentEditor.module.scss index ea33f29d..0b1f8353 100644 --- a/src/components/_shared/CommentEditor/styles/CommentEditor.module.scss +++ b/src/components/_shared/CommentEditor/styles/CommentEditor.module.scss @@ -30,3 +30,21 @@ margin: 12px 0; font-style: italic; } + +.signInMessage { + background: #f1f2f3; + border-radius: 8px; + padding: 16px; + text-align: center; + font-size: 20px; + + .link { + color: #2638d9; + cursor: pointer; + transition: 0.3s ease-in-out; + + &:hover { + text-decoration: unset; + } + } +} diff --git a/src/styles/Feed.scss b/src/styles/Feed.scss index 93ce4616..fb5f923c 100644 --- a/src/styles/Feed.scss +++ b/src/styles/Feed.scss @@ -57,8 +57,8 @@ .feed-filter { display: flex; + flex-wrap: wrap; @include font-size(1.7rem); - font-weight: 500; list-style: none; margin: 0 0 1.6rem; @@ -66,7 +66,7 @@ li { border-bottom: 4px solid transparent; - margin: 0 1.4em 1em 0; + margin: 0 1.4em 0.5em 0; &:last-child { margin-right: 0; diff --git a/src/styles/app.scss b/src/styles/app.scss index 3ae381c7..c87ca4bd 100644 --- a/src/styles/app.scss +++ b/src/styles/app.scss @@ -691,11 +691,11 @@ astro-island { .left-col { height: 100%; padding-right: 2rem; - position: absolute; right: 100%; top: 0; @include media-breakpoint-up(md) { + position: absolute; width: 161px; } diff --git a/src/utils/meta.ts b/src/utils/meta.ts index e6ddd1ae..a411f676 100644 --- a/src/utils/meta.ts +++ b/src/utils/meta.ts @@ -1,7 +1,9 @@ -export const getDescription = (body: string) => { - if (!body) return null +export const getDescription = (body: string): string => { + if (!body) { + return '' + } const descriptionWordsArray = body - .slice(0, 150) + .slice(0, 150) // meta description is roughly 155 characters long .replaceAll(/<[^>]*>/g, '') .split(' ') return descriptionWordsArray.splice(0, descriptionWordsArray.length - 1).join(' ') + '...'