Skip to content

Commit 531f262

Browse files
simonhampclaude
andcommitted
Move heading hash symbol after text and show on hover with animation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 40b1a5e commit 531f262

File tree

4 files changed

+77
-5
lines changed

4 files changed

+77
-5
lines changed

app/Support/CommonMark/HeadingRenderer.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ public function render(Node $node, ChildNodeRendererInterface $childRenderer)
2424

2525
if ($node->getLevel() === 1 || $node->getLevel() === 2 || $node->getLevel() === 3) {
2626
$element->setContents(
27+
$element->getContents().
2728
new HtmlElement(
2829
'a',
29-
['href' => "#{$id}", 'class' => 'mr-2 no-underline font-medium', 'style' => 'border-bottom: 0 !important;'],
30-
new HtmlElement('span', ['class' => ' text-gray-600 dark:text-gray-400 hover:text-[#00aaa6]'], '#'),
31-
).
32-
$element->getContents()
30+
['href' => "#{$id}", 'class' => 'heading-anchor ml-2 no-underline font-medium', 'style' => 'border-bottom: 0 !important;'],
31+
new HtmlElement('span', ['class' => 'text-gray-600 dark:text-gray-400 hover:text-[#00aaa6]'], '#'),
32+
)
3333
);
3434
}
3535

resources/css/app.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,18 @@ nav.docs-navigation li:has(.third-tier .exact-active) > .subsection-header {
207207
}
208208

209209
/* Prose */
210+
.prose h1,
211+
.prose h2,
212+
.prose h3 {
213+
& .heading-anchor {
214+
@apply inline-block opacity-0 translate-x-[-4px] transition-all duration-200 ease-out;
215+
}
216+
217+
&:hover .heading-anchor {
218+
@apply opacity-100 translate-x-0;
219+
}
220+
}
221+
210222
.prose h1 {
211223
@apply text-2xl;
212224
}

resources/views/components/plugin-toc.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
const elements = article.querySelectorAll('h2[id], h3[id]')
99
this.headings = Array.from(elements).map(el => ({
1010
id: el.id,
11-
text: el.textContent.replace(/^#\s*/, '').trim(),
11+
text: el.textContent.replace(/\s*#$/, '').trim(),
1212
level: parseInt(el.tagName.substring(1)),
1313
}))
1414
},
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace Tests\Feature;
4+
5+
use App\Support\CommonMark\CommonMark;
6+
use Tests\TestCase;
7+
8+
class HeadingRendererTest extends TestCase
9+
{
10+
public function test_heading_hash_appears_after_text(): void
11+
{
12+
$html = CommonMark::convertToHtml('## My Heading');
13+
14+
$this->assertStringContainsString('My Heading<a', $html);
15+
$this->assertStringNotContainsString('#</span></a>My Heading', $html);
16+
}
17+
18+
public function test_heading_anchor_has_correct_class(): void
19+
{
20+
$html = CommonMark::convertToHtml('## Test Heading');
21+
22+
$this->assertStringContainsString('heading-anchor', $html);
23+
$this->assertStringContainsString('ml-2', $html);
24+
}
25+
26+
public function test_heading_has_id_attribute(): void
27+
{
28+
$html = CommonMark::convertToHtml('## My Section');
29+
30+
$this->assertStringContainsString('id="my-section"', $html);
31+
}
32+
33+
public function test_heading_anchor_links_to_id(): void
34+
{
35+
$html = CommonMark::convertToHtml('## My Section');
36+
37+
$this->assertStringContainsString('href="#my-section"', $html);
38+
}
39+
40+
public function test_h1_gets_anchor(): void
41+
{
42+
$html = CommonMark::convertToHtml('# Title');
43+
44+
$this->assertStringContainsString('heading-anchor', $html);
45+
}
46+
47+
public function test_h3_gets_anchor(): void
48+
{
49+
$html = CommonMark::convertToHtml('### Sub Section');
50+
51+
$this->assertStringContainsString('heading-anchor', $html);
52+
}
53+
54+
public function test_h4_does_not_get_anchor(): void
55+
{
56+
$html = CommonMark::convertToHtml('#### Deep Heading');
57+
58+
$this->assertStringNotContainsString('heading-anchor', $html);
59+
}
60+
}

0 commit comments

Comments
 (0)