···143143|-----------|------|---------|-------------|
144144| `document-uri` | `string` | - | AT Protocol URI for the document. Optional if a `<link rel="site.standard.document">` tag exists in the page head. |
145145| `depth` | `number` | `6` | Maximum depth of nested replies to fetch. |
146146+| `hide` | `string` | - | Set to "auto" to hide if no document link is detected |
146147147148```html
148149<!-- Use attributes for explicit control -->
+56-55
docs/docs/public/sequoia-comments.js
···1414 * Attributes:
1515 * - document-uri: AT Protocol URI for the document (optional if link tag exists)
1616 * - depth: Maximum depth of nested replies to fetch (default: 6)
1717+ * - hide: Set to "auto" to hide if no document link is detected
1718 *
1819 * CSS Custom Properties:
1920 * - --sequoia-fg-color: Text color (default: #1f2937)
···573574class SequoiaComments extends BaseElement {
574575 constructor() {
575576 super();
576576- this.shadow = this.attachShadow({ mode: "open" });
577577+ const shadow = this.attachShadow({ mode: "open" });
578578+579579+ const styleTag = document.createElement("style");
580580+ shadow.appendChild(styleTag);
581581+ styleTag.innerText = styles;
582582+583583+ const container = document.createElement("div");
584584+ shadow.appendChild(container);
585585+ container.className = "sequoia-comments-container";
586586+ container.part = "container";
587587+588588+ this.commentsContainer = container;
577589 this.state = { type: "loading" };
578590 this.abortController = null;
591591+579592 }
580593581594 static get observedAttributes() {
582582- return ["document-uri", "depth"];
595595+ return ["document-uri", "depth", "hide"];
583596 }
584597585598 connectedCallback() {
···614627 get depth() {
615628 const depthAttr = this.getAttribute("depth");
616629 return depthAttr ? parseInt(depthAttr, 10) : 6;
630630+ }
631631+632632+ get hide() {
633633+ const hideAttr = this.getAttribute("hide");
634634+ return hideAttr === "auto";
617635 }
618636619637 async loadComments() {
···666684 }
667685668686 render() {
669669- const styleTag = `<style>${styles}</style>`;
670670-671687 switch (this.state.type) {
672688 case "loading":
673673- this.shadow.innerHTML = `
674674- ${styleTag}
675675- <div class="sequoia-comments-container">
676676- <div class="sequoia-loading">
677677- <span class="sequoia-loading-spinner"></span>
678678- Loading comments...
679679- </div>
689689+ this.commentsContainer.innerHTML = `
690690+ <div class="sequoia-loading">
691691+ <span class="sequoia-loading-spinner"></span>
692692+ Loading comments...
680693 </div>
681694 `;
682695 break;
683696684697 case "no-document":
685685- this.shadow.innerHTML = `
686686- ${styleTag}
687687- <div class="sequoia-comments-container">
688688- <div class="sequoia-warning">
689689- No document found. Add a <code><link rel="site.standard.document" href="at://..."></code> tag to your page.
690690- </div>
698698+ this.commentsContainer.innerHTML = `
699699+ <div class="sequoia-warning">
700700+ No document found. Add a <code><link rel="site.standard.document" href="at://..."></code> tag to your page.
691701 </div>
692702 `;
703703+ if (this.hide) {
704704+ this.commentsContainer.style.display = 'none';
705705+ }
693706 break;
694707695708 case "no-comments-enabled":
696696- this.shadow.innerHTML = `
697697- ${styleTag}
698698- <div class="sequoia-comments-container">
699699- <div class="sequoia-empty">
700700- Comments are not enabled for this post.
701701- </div>
709709+ this.commentsContainer.innerHTML = `
710710+ <div class="sequoia-empty">
711711+ Comments are not enabled for this post.
702712 </div>
703713 `;
704714 break;
705715706716 case "empty":
707707- this.shadow.innerHTML = `
708708- ${styleTag}
709709- <div class="sequoia-comments-container">
710710- <div class="sequoia-comments-header">
711711- <h3 class="sequoia-comments-title">Comments</h3>
712712- <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
713713- ${BLUESKY_ICON}
714714- Reply on Bluesky
715715- </a>
716716- </div>
717717- <div class="sequoia-empty">
718718- No comments yet. Be the first to reply on Bluesky!
719719- </div>
717717+ this.commentsContainer.innerHTML = `
718718+ <div class="sequoia-comments-header">
719719+ <h3 class="sequoia-comments-title">Comments</h3>
720720+ <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
721721+ ${BLUESKY_ICON}
722722+ Reply on Bluesky
723723+ </a>
724724+ </div>
725725+ <div class="sequoia-empty">
726726+ No comments yet. Be the first to reply on Bluesky!
720727 </div>
721728 `;
722729 break;
723730724731 case "error":
725725- this.shadow.innerHTML = `
726726- ${styleTag}
727727- <div class="sequoia-comments-container">
728728- <div class="sequoia-error">
729729- Failed to load comments: ${escapeHtml(this.state.message)}
730730- </div>
732732+ this.commentsContainer.innerHTML = `
733733+ <div class="sequoia-error">
734734+ Failed to load comments: ${escapeHtml(this.state.message)}
731735 </div>
732736 `;
733737 break;
···740744 .join("");
741745 const commentCount = this.countComments(replies);
742746743743- this.shadow.innerHTML = `
744744- ${styleTag}
745745- <div class="sequoia-comments-container">
746746- <div class="sequoia-comments-header">
747747- <h3 class="sequoia-comments-title">${commentCount} Comment${commentCount !== 1 ? "s" : ""}</h3>
748748- <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
749749- ${BLUESKY_ICON}
750750- Reply on Bluesky
751751- </a>
752752- </div>
753753- <div class="sequoia-comments-list">
754754- ${threadsHtml}
755755- </div>
747747+ this.commentsContainer.innerHTML = `
748748+ <div class="sequoia-comments-header">
749749+ <h3 class="sequoia-comments-title">${commentCount} Comment${commentCount !== 1 ? "s" : ""}</h3>
750750+ <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
751751+ ${BLUESKY_ICON}
752752+ Reply on Bluesky
753753+ </a>
754754+ </div>
755755+ <div class="sequoia-comments-list">
756756+ ${threadsHtml}
756757 </div>
757758 `;
758759 break;
+56-55
packages/cli/src/components/sequoia-comments.js
···1414 * Attributes:
1515 * - document-uri: AT Protocol URI for the document (optional if link tag exists)
1616 * - depth: Maximum depth of nested replies to fetch (default: 6)
1717+ * - hide: Set to "auto" to hide if no document link is detected
1718 *
1819 * CSS Custom Properties:
1920 * - --sequoia-fg-color: Text color (default: #1f2937)
···573574class SequoiaComments extends BaseElement {
574575 constructor() {
575576 super();
576576- this.shadow = this.attachShadow({ mode: "open" });
577577+ const shadow = this.attachShadow({ mode: "open" });
578578+579579+ const styleTag = document.createElement("style");
580580+ shadow.appendChild(styleTag);
581581+ styleTag.innerText = styles;
582582+583583+ const container = document.createElement("div");
584584+ shadow.appendChild(container);
585585+ container.className = "sequoia-comments-container";
586586+ container.part = "container";
587587+588588+ this.commentsContainer = container;
577589 this.state = { type: "loading" };
578590 this.abortController = null;
591591+579592 }
580593581594 static get observedAttributes() {
582582- return ["document-uri", "depth"];
595595+ return ["document-uri", "depth", "hide"];
583596 }
584597585598 connectedCallback() {
···614627 get depth() {
615628 const depthAttr = this.getAttribute("depth");
616629 return depthAttr ? parseInt(depthAttr, 10) : 6;
630630+ }
631631+632632+ get hide() {
633633+ const hideAttr = this.getAttribute("hide");
634634+ return hideAttr === "auto";
617635 }
618636619637 async loadComments() {
···666684 }
667685668686 render() {
669669- const styleTag = `<style>${styles}</style>`;
670670-671687 switch (this.state.type) {
672688 case "loading":
673673- this.shadow.innerHTML = `
674674- ${styleTag}
675675- <div class="sequoia-comments-container">
676676- <div class="sequoia-loading">
677677- <span class="sequoia-loading-spinner"></span>
678678- Loading comments...
679679- </div>
689689+ this.commentsContainer.innerHTML = `
690690+ <div class="sequoia-loading">
691691+ <span class="sequoia-loading-spinner"></span>
692692+ Loading comments...
680693 </div>
681694 `;
682695 break;
683696684697 case "no-document":
685685- this.shadow.innerHTML = `
686686- ${styleTag}
687687- <div class="sequoia-comments-container">
688688- <div class="sequoia-warning">
689689- No document found. Add a <code><link rel="site.standard.document" href="at://..."></code> tag to your page.
690690- </div>
698698+ this.commentsContainer.innerHTML = `
699699+ <div class="sequoia-warning">
700700+ No document found. Add a <code><link rel="site.standard.document" href="at://..."></code> tag to your page.
691701 </div>
692702 `;
703703+ if (this.hide) {
704704+ this.commentsContainer.style.display = 'none';
705705+ }
693706 break;
694707695708 case "no-comments-enabled":
696696- this.shadow.innerHTML = `
697697- ${styleTag}
698698- <div class="sequoia-comments-container">
699699- <div class="sequoia-empty">
700700- Comments are not enabled for this post.
701701- </div>
709709+ this.commentsContainer.innerHTML = `
710710+ <div class="sequoia-empty">
711711+ Comments are not enabled for this post.
702712 </div>
703713 `;
704714 break;
705715706716 case "empty":
707707- this.shadow.innerHTML = `
708708- ${styleTag}
709709- <div class="sequoia-comments-container">
710710- <div class="sequoia-comments-header">
711711- <h3 class="sequoia-comments-title">Comments</h3>
712712- <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
713713- ${BLUESKY_ICON}
714714- Reply on Bluesky
715715- </a>
716716- </div>
717717- <div class="sequoia-empty">
718718- No comments yet. Be the first to reply on Bluesky!
719719- </div>
717717+ this.commentsContainer.innerHTML = `
718718+ <div class="sequoia-comments-header">
719719+ <h3 class="sequoia-comments-title">Comments</h3>
720720+ <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
721721+ ${BLUESKY_ICON}
722722+ Reply on Bluesky
723723+ </a>
724724+ </div>
725725+ <div class="sequoia-empty">
726726+ No comments yet. Be the first to reply on Bluesky!
720727 </div>
721728 `;
722729 break;
723730724731 case "error":
725725- this.shadow.innerHTML = `
726726- ${styleTag}
727727- <div class="sequoia-comments-container">
728728- <div class="sequoia-error">
729729- Failed to load comments: ${escapeHtml(this.state.message)}
730730- </div>
732732+ this.commentsContainer.innerHTML = `
733733+ <div class="sequoia-error">
734734+ Failed to load comments: ${escapeHtml(this.state.message)}
731735 </div>
732736 `;
733737 break;
···740744 .join("");
741745 const commentCount = this.countComments(replies);
742746743743- this.shadow.innerHTML = `
744744- ${styleTag}
745745- <div class="sequoia-comments-container">
746746- <div class="sequoia-comments-header">
747747- <h3 class="sequoia-comments-title">${commentCount} Comment${commentCount !== 1 ? "s" : ""}</h3>
748748- <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
749749- ${BLUESKY_ICON}
750750- Reply on Bluesky
751751- </a>
752752- </div>
753753- <div class="sequoia-comments-list">
754754- ${threadsHtml}
755755- </div>
747747+ this.commentsContainer.innerHTML = `
748748+ <div class="sequoia-comments-header">
749749+ <h3 class="sequoia-comments-title">${commentCount} Comment${commentCount !== 1 ? "s" : ""}</h3>
750750+ <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button">
751751+ ${BLUESKY_ICON}
752752+ Reply on Bluesky
753753+ </a>
754754+ </div>
755755+ <div class="sequoia-comments-list">
756756+ ${threadsHtml}
756757 </div>
757758 `;
758759 break;