Skip to content

Commit

Permalink
refactor(website): Split GoToTop button, pages navigations and TOC fe…
Browse files Browse the repository at this point in the history
…atures into separate components, add accessibility titles.
  • Loading branch information
Ayfri committed Jan 8, 2025
1 parent 8251bac commit 03edc3d
Show file tree
Hide file tree
Showing 5 changed files with 262 additions and 208 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ fun Entry(article: DocArticle, selected: Boolean = false) = Li {
}

classes(DocTreeStyle.entry, DocTreeStyle.articleEntry)
title(article.navTitle)
if (selected) classes(DocTreeStyle.selected)
}
}
Expand All @@ -37,6 +38,7 @@ fun GroupEntry(name: String, level: Int) = Li({
}
}
classes(DocTreeStyle.entry, DocTreeStyle.groupEntry)
title(name)
}) {
Span(name)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package io.github.ayfri.kore.website.components.doc

import androidx.compose.runtime.*
import com.varabyte.kobweb.compose.css.Cursor
import com.varabyte.kobweb.compose.css.cursor
import com.varabyte.kobweb.compose.css.translateY
import com.varabyte.kobweb.compose.css.zIndex
import com.varabyte.kobweb.silk.components.icons.mdi.MdiKeyboardArrowUp
import io.github.ayfri.kore.website.GlobalStyle
import io.github.ayfri.kore.website.utils.transition
import kotlinx.browser.window
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Button

object GoToTopButtonStyle : StyleSheet() {
val button by style {
alignItems(AlignItems.Center)
backgroundColor(GlobalStyle.secondaryBackgroundColor)
border(0.px)
borderRadius(GlobalStyle.roundingButton)
bottom(2.cssRem)
color(GlobalStyle.textColor)
cursor(Cursor.Pointer)
display(DisplayStyle.Flex)
height(3.cssRem)
justifyContent(JustifyContent.Center)
opacity(0)
padding(0.px)
position(Position.Fixed)
right(2.cssRem)
transition(0.3.s, "opacity", "translate")
translateY(100.percent)
width(3.cssRem)
zIndex(10)

self + hover style {
backgroundColor(GlobalStyle.tertiaryBackgroundColor)
}

self + className("visible") style {
opacity(1)
translateY(0.percent)
}

child(self, type("span")) style {
fontSize(2.cssRem)
}
}
}

@Composable
fun GoToTopButton() {
var visible by remember { mutableStateOf(false) }

LaunchedEffect(Unit) {
window.onscroll = {
visible = window.scrollY > 300
}
}

Style(GoToTopButtonStyle)

Button(
{
classes(GoToTopButtonStyle.button)
if (visible) classes("visible")
onClick { window.scrollTo(0.0, 0.0) }
}
) {
MdiKeyboardArrowUp()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package io.github.ayfri.kore.website.components.doc

import androidx.compose.runtime.Composable
import com.varabyte.kobweb.compose.css.TextDecorationLine
import com.varabyte.kobweb.compose.css.autoLength
import com.varabyte.kobweb.compose.css.textDecorationLine
import io.github.ayfri.kore.website.GlobalStyle
import io.github.ayfri.kore.website.docEntries
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.A
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.dom.Text

object PageNavigationStyle : StyleSheet() {
val container by style {
display(DisplayStyle.Flex)
justifyContent(JustifyContent.SpaceBetween)
marginTop(2.cssRem)
gap(1.cssRem)
}

val prevPage by style {
color(GlobalStyle.linkColor)
textDecorationLine(TextDecorationLine.None)

self + hover style {
textDecorationLine(TextDecorationLine.Underline)
}
}

val nextPage by style {
color(GlobalStyle.linkColor)
marginLeft(autoLength)
textDecorationLine(TextDecorationLine.None)

self + hover style {
textDecorationLine(TextDecorationLine.Underline)
}
}
}

@Composable
fun PageNavigation(currentPath: String) {
val currentIndex = docEntries.indexOfFirst { it.path == currentPath }
if (currentIndex == -1) return

Style(PageNavigationStyle)

Div({
classes(PageNavigationStyle.container)
}) {
if (currentIndex > 0) {
A(docEntries[currentIndex - 1].path, {
classes(PageNavigationStyle.prevPage)
title(docEntries[currentIndex - 1].navTitle)
}) {
Text("${docEntries[currentIndex - 1].navTitle}")
}
}

if (currentIndex < docEntries.size - 1) {
A(docEntries[currentIndex + 1].path, {
classes(PageNavigationStyle.nextPage)
title(docEntries[currentIndex + 1].navTitle)
}) {
Text("${docEntries[currentIndex + 1].navTitle}")
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package io.github.ayfri.kore.website.components.doc

import androidx.compose.runtime.*
import com.varabyte.kobweb.compose.css.*
import io.github.ayfri.kore.website.GlobalStyle
import io.github.ayfri.kore.website.components.layouts.MarkdownLayoutStyle
import io.github.ayfri.kore.website.utils.smMax
import io.github.ayfri.kore.website.utils.transition
import kotlinx.browser.document
import kotlinx.browser.window
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.*
import org.w3c.dom.HTMLElement
import org.w3c.dom.asList

object TableOfContentsStyle : StyleSheet() {
val container by style {
backgroundColor(GlobalStyle.secondaryBackgroundColor)
borderRadius(GlobalStyle.roundingButton)
maxHeight(80.vh - 4.cssRem)
maxWidth(16.cssRem)
overflowY(Overflow.Auto)
padding(1.5.cssRem)
position(Position.Fixed)
right(1.cssRem)
top(15.vh)

smMax(self) {
display(DisplayStyle.None)
}

"ul" style {
paddingLeft(1.5.cssRem)
}
}

val entry by style {
cursor(Cursor.Pointer)
padding(0.2.cssRem, 0.px)
color(GlobalStyle.textColor)
listStyle(ListStyleType.None)
transition(0.2.s, "color")
overflow(Overflow.Hidden)
textOverflow(TextOverflow.Ellipsis)
whiteSpace(WhiteSpace.NoWrap)
userSelect(UserSelect.None)

self + hover style {
color(GlobalStyle.linkColor)
}
}
}

@Composable
fun TableOfContents() {
var headings by remember { mutableStateOf(listOf<HTMLElement>()) }

LaunchedEffect(Unit) {
headings = document.querySelectorAll(".${MarkdownLayoutStyle.mainContent} .${MarkdownLayoutStyle.heading}")
.asList()
.map { it as HTMLElement }
}

LaunchedEffect(Unit) {
window.addEventListener("hashchange", {
val hash = window.location.hash
if (hash.isNotEmpty()) {
val element = document.querySelector(hash)
element?.classList?.remove(MarkdownLayoutStyle.highlight)
element?.classList?.add(MarkdownLayoutStyle.highlight)
}
})
}

Style(TableOfContentsStyle)

Nav({
classes(TableOfContentsStyle.container)
}) {
H3 { Text("On this page") }
Ul {
headings.forEach { heading ->
val headingName = heading.innerText.removePrefix("link").trim()

Li({
classes(TableOfContentsStyle.entry)
title(headingName)
style {
marginLeft((heading.tagName.last().toString().toInt() - 2) * 1.25.cssRem)
}
onClick {
val id = heading.id
if (id.isNotEmpty()) {
window.location.hash = "#$id"
heading.classList.remove(MarkdownLayoutStyle.highlight)
heading.offsetWidth
heading.classList.add(MarkdownLayoutStyle.highlight)
}
}
}) {
Text(headingName)
}
}
}
}
}
Loading

0 comments on commit 03edc3d

Please sign in to comment.