diff --git a/app/components/DemoStage.vue b/app/components/DemoStage.vue index 53fa6527..3716a212 100644 --- a/app/components/DemoStage.vue +++ b/app/components/DemoStage.vue @@ -40,8 +40,10 @@ const liveUrl = computed(() => live && !demo.video && !demo.writing ? demo.liveU
{{ recording.usage.sentence }} @@ -58,7 +60,9 @@ const liveUrl = computed(() => live && !demo.video && !demo.writing ? demo.liveU
{{ demo.prompt }}
diff --git a/layers/registry/app/components/SkillFileTreeNode.vue b/layers/registry/app/components/SkillFileTreeNode.vue
index 6070ddb0..f69b3ee3 100644
--- a/layers/registry/app/components/SkillFileTreeNode.vue
+++ b/layers/registry/app/components/SkillFileTreeNode.vue
@@ -20,12 +20,20 @@ const emit = defineEmits<{
select: [path: string]
}>()
-const open = ref(props.node.kind === 'dir' && props.node.initiallyOpen)
+// Mount a folder's entries on first expansion. Keep them after closing so
+// nested expansion state survives, without sending unopened files in HTML.
+const folderState = ref<'unopened' | 'open' | 'closed'>(
+ props.node.kind === 'dir' && props.node.initiallyOpen ? 'open' : 'unopened',
+)
+const open = computed(() => folderState.value === 'open')
+const renderedChildren = computed(() =>
+ props.node.kind === 'dir' && folderState.value !== 'unopened' ? props.node.children : [],
+)
// Opening a file from a link or the breadcrumb reveals it in the tree.
watch(() => props.activePath, (active) => {
if (props.node.kind === 'dir' && active.startsWith(`${props.node.path}/`))
- open.value = true
+ folderState.value = 'open'
}, { immediate: true })
function countFiles(node: TreeNode): number {
@@ -72,7 +80,7 @@ const inlineRenderable = computed(() =>
:aria-expanded="open"
:aria-controls="`${idPrefix}-${node.path}`"
:title="node.path"
- @click="open = !open"
+ @click="folderState = open ? 'closed' : 'open'"
>