Table of contents mobile style

This commit is contained in:
kvakazyambra 2023-09-20 23:57:44 +03:00
parent 5aa0d1c98b
commit 42493c2e98
3 changed files with 133 additions and 33 deletions

View File

@ -297,7 +297,7 @@ export const FullArticle = (props: Props) => {
</Show> </Show>
</article> </article>
<Show when={isDesktop() && body()}> <Show when={body()}>
<div class="col-md-6 offset-md-1"> <div class="col-md-6 offset-md-1">
<TableOfContents variant="article" parentSelector="#shoutBody" body={body()} /> <TableOfContents variant="article" parentSelector="#shoutBody" body={body()} />
</div> </div>

View File

@ -1,7 +1,38 @@
.TableOfContentsFixedWrapper { .TableOfContentsFixedWrapper {
min-height: 100%; min-height: 100%;
position: relative;
top: 0; top: 0;
@include media-breakpoint-down(xl) {
background: #000;
bottom: 0;
color: #fff;
font-size: 1.6rem;
left: 0;
min-height: auto;
max-height: 50vh;
position: fixed;
top: auto;
width: 100%;
.TableOfContentsHeading {
text-transform: capitalize;
}
.TableOfContentsHeading,
button {
&,
&:hover {
color: #fff;
}
}
.TableOfContentsHeadingsItem {
font-size: 1.6rem;
margin-top: 1.6rem;
}
}
&:not(.TableOfContentsFixedWrapperLefted) { &:not(.TableOfContentsFixedWrapperLefted) {
margin-top: -0.2em; margin-top: -0.2em;
@ -32,19 +63,31 @@
} }
.TableOfContentsContainer { .TableOfContentsContainer {
position: sticky;
top: 100px; top: 100px;
right: 20px; right: 20px;
display: flex; display: flex;
width: 100%; width: 100%;
height: calc(100vh - 120px);
overflow: auto; overflow: auto;
flex-direction: column;
align-items: flex-start; align-items: flex-start;
background-color: transparent; background-color: transparent;
.TableOfContentsFixedWrapperLefted & { @include media-breakpoint-up(xl) {
height: calc(100vh - 250px); flex-direction: column;
height: calc(100vh - 120px);
position: sticky;
.TableOfContentsFixedWrapperLefted & {
height: calc(100vh - 250px);
}
}
}
.TableOfContentsContainerInner {
@include media-breakpoint-down(xl) {
flex: 1 100%;
max-height: 50vh;
overflow: auto;
padding: 1.4rem 2rem;
} }
} }
@ -74,11 +117,31 @@
border: none; border: none;
cursor: pointer; cursor: pointer;
@include media-breakpoint-down(xl) {
background: #fff;
border: 1px solid #000;
border-radius: 100%;
bottom: 1rem;
height: 40px;
position: fixed;
right: 1rem;
top: auto;
width: 40px;
}
&:hover { &:hover {
filter: invert(1); filter: invert(1);
} }
} }
.TableOfContentsCloseButton {
height: 2.4rem;
position: absolute;
top: 1.4rem;
right: 1.4rem;
width: 2.4rem;
}
.TableOfContentsHeadingsList { .TableOfContentsHeadingsList {
position: relative; position: relative;
display: flex; display: flex;
@ -97,7 +160,6 @@
font-weight: 400; font-weight: 400;
line-height: 20px; line-height: 20px;
text-align: left; text-align: left;
letter-spacing: -0.14px;
&:hover { &:hover {
color: rgb(0 0 0 / 50%); color: rgb(0 0 0 / 50%);

View File

@ -68,42 +68,48 @@ export const TableOfContents = (props: Props) => {
> >
<div class={styles.TableOfContentsContainer}> <div class={styles.TableOfContentsContainer}>
<Show when={isVisible()}> <Show when={isVisible()}>
<div class={styles.TableOfContentsHeader}> <div class={styles.TableOfContentsContainerInner}>
<p class={styles.TableOfContentsHeading}>{t('contents')}</p> <div class={styles.TableOfContentsHeader}>
</div> <p class={styles.TableOfContentsHeading}>{t('contents')}</p>
<ul class={styles.TableOfContentsHeadingsList}> </div>
<For each={headings()}> <ul class={styles.TableOfContentsHeadingsList}>
{(h) => ( <For each={headings()}>
<li> {(h) => (
<button <li>
class={clsx(styles.TableOfContentsHeadingsItem, { <button
[styles.TableOfContentsHeadingsItemH3]: h.nodeName === 'H3', class={clsx(styles.TableOfContentsHeadingsItem, {
[styles.TableOfContentsHeadingsItemH4]: h.nodeName === 'H4' [styles.TableOfContentsHeadingsItemH3]: h.nodeName === 'H3',
})} [styles.TableOfContentsHeadingsItemH4]: h.nodeName === 'H4'
innerHTML={h.textContent} })}
onClick={(e) => { innerHTML={h.textContent}
e.preventDefault() onClick={(e) => {
e.preventDefault()
scrollToHeader(h) scrollToHeader(h)
}} }}
/> />
</li> </li>
)} )}
</For> </For>
</ul> </ul>
</div>
</Show> </Show>
<button <button
class={clsx(styles.TableOfContentsPrimaryButton, { class={clsx(
[styles.TableOfContentsPrimaryButtonLefted]: props.variant === 'editor' && !isVisible() styles.TableOfContentsPrimaryButton,
})} {
[styles.TableOfContentsPrimaryButtonLefted]: props.variant === 'editor' && !isVisible()
},
'd-none d-xl-block'
)}
onClick={(e) => { onClick={(e) => {
e.preventDefault() e.preventDefault()
toggleIsVisible() toggleIsVisible()
}} }}
title={isVisible() ? t('Hide table of contents') : t('Show table of contents')} title={isVisible() ? t('Hide table of contents') : t('Show table of contents')}
> >
<Show when={isVisible()} fallback={<Icon name="show-table-of-contents" class={'icon'} />}> <Show when={isVisible()} fallback={<Icon name="show-table-of-contents" class="icon" />}>
{props.variant === 'editor' ? ( {props.variant === 'editor' ? (
<Icon name="hide-table-of-contents" class="icon" /> <Icon name="hide-table-of-contents" class="icon" />
) : ( ) : (
@ -111,7 +117,39 @@ export const TableOfContents = (props: Props) => {
)} )}
</Show> </Show>
</button> </button>
<Show when={isVisible()}>
<button
class={clsx(styles.TableOfContentsCloseButton, 'd-xl-none')}
onClick={(e) => {
e.preventDefault()
toggleIsVisible()
}}
title={isVisible() ? t('Hide table of contents') : t('Show table of contents')}
>
<Icon name="close-white" class="icon" />
</button>
</Show>
</div> </div>
<Show when={!isVisible()}>
<button
class={clsx(
styles.TableOfContentsPrimaryButton,
{
[styles.TableOfContentsPrimaryButtonLefted]: props.variant === 'editor' && !isVisible()
},
'd-xl-none'
)}
onClick={(e) => {
e.preventDefault()
toggleIsVisible()
}}
title={isVisible() ? t('Hide table of contents') : t('Show table of contents')}
>
<Icon name="hide-table-of-contents-2" class="icon" />
</button>
</Show>
</div> </div>
</Show> </Show>
) )