Skip to content

Commit

Permalink
feat: back-to-top and article badges (#122)
Browse files Browse the repository at this point in the history
Co-authored-by: Yaël Guilloux <yael.guilloux@gmail.com>
  • Loading branch information
Novout and Tahul committed May 16, 2023
1 parent 52dd186 commit 6584e87
Show file tree
Hide file tree
Showing 9 changed files with 711 additions and 202 deletions.
6 changes: 6 additions & 0 deletions .starters/default/content/articles/2.configure.md
Expand Up @@ -87,6 +87,12 @@ defineAppConfig({
navigation: false, // possible value are : true | false
position: 'center', // possible value are : 'none' | 'left' | 'center' | 'right'
message: 'Follow me on' // string that will be displayed on the footer (leave empty or delete to disable)
}
// Disable back to top button: false
backToTop: {
text: 'Back to top',
icon: 'material-symbols:arrow-upward'
}
}
})
```
16 changes: 16 additions & 0 deletions .starters/default/content/articles/3.write-articles.md
Expand Up @@ -91,6 +91,22 @@ description: Another description

You are now ready to edit your article and create new ones!

## Optional Arguments

In the frontmatter block, you can pass additional options for displaying your article, such as displaying badges on the image:

```md
---
cover: path/to/cover
date: 2022-08-23
badges: [{
color: 'white',
bg: 'rgba(0, 0, 0, 0.3)',
content: 'Technology'
}]
---
```

## Read more

Alpine is a Nuxt theme using the Content module in `documentDriven` mode.
Expand Down
2 changes: 1 addition & 1 deletion .starters/default/package.json
Expand Up @@ -10,7 +10,7 @@
"lint": "eslint ."
},
"devDependencies": {
"nuxt": "^3.4.3",
"nuxt": "^3.5.0",
"@nuxt-themes/alpine": "^1.5.4",
"@nuxtjs/plausible": "^0.2.1",
"@nuxt/devtools": "^0.4.6",
Expand Down
4 changes: 4 additions & 0 deletions app.config.ts
Expand Up @@ -36,6 +36,10 @@ export default defineAppConfig({
},
form: {
successMessage: 'Message sent. Thank you!'
},
backToTop: {
text: 'Back to top',
icon: 'material-symbols:arrow-upward'
}
}
})
46 changes: 43 additions & 3 deletions components/content/ArticlesListItem.vue
Expand Up @@ -6,6 +6,7 @@ type Article = {
title: string
date: string
description: string
badges?: { bg: string, text: string, content: string }[]
}
const props = defineProps({
Expand All @@ -30,15 +31,40 @@ const id = computed(() => {
</script>

<template>
<article v-if="article._path && article.title" :class="{ 'featured': featured }" :data-content-id="id">
<article
v-if="article._path && article.title"
:class="{ 'featured': featured }"
:data-content-id="id"
>
<div class="image">
<div v-if="article?.badges">
<span
v-for="(badge, index) in article.badges"
:key="index"
:style="{
backgroundColor: badge?.bg || 'rgba(0, 0, 0, 0.3)',
color: badge?.color || 'white'
}"
>
{{ typeof badge === 'string' ? badge : badge.content }}
</span>
</div>
<NuxtLink :to="article._path">
<NuxtImg v-if="article.cover" :src="article.cover" :alt="article.title" width="16" height="9" />
<NuxtImg
v-if="article.cover"
:src="article.cover"
:alt="article.title"
width="16"
height="9"
/>
</NuxtLink>
</div>
<div class="content">
<NuxtLink :to="article._path" class="headline">
<NuxtLink
:to="article._path"
class="headline"
>
<h1>
{{ article.title }}
</h1>
Expand Down Expand Up @@ -74,6 +100,20 @@ css({
},
'.image': {
flex: 1,
div: {
position: 'absolute',
display: 'flex',
flexWrap: true,
gap: '{space.2}',
marginTop: '{space.2}',
marginLeft: '{space.2}',
span: {
padding: '{space.1}',
borderRadius: '{radii.sm}',
text: 'xs',
fontWeight: 700
}
}
},
'.content': {
display: 'flex',
Expand Down
49 changes: 43 additions & 6 deletions layouts/article.vue
@@ -1,30 +1,51 @@
<template>
<article>
<article ref="article">
<!-- TODO: could be refactored as a transparent ButtonLink -->
<NuxtLink :to="parentPath" class="back">
<NuxtLink
:to="parentPath"
class="back"
>
<Icon name="ph:arrow-left" />
<span class="text-primary-900 dark:text-primary-100">
<span>
Back
</span>
</NuxtLink>
<header>
<h1 v-if="page?.title" class="title">
<h1
v-if="page?.title"
class="title"
>
{{ page.title }}
</h1>
<time v-if="page?.date" class="text-primary-700 dark:text-primary-400" :datetime="page.date">
<time
v-if="page?.date"
:datetime="page.date"
>
{{ formatDate(page.date) }}
</time>
</header>
<div class="prose">
<slot />
<div
v-if="alpine?.backToTop"
class="back-to-top"
>
<ProseA @click.prevent.stop="onBackToTop">
{{ alpine?.backToTop?.text || 'Back to top' }}
<Icon :name="alpine?.backToTop?.icon || 'material-symbols:arrow-upward'" />
</ProseA>
</div>
</div>
</article>
</template>
<script setup lang="ts">
const { page } = useContent()
const route = useRoute()
const alpine = useAppConfig().alpine
const article = ref<HTMLElement | null>(null)
if (page.value && page.value.cover) {
useHead({
Expand All @@ -41,6 +62,12 @@ const parentPath = computed(
return pathTabl.join('/')
}
)
const onBackToTop = () => {
article.value?.scrollIntoView({
behavior: 'smooth'
})
}
</script>
<style scoped lang="ts">
Expand Down Expand Up @@ -77,9 +104,19 @@ css({
color: '{elements.text.secondary.color.static}'
},
'.prose': {
'.back-to-top': {
display: 'flex',
justifyContent: 'flex-end',
alignItems: 'center',
width: '100%',
a: {
cursor: 'pointer',
fontSize: '{text.lg.fontSize}'
}
},
'& :deep(h1)': {
display: 'none'
}
},
}
}
})
Expand Down
9 changes: 9 additions & 0 deletions nuxt.schema.ts
Expand Up @@ -169,6 +169,15 @@ export default defineNuxtSchema({
* Success message.
*/
successMessage: 'Message sent. Thank you!'
},
/**
* Back to top button configuration.
*
* @studioIcon material-symbols:arrow-upward
*/
backToTop: {
icon: 'material-symbols:arrow-upward',
text: 'Back to top',
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions package.json
Expand Up @@ -36,13 +36,13 @@
"devDependencies": {
"@nuxt/eslint-config": "^0.1.1",
"@nuxtjs/plausible": "^0.2.1",
"@types/node": "^20.1.2",
"@types/node": "^20.1.5",
"eslint": "^8.40.0",
"nuxt": "^3.4.3",
"nuxt": "^3.5.0",
"release-it": "^15.10.3",
"typescript": "^5.0.4",
"vite-plugin-inspect": "^0.7.26",
"vue": "^3.2.47"
"vue": "^3.3.2"
},
"pnpm": {
"peerDependencyRules": {
Expand Down

0 comments on commit 6584e87

Please sign in to comment.