Resolves #1
+114
-124
Diff
round #0
+1
-14
bun.lock
+1
-14
bun.lock
···
24
24
},
25
25
"packages/cli": {
26
26
"name": "sequoia-cli",
27
-
"version": "0.3.2",
27
+
"version": "0.4.0",
28
28
"bin": {
29
29
"sequoia": "dist/index.js",
30
30
},
···
47
47
"typescript": "^5",
48
48
},
49
49
},
50
-
"packages/ui": {
51
-
"name": "sequoia-ui",
52
-
"version": "0.1.0",
53
-
"devDependencies": {
54
-
"@biomejs/biome": "^2.3.13",
55
-
"@types/node": "^20",
56
-
},
57
-
"peerDependencies": {
58
-
"typescript": "^5",
59
-
},
60
-
},
61
50
},
62
51
"packages": {
63
52
"@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
···
1370
1359
1371
1360
"sequoia-cli": ["sequoia-cli@workspace:packages/cli"],
1372
1361
1373
-
"sequoia-ui": ["sequoia-ui@workspace:packages/ui"],
1374
-
1375
1362
"serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="],
1376
1363
1377
1364
"set-cookie-parser": ["set-cookie-parser@2.7.2", "", {}, "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw=="],
+1
docs/docs/pages/comments.mdx
+1
docs/docs/pages/comments.mdx
···
143
143
|-----------|------|---------|-------------|
144
144
| `document-uri` | `string` | - | AT Protocol URI for the document. Optional if a `<link rel="site.standard.document">` tag exists in the page head. |
145
145
| `depth` | `number` | `6` | Maximum depth of nested replies to fetch. |
146
+
| `hide` | `string` | - | Set to "auto" to hide if no document link is detected |
146
147
147
148
```html
148
149
<!-- Use attributes for explicit control -->
+56
-55
docs/docs/public/sequoia-comments.js
+56
-55
docs/docs/public/sequoia-comments.js
···
14
14
* Attributes:
15
15
* - document-uri: AT Protocol URI for the document (optional if link tag exists)
16
16
* - depth: Maximum depth of nested replies to fetch (default: 6)
17
+
* - hide: Set to "auto" to hide if no document link is detected
17
18
*
18
19
* CSS Custom Properties:
19
20
* - --sequoia-fg-color: Text color (default: #1f2937)
···
573
574
class SequoiaComments extends BaseElement {
574
575
constructor() {
575
576
super();
576
-
this.shadow = this.attachShadow({ mode: "open" });
577
+
const shadow = this.attachShadow({ mode: "open" });
578
+
579
+
const styleTag = document.createElement("style");
580
+
shadow.appendChild(styleTag);
581
+
styleTag.innerText = styles;
582
+
583
+
const container = document.createElement("div");
584
+
shadow.appendChild(container);
585
+
container.className = "sequoia-comments-container";
586
+
container.part = "container";
587
+
588
+
this.commentsContainer = container;
577
589
this.state = { type: "loading" };
578
590
this.abortController = null;
591
+
579
592
}
580
593
581
594
static get observedAttributes() {
582
-
return ["document-uri", "depth"];
595
+
return ["document-uri", "depth", "hide"];
583
596
}
584
597
585
598
connectedCallback() {
···
616
629
return depthAttr ? parseInt(depthAttr, 10) : 6;
617
630
}
618
631
632
+
get hide() {
633
+
const hideAttr = this.getAttribute("hide");
634
+
return hideAttr === "auto";
635
+
}
636
+
619
637
async loadComments() {
620
638
// Cancel any in-flight request
621
639
this.abortController?.abort();
···
666
684
}
667
685
668
686
render() {
669
-
const styleTag = `<style>${styles}</style>`;
670
-
671
687
switch (this.state.type) {
672
688
case "loading":
673
-
this.shadow.innerHTML = `
674
-
${styleTag}
675
-
<div class="sequoia-comments-container">
676
-
<div class="sequoia-loading">
677
-
<span class="sequoia-loading-spinner"></span>
678
-
Loading comments...
679
-
</div>
689
+
this.commentsContainer.innerHTML = `
690
+
<div class="sequoia-loading">
691
+
<span class="sequoia-loading-spinner"></span>
692
+
Loading comments...
680
693
</div>
681
694
`;
682
695
break;
683
696
684
697
case "no-document":
685
-
this.shadow.innerHTML = `
686
-
${styleTag}
687
-
<div class="sequoia-comments-container">
688
-
<div class="sequoia-warning">
689
-
No document found. Add a <code><link rel="site.standard.document" href="at://..."></code> tag to your page.
690
-
</div>
698
+
this.commentsContainer.innerHTML = `
699
+
<div class="sequoia-warning">
700
+
No document found. Add a <code><link rel="site.standard.document" href="at://..."></code> tag to your page.
691
701
</div>
692
702
`;
703
+
if (this.hide) {
704
+
this.commentsContainer.style.display = 'none';
705
+
}
693
706
break;
694
707
695
708
case "no-comments-enabled":
696
-
this.shadow.innerHTML = `
697
-
${styleTag}
698
-
<div class="sequoia-comments-container">
699
-
<div class="sequoia-empty">
700
-
Comments are not enabled for this post.
701
-
</div>
709
+
this.commentsContainer.innerHTML = `
710
+
<div class="sequoia-empty">
711
+
Comments are not enabled for this post.
702
712
</div>
703
713
`;
704
714
break;
705
715
706
716
case "empty":
707
-
this.shadow.innerHTML = `
708
-
${styleTag}
709
-
<div class="sequoia-comments-container">
710
-
<div class="sequoia-comments-header">
711
-
<h3 class="sequoia-comments-title">Comments</h3>
712
-
<a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
713
-
${BLUESKY_ICON}
714
-
Reply on Bluesky
715
-
</a>
716
-
</div>
717
-
<div class="sequoia-empty">
718
-
No comments yet. Be the first to reply on Bluesky!
719
-
</div>
717
+
this.commentsContainer.innerHTML = `
718
+
<div class="sequoia-comments-header">
719
+
<h3 class="sequoia-comments-title">Comments</h3>
720
+
<a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
721
+
${BLUESKY_ICON}
722
+
Reply on Bluesky
723
+
</a>
724
+
</div>
725
+
<div class="sequoia-empty">
726
+
No comments yet. Be the first to reply on Bluesky!
720
727
</div>
721
728
`;
722
729
break;
723
730
724
731
case "error":
725
-
this.shadow.innerHTML = `
726
-
${styleTag}
727
-
<div class="sequoia-comments-container">
728
-
<div class="sequoia-error">
729
-
Failed to load comments: ${escapeHtml(this.state.message)}
730
-
</div>
732
+
this.commentsContainer.innerHTML = `
733
+
<div class="sequoia-error">
734
+
Failed to load comments: ${escapeHtml(this.state.message)}
731
735
</div>
732
736
`;
733
737
break;
···
740
744
.join("");
741
745
const commentCount = this.countComments(replies);
742
746
743
-
this.shadow.innerHTML = `
744
-
${styleTag}
745
-
<div class="sequoia-comments-container">
746
-
<div class="sequoia-comments-header">
747
-
<h3 class="sequoia-comments-title">${commentCount} Comment${commentCount !== 1 ? "s" : ""}</h3>
748
-
<a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
749
-
${BLUESKY_ICON}
750
-
Reply on Bluesky
751
-
</a>
752
-
</div>
753
-
<div class="sequoia-comments-list">
754
-
${threadsHtml}
755
-
</div>
747
+
this.commentsContainer.innerHTML = `
748
+
<div class="sequoia-comments-header">
749
+
<h3 class="sequoia-comments-title">${commentCount} Comment${commentCount !== 1 ? "s" : ""}</h3>
750
+
<a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
751
+
${BLUESKY_ICON}
752
+
Reply on Bluesky
753
+
</a>
754
+
</div>
755
+
<div class="sequoia-comments-list">
756
+
${threadsHtml}
756
757
</div>
757
758
`;
758
759
break;
+56
-55
packages/cli/src/components/sequoia-comments.js
+56
-55
packages/cli/src/components/sequoia-comments.js
···
14
14
* Attributes:
15
15
* - document-uri: AT Protocol URI for the document (optional if link tag exists)
16
16
* - depth: Maximum depth of nested replies to fetch (default: 6)
17
+
* - hide: Set to "auto" to hide if no document link is detected
17
18
*
18
19
* CSS Custom Properties:
19
20
* - --sequoia-fg-color: Text color (default: #1f2937)
···
573
574
class SequoiaComments extends BaseElement {
574
575
constructor() {
575
576
super();
576
-
this.shadow = this.attachShadow({ mode: "open" });
577
+
const shadow = this.attachShadow({ mode: "open" });
578
+
579
+
const styleTag = document.createElement("style");
580
+
shadow.appendChild(styleTag);
581
+
styleTag.innerText = styles;
582
+
583
+
const container = document.createElement("div");
584
+
shadow.appendChild(container);
585
+
container.className = "sequoia-comments-container";
586
+
container.part = "container";
587
+
588
+
this.commentsContainer = container;
577
589
this.state = { type: "loading" };
578
590
this.abortController = null;
591
+
579
592
}
580
593
581
594
static get observedAttributes() {
582
-
return ["document-uri", "depth"];
595
+
return ["document-uri", "depth", "hide"];
583
596
}
584
597
585
598
connectedCallback() {
···
616
629
return depthAttr ? parseInt(depthAttr, 10) : 6;
617
630
}
618
631
632
+
get hide() {
633
+
const hideAttr = this.getAttribute("hide");
634
+
return hideAttr === "auto";
635
+
}
636
+
619
637
async loadComments() {
620
638
// Cancel any in-flight request
621
639
this.abortController?.abort();
···
666
684
}
667
685
668
686
render() {
669
-
const styleTag = `<style>${styles}</style>`;
670
-
671
687
switch (this.state.type) {
672
688
case "loading":
673
-
this.shadow.innerHTML = `
674
-
${styleTag}
675
-
<div class="sequoia-comments-container">
676
-
<div class="sequoia-loading">
677
-
<span class="sequoia-loading-spinner"></span>
678
-
Loading comments...
679
-
</div>
689
+
this.commentsContainer.innerHTML = `
690
+
<div class="sequoia-loading">
691
+
<span class="sequoia-loading-spinner"></span>
692
+
Loading comments...
680
693
</div>
681
694
`;
682
695
break;
683
696
684
697
case "no-document":
685
-
this.shadow.innerHTML = `
686
-
${styleTag}
687
-
<div class="sequoia-comments-container">
688
-
<div class="sequoia-warning">
689
-
No document found. Add a <code><link rel="site.standard.document" href="at://..."></code> tag to your page.
690
-
</div>
698
+
this.commentsContainer.innerHTML = `
699
+
<div class="sequoia-warning">
700
+
No document found. Add a <code><link rel="site.standard.document" href="at://..."></code> tag to your page.
691
701
</div>
692
702
`;
703
+
if (this.hide) {
704
+
this.commentsContainer.style.display = 'none';
705
+
}
693
706
break;
694
707
695
708
case "no-comments-enabled":
696
-
this.shadow.innerHTML = `
697
-
${styleTag}
698
-
<div class="sequoia-comments-container">
699
-
<div class="sequoia-empty">
700
-
Comments are not enabled for this post.
701
-
</div>
709
+
this.commentsContainer.innerHTML = `
710
+
<div class="sequoia-empty">
711
+
Comments are not enabled for this post.
702
712
</div>
703
713
`;
704
714
break;
705
715
706
716
case "empty":
707
-
this.shadow.innerHTML = `
708
-
${styleTag}
709
-
<div class="sequoia-comments-container">
710
-
<div class="sequoia-comments-header">
711
-
<h3 class="sequoia-comments-title">Comments</h3>
712
-
<a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
713
-
${BLUESKY_ICON}
714
-
Reply on Bluesky
715
-
</a>
716
-
</div>
717
-
<div class="sequoia-empty">
718
-
No comments yet. Be the first to reply on Bluesky!
719
-
</div>
717
+
this.commentsContainer.innerHTML = `
718
+
<div class="sequoia-comments-header">
719
+
<h3 class="sequoia-comments-title">Comments</h3>
720
+
<a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
721
+
${BLUESKY_ICON}
722
+
Reply on Bluesky
723
+
</a>
724
+
</div>
725
+
<div class="sequoia-empty">
726
+
No comments yet. Be the first to reply on Bluesky!
720
727
</div>
721
728
`;
722
729
break;
723
730
724
731
case "error":
725
-
this.shadow.innerHTML = `
726
-
${styleTag}
727
-
<div class="sequoia-comments-container">
728
-
<div class="sequoia-error">
729
-
Failed to load comments: ${escapeHtml(this.state.message)}
730
-
</div>
732
+
this.commentsContainer.innerHTML = `
733
+
<div class="sequoia-error">
734
+
Failed to load comments: ${escapeHtml(this.state.message)}
731
735
</div>
732
736
`;
733
737
break;
···
740
744
.join("");
741
745
const commentCount = this.countComments(replies);
742
746
743
-
this.shadow.innerHTML = `
744
-
${styleTag}
745
-
<div class="sequoia-comments-container">
746
-
<div class="sequoia-comments-header">
747
-
<h3 class="sequoia-comments-title">${commentCount} Comment${commentCount !== 1 ? "s" : ""}</h3>
748
-
<a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
749
-
${BLUESKY_ICON}
750
-
Reply on Bluesky
751
-
</a>
752
-
</div>
753
-
<div class="sequoia-comments-list">
754
-
${threadsHtml}
755
-
</div>
747
+
this.commentsContainer.innerHTML = `
748
+
<div class="sequoia-comments-header">
749
+
<h3 class="sequoia-comments-title">${commentCount} Comment${commentCount !== 1 ? "s" : ""}</h3>
750
+
<a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
751
+
${BLUESKY_ICON}
752
+
Reply on Bluesky
753
+
</a>
754
+
</div>
755
+
<div class="sequoia-comments-list">
756
+
${threadsHtml}
756
757
</div>
757
758
`;
758
759
break;
History
1 round
2 comments
heaths.dev
submitted
#0
1 commit
expand
collapse
Add hide attribute to sequoia-comments component
Resolves #1
expand 2 comments
All good! Experimental software and all that lol. Thanks for this!
pull request successfully merged
Rats. I just pushed the same commit here so it references the wrong issue. I can't change the PR description, unfortunately, until https://tangled.org/tangled.org/core/issues/175 is implemented. This actually resolved issue #12 here on tangled.