Feature/header (#408)

New header
This commit is contained in:
kvakazyambra 2024-04-08 14:26:20 +03:00 committed by GitHub
parent c3495ed0b3
commit 6851c3af6a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 262 additions and 89 deletions

View File

@ -83,6 +83,7 @@
"Coming soon": "Coming soon",
"Comment successfully deleted": "Comment successfully deleted",
"Commentator": "Commentator",
"Commenting": "Commenting",
"Comments": "Comments",
"CommentsWithCount": "{count, plural, =0 {{count} comments} one {{count} comment} few {{count} comments} other {{count} comments}}",
"Communities": "Communities",

View File

@ -87,6 +87,7 @@
"Comment successfully deleted": "Комментарий успешно удален",
"Comment": "Комментировать",
"Commentator": "Комментатор",
"Commenting": "Комментирование",
"Comments": "Комментарии",
"CommentsWithCount": "{count, plural, =0 {{count} комментариев} one {{count} комментарий} few {{count} комментария} other {{count} комментариев}}",
"Communities": "Сообщества",

View File

@ -114,6 +114,11 @@
position: absolute;
right: 0;
}
.control {
align-items: center;
display: flex;
}
}
.mainNavigationWrapper {
@ -192,15 +197,8 @@
padding: divide($container-padding-x, 2) !important;
}
@include media-breakpoint-up(md) {
span,
button {
padding: 0 0.4rem;
}
}
:global(.view-switcher) {
margin: 0 -0.5rem;
margin: 0;
overflow: hidden;
padding: 0;
}
@ -299,9 +297,6 @@
.burgerContainer {
box-sizing: content-box;
display: inline-flex;
padding-left: 0;
// float: right;
@include media-breakpoint-up(sm) {
padding-left: divide($container-padding-x, 2);
@ -430,12 +425,15 @@
width: 100%;
@include media-breakpoint-up(xl) {
right: 2rem;
right: 9rem;
}
.control {
cursor: pointer;
border: 0;
cursor: pointer;
height: 3.2rem;
margin: 0 0.6rem;
width: 3.2rem;
&:hover {
background: none;
@ -451,11 +449,7 @@
}
.control + .control {
margin-left: 1.2rem;
@include media-breakpoint-up(sm) {
margin-left: 2rem;
}
margin: 0 0.6rem;
}
img {
@ -497,10 +491,15 @@
}
}
.settingsControlContainer {
margin-left: 1rem !important;
margin-right: 2rem !important;
}
.settingsControl {
border-radius: 100%;
padding: 0.8rem !important;
min-width: 4rem !important;
padding: 0.8rem !important;
&:hover {
background: var(--background-color-invert);
@ -516,12 +515,18 @@
align-items: center;
border-radius: 100%;
display: flex;
height: 2.4em;
height: 2.8rem;
justify-content: center;
margin-left: 0.3rem;
margin: 0 0.4rem;
position: relative;
transition: margin-left 0.3s;
width: 2.4em;
width: 2.8rem;
@include media-breakpoint-up(md) {
height: 3.2rem;
margin: 0 0.7rem;
width: 3.2rem;
}
@include media-breakpoint-down(sm) {
margin-left: 0.4rem !important;
@ -543,12 +548,13 @@
a:link {
border: none;
cursor: pointer;
height: auto;
height: 100%;
margin: 0;
padding: 0;
width: 100%;
&:hover {
background: none !important;
background: none;
.icon {
display: none;
@ -571,6 +577,20 @@
}
}
.userControlItemSearch {
margin: 0 1rem 0 2.2rem;
}
.userControlItemUserpic {
height: 3.2rem;
width: 3.2rem;
@include media-breakpoint-up(md) {
height: 4rem;
width: 4rem;
}
}
.userControlItemInbox,
.userControlItemSearch {
@include media-breakpoint-down(sm) {
@ -579,7 +599,16 @@
}
.userControlItemVerbose {
margin-left: 0.9em !important;
align-items: stretch;
display: flex;
height: 3.2rem;
margin-left: 1rem !important;
width: 3.2rem;
@include media-breakpoint-up(md) {
height: 4rem;
width: 4rem;
}
&:first-child {
margin-left: 0 !important;
@ -590,6 +619,7 @@
@include media-breakpoint-up(xl) {
background: none;
margin-left: 0.8rem !important;
}
.icon {
@ -611,10 +641,14 @@
}
@include media-breakpoint-up(xl) {
margin-left: 0.5em !important;
margin-right: 0.5em;
margin-left: 3rem !important;
margin-right: 0;
width: auto;
&:last-child {
margin-right: 0;
}
.icon {
display: none !important;
}
@ -629,6 +663,37 @@
}
}
a:link,
a:visited,
button {
align-items: center;
display: flex;
justify-content: center;
@include media-breakpoint-up(xl) {
border-radius: 2rem;
box-shadow: inset 0 0 0 2px #000;
padding: 0 2rem;
}
&:hover {
background-color: var(--link-hover-background);
&,
.textLabel {
color: #fff !important;
}
.icon {
display: none;
}
.iconHover {
display: block;
}
}
}
button {
margin: 0 !important;
}
@ -636,27 +701,6 @@
a::before {
display: none;
}
a:hover,
button:hover {
.icon {
display: none;
}
.iconHover {
display: block;
}
.textLabel {
color: var(--link-hover-color);
}
}
a:hover {
.textLabel {
background-color: var(--link-hover-background);
}
}
}
.subnavigation {
@ -746,3 +790,65 @@
position: relative;
top: 0.15em;
}
.editorPopup {
border: 1px solid rgb(0 0 0 / 15%) !important;
border-radius: 1.6rem;
line-height: 1.3;
min-width: 28rem;
padding: 1.6rem !important;
}
.editorModePopupOpener {
display: inline-block;
margin-right: 2rem;
position: relative;
text-align: right;
width: 9em;
}
.editorModePopupOpenerIcon {
height: 2rem;
left: 100%;
margin-left: 0.2em;
top: 0;
transform: rotate(90deg);
position: absolute;
width: 2rem;
}
.editorModesList {
li {
cursor: pointer;
margin-bottom: 1.6rem;
padding-left: 3rem !important;
position: relative;
&:hover {
opacity: 0.6;
}
}
.editorModesSelected {
cursor: default;
opacity: 0.6;
}
}
.editorModeTitle {
color: #000;
margin-bottom: 0.5rem;
}
.editorModeDescription {
color: #696969;
font-size: 1.2rem;
}
.editorModeIcon {
height: 2.4rem;
left: 0;
position: absolute;
top: -0.2em;
width: 2.4rem;
}

View File

@ -17,6 +17,8 @@ import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient'
import { ProfilePopup } from './ProfilePopup'
import { useSnackbar } from '../../context/snackbar'
import { Popup } from '../_shared/Popup'
import { VotersList } from '../_shared/VotersList'
import styles from './Header/Header.module.scss'
type Props = {
@ -51,7 +53,7 @@ export const HeaderAuth = (props: Props) => {
const isEditorPage = createMemo(() => page().route === 'edit' || page().route === 'editSettings')
const isNotificationsVisible = createMemo(() => isAuthenticated() && !isEditorPage())
const isSaveButtonVisible = createMemo(() => isAuthenticated() && isEditorPage())
const isCreatePostButtonVisible = createMemo(() => isAuthenticated() && !isEditorPage())
const isCreatePostButtonVisible = createMemo(() => !isEditorPage())
const isAuthenticatedControlsVisible = createMemo(
() => isAuthenticated() && session()?.user?.email_verified,
)
@ -65,6 +67,7 @@ export const HeaderAuth = (props: Props) => {
}
const [width, setWidth] = createSignal(0)
const [editorMode, setEditorMode] = createSignal(t('Editing'))
onMount(() => {
const handleResize = () => setWidth(window.innerWidth)
@ -106,7 +109,7 @@ export const HeaderAuth = (props: Props) => {
<Show when={isSessionLoaded()} keyed={true}>
<div class={clsx('col-auto col-lg-7', styles.usernav)}>
<div class={styles.userControl}>
<Show when={isCreatePostButtonVisible()}>
<Show when={isCreatePostButtonVisible() && isAuthenticated()}>
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
<a href={getPagePath(router, 'create')}>
<span class={styles.textLabel}>{t('Create post')}</span>
@ -117,7 +120,7 @@ export const HeaderAuth = (props: Props) => {
</Show>
<Show when={!isSaveButtonVisible()}>
<div class={styles.userControlItem}>
<div class={clsx(styles.userControlItem, styles.userControlItemSearch)}>
<a href="?m=search">
<Icon name="search" class={styles.icon} />
<Icon name="search" class={clsx(styles.icon, styles.iconHover)} />
@ -143,13 +146,47 @@ export const HeaderAuth = (props: Props) => {
</Show>
<Show when={isSaveButtonVisible()}>
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
{renderIconedButton({
value: t('Save'),
icon: 'save',
action: handleSaveButtonClick,
})}
</div>
<Popup
trigger={
<span class={styles.editorModePopupOpener}>
<Icon name="swiper-r-arr" class={styles.editorModePopupOpenerIcon} />
{editorMode()}
</span>
}
variant="bordered"
popupCssClass={styles.editorPopup}
>
<ul class={clsx('nodash', styles.editorModesList)}>
<li
class={clsx({ [styles.editorModesSelected]: editorMode() === t('Preview') })}
onClick={() => setEditorMode(t('Preview'))}
>
<Icon name="eye" class={styles.editorModeIcon} />
<div class={styles.editorModeTitle}>{t('Preview')}</div>
<div class={styles.editorModeDescription}>
Посмотрите, как материал будет выглядеть при публикации
</div>
</li>
<li
class={clsx({ [styles.editorModesSelected]: editorMode() === t('Editing') })}
onClick={() => setEditorMode(t('Editing'))}
>
<Icon name="pencil-outline" class={styles.editorModeIcon} />
<div class={styles.editorModeTitle}>{t('Editing')}</div>
<div class={styles.editorModeDescription}>Изменяйте текст напрямую в редакторе</div>
</li>
<li
class={clsx({ [styles.editorModesSelected]: editorMode() === t('Commenting') })}
onClick={() => setEditorMode(t('Commenting'))}
>
<Icon name="comment" class={styles.editorModeIcon} />
<div class={styles.editorModeTitle}>{t('Commenting')}</div>
<div class={styles.editorModeDescription}>
Предлагайте правки и комментарии, чтобы сделать материал лучше
</div>
</li>
</ul>
</Popup>
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
{renderIconedButton({
@ -159,12 +196,18 @@ export const HeaderAuth = (props: Props) => {
})}
</div>
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
<div
class={clsx(
styles.userControlItem,
styles.settingsControlContainer,
styles.userControlItemVerbose,
)}
>
<Popover content={t('Settings')}>
{(ref) => (
<Button
ref={ref}
value={<Icon name="burger" />}
value={<Icon name="ellipsis" />}
variant={'light'}
onClick={handleBurgerButtonClick}
class={styles.settingsControl}
@ -173,6 +216,17 @@ export const HeaderAuth = (props: Props) => {
</Popover>
</div>
</Show>
<Show when={isCreatePostButtonVisible() && !isAuthenticated()}>
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
<a href={getPagePath(router, 'create')}>
<span class={styles.textLabel}>{t('Create post')}</span>
<Icon name="pencil" class={styles.icon} />
<Icon name="pencil" class={clsx(styles.icon, styles.iconHover)} />
</a>
</div>
</Show>
<Show
when={isAuthenticatedControlsVisible()}
fallback={
@ -195,28 +249,31 @@ export const HeaderAuth = (props: Props) => {
</a>
</div>
</Show>
<ProfilePopup
onVisibilityChange={(isVisible) => {
props.setIsProfilePopupVisible(isVisible)
}}
containerCssClass={styles.control}
trigger={
<div class={styles.userControlItem}>
<button class={styles.button}>
<div classList={{ entered: page().path === `/${author()?.slug}` }}>
<Userpic
size={'M'}
name={author()?.name}
userpic={author()?.pic}
class={styles.userpic}
/>
</div>
</button>
</div>
}
/>
</Show>
</div>
<Show when={isAuthenticated()}>
<ProfilePopup
onVisibilityChange={(isVisible) => {
props.setIsProfilePopupVisible(isVisible)
}}
containerCssClass={styles.control}
trigger={
<div class={clsx(styles.userControlItem, styles.userControlItemUserpic)}>
<button class={styles.button}>
<div classList={{ entered: page().path === `/${author()?.slug}` }}>
<Userpic
size={'L'}
name={author()?.name}
userpic={author()?.pic}
class={styles.userpic}
/>
</div>
</button>
</div>
}
/>
</Show>
</div>
</Show>
</ShowOnlyOnClient>

View File

@ -1,5 +1,4 @@
.snackbar {
min-height: 2px;
background-color: var(--default-color);
color: #fff;
font-size: 2rem;

View File

@ -10,18 +10,23 @@
}
.notificationsCounter {
background-color: #d00820;
border: 2px solid #fff;
border-radius: 2em;
align-items: center;
background-color: #E84500;
border-radius: 0.8rem;
color: #fff;
font-size: 1rem;
display: flex;
font-size: 1.2rem;
font-weight: 700;
height: 1.6em;
left: 1.1em;
line-height: 1.25em;
height: 2.2rem;
justify-content: center;
left: 1.6rem;
min-width: 2.2rem;
padding: 0 0.25em;
position: absolute;
text-align: center;
top: -0.5rem;
min-width: 1.5em;
@include media-breakpoint-up(md) {
left: 1.8rem;
}
}

View File

@ -622,6 +622,10 @@ figure {
margin-bottom: 0.6em;
white-space: nowrap;
@include media-breakpoint-up(md) {
margin-right: 2.4rem;
}
.link {
border-bottom: none;
}