Skip to content

Commit c985d93

Browse files
committed
Extract shared ProseHeading component from prose h2/h3 overrides
Move the heading markup, anchor glyph, and accessibility attributes into a generic ProseHeading component that accepts an `as` prop (h1–h6) and an optional `glyph` prop (defaults to `#`). ProseH2 and ProseH3 become thin wrappers delegating to ProseHeading. Shared ProseHeadingProps interface lives in utils/ for auto-import. Signed-off-by: Alejandro Mery <amery@apptly.co> Signed-off-by: Claude <noreply@anthropic.com>
1 parent d848706 commit c985d93

4 files changed

Lines changed: 47 additions & 30 deletions

File tree

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
11
<script setup lang="ts">
2-
/** Prose h2 override — plain heading with hover-visible `#` anchor glyph. */
3-
const props = defineProps<{
4-
/** Heading anchor ID, used for the `id` attribute and `#` permalink. */
5-
id?: string
6-
}>();
2+
/** Prose h2 override — delegates to ProseHeading with anchor glyph. */
3+
const props = defineProps<ProseHeadingProps>();
74
</script>
85

96
<template>
10-
<h2
11-
:id="id"
12-
class="group"
7+
<ProseHeading
8+
:id="props.id"
9+
:glyph="props.glyph"
10+
as="h2"
1311
>
1412
<slot />
15-
<a
16-
v-if="props.id"
17-
:href="`#${props.id}`"
18-
class="ml-2 no-underline text-gray-300 opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100 hover:text-gray-500"
19-
aria-label="Permalink to this section"
20-
>#</a>
21-
</h2>
13+
</ProseHeading>
2214
</template>
Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
11
<script setup lang="ts">
2-
/** Prose h3 override — plain heading with hover-visible `#` anchor glyph. */
3-
const props = defineProps<{
4-
/** Heading anchor ID, used for the `id` attribute and `#` permalink. */
5-
id?: string
6-
}>();
2+
/** Prose h3 override — delegates to ProseHeading with anchor glyph. */
3+
const props = defineProps<ProseHeadingProps>();
74
</script>
85

96
<template>
10-
<h3
11-
:id="id"
12-
class="group"
7+
<ProseHeading
8+
:id="props.id"
9+
:glyph="props.glyph"
10+
as="h3"
1311
>
1412
<slot />
15-
<a
16-
v-if="props.id"
17-
:href="`#${props.id}`"
18-
class="ml-2 no-underline text-gray-300 opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100 hover:text-gray-500"
19-
aria-label="Permalink to this section"
20-
>#</a>
21-
</h3>
13+
</ProseHeading>
2214
</template>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<script setup lang="ts">
2+
/** Generic prose heading with hover-visible anchor glyph. */
3+
const props = withDefaults(defineProps<ProseHeadingProps & {
4+
/** HTML heading element to render. */
5+
as: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
6+
}>(), {
7+
glyph: '#',
8+
});
9+
</script>
10+
11+
<template>
12+
<component
13+
:is="props.as"
14+
:id="props.id"
15+
class="group"
16+
>
17+
<slot />
18+
<a
19+
v-if="props.id"
20+
:href="`#${props.id}`"
21+
class="ml-2 no-underline text-gray-300 opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100 hover:text-gray-500"
22+
aria-label="Permalink to this section"
23+
>{{ props.glyph }}</a>
24+
</component>
25+
</template>

app/utils/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
// Virtual slug for the "Other" group (projects not under any umbrella).
22
export const OTHER_SLUG = '_';
33

4+
/** Shared props for prose heading overrides. */
5+
export interface ProseHeadingProps {
6+
/** Heading anchor ID, used for the `id` attribute and `#` permalink. */
7+
id?: string
8+
/** Anchor glyph shown on hover. */
9+
glyph?: string
10+
}
11+
412
/**
513
* Type-safe Array.includes that accepts a wider search value.
614
*

0 commit comments

Comments
 (0)