11<script setup lang="ts">
2- import { shallowRef , computed } from ' vue'
2+ import { computed , shallowRef } from ' vue'
33
44interface Props {
55 title: string
66 isLoading? : boolean
77 headingLevel? : ` h${number } `
88 id: string
9+ order? : number
910}
1011
1112const props = withDefaults (defineProps <Props >(), {
@@ -20,6 +21,7 @@ const contentId = `${props.id}-collapsible-content`
2021const headingId = ` ${props .id }-heading `
2122
2223const isOpen = shallowRef (true )
24+ const isPinned = shallowRef (false )
2325
2426onPrehydrate (() => {
2527 const settings = JSON .parse (localStorage .getItem (' npmx-settings' ) || ' {}' )
@@ -38,13 +40,14 @@ onPrehydrate(() => {
3840onMounted (() => {
3941 if (document ?.documentElement ) {
4042 isOpen .value = ! (document .documentElement .dataset .collapsed ?.includes (props .id ) ?? false )
43+ isPinned .value = document .documentElement .dataset .pinned ?.includes (props .id ) ?? false
4144 }
4245})
4346
4447function toggle() {
4548 isOpen .value = ! isOpen .value
4649
47- const removed = appSettings .settings .value .sidebar .collapsed .filter (c => c !== props .id )
50+ const removed = appSettings .settings .value .sidebar .collapsed ? .filter (c => c !== props .id ) ?? []
4851
4952 if (isOpen .value ) {
5053 appSettings .settings .value .sidebar .collapsed = removed
@@ -57,6 +60,21 @@ function toggle() {
5760 appSettings .settings .value .sidebar .collapsed .join (' ' )
5861}
5962
63+ function togglePin() {
64+ isPinned .value = ! isPinned .value
65+
66+ const removed = appSettings .settings .value .sidebar .pinned ?.filter (c => c !== props .id ) ?? []
67+
68+ if (isPinned .value ) {
69+ removed .push (props .id )
70+ appSettings .settings .value .sidebar .pinned = removed
71+ } else {
72+ appSettings .settings .value .sidebar .pinned = removed
73+ }
74+
75+ document .documentElement .dataset .pinned = appSettings .settings .value .sidebar .pinned .join (' ' )
76+ }
77+
6078const ariaLabel = computed (() => {
6179 const action = isOpen .value ? ' Collapse' : ' Expand'
6280 return props .title ? ` ${action } ${props .title } ` : action
@@ -74,7 +92,11 @@ useHead({
7492 </script >
7593
7694<template >
77- <section class =" scroll-mt-20" :data-anchor-id =" id" >
95+ <section
96+ class =" scroll-mt-20"
97+ :class =" order !== undefined ? `order-${order}` : ''"
98+ :data-anchor-id =" id"
99+ >
78100 <div class =" flex items-center justify-between mb-3" >
79101 <component
80102 :is =" headingLevel"
@@ -117,6 +139,15 @@ useHead({
117139
118140 <!-- Actions slot for buttons or other elements -->
119141 <slot name =" actions" />
142+ <!-- pin button -->
143+ <button
144+ type =" button"
145+ class =" w-4 h-4 flex items-center justify-center text-fg-subtle hover:text-fg-muted transition-colors duration-200 shrink-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 rounded"
146+ @click =" togglePin"
147+ >
148+ <span v-if =" isPinned" class =" i-carbon:pin-filled w-3 h-3" aria-hidden =" true" />
149+ <span v-else class =" i-carbon:pin w-3 h-3" aria-hidden =" true" />
150+ </button >
120151 </div >
121152
122153 <div
0 commit comments