From 87466df3ae514e9454859c236b1d3264b8293c7f Mon Sep 17 00:00:00 2001 From: MykolaGolubyev Date: Mon, 6 Apr 2026 21:29:01 -0400 Subject: [PATCH 1/2] tabs: fix tab with code snippets regression --- ...ix-2026-04-06-tabs-switch-wrong-content.md | 1 + znai-docs/znai/snippets/file-name.js | 8 ++-- .../code-snippets/SimpleCodeSnippet.jsx | 48 ++++++------------- .../src/test/groovy/pages/DocContent.groovy | 4 ++ znai-tests/src/test/groovy/sampledoc/toc | 1 + .../test/groovy/scenarios/sampleDoc.groovy | 23 +++++++++ 6 files changed, 48 insertions(+), 37 deletions(-) create mode 100644 znai-docs/znai/release-notes/1.88/fix-2026-04-06-tabs-switch-wrong-content.md diff --git a/znai-docs/znai/release-notes/1.88/fix-2026-04-06-tabs-switch-wrong-content.md b/znai-docs/znai/release-notes/1.88/fix-2026-04-06-tabs-switch-wrong-content.md new file mode 100644 index 000000000..18004de38 --- /dev/null +++ b/znai-docs/znai/release-notes/1.88/fix-2026-04-06-tabs-switch-wrong-content.md @@ -0,0 +1 @@ +* Fix: Tab properly displays selected content (instead of previously selected content) \ No newline at end of file diff --git a/znai-docs/znai/snippets/file-name.js b/znai-docs/znai/snippets/file-name.js index baf15538d..a7ee6e8ea 100644 --- a/znai-docs/znai/snippets/file-name.js +++ b/znai-docs/znai/snippets/file-name.js @@ -1,7 +1,7 @@ class JsClass { - constructor() { - usefulAction() - } + constructor() { + usefulAction(); + } } -export default JsClass \ No newline at end of file +export default JsClass; diff --git a/znai-reactjs/src/doc-elements/code-snippets/SimpleCodeSnippet.jsx b/znai-reactjs/src/doc-elements/code-snippets/SimpleCodeSnippet.jsx index c5010559e..e5fc13661 100644 --- a/znai-reactjs/src/doc-elements/code-snippets/SimpleCodeSnippet.jsx +++ b/znai-reactjs/src/doc-elements/code-snippets/SimpleCodeSnippet.jsx @@ -38,34 +38,12 @@ class SimpleCodeSnippet extends React.Component { constructor(props) { super(props); - this.processProps(props); this.state = { clickedReadMore: false, hasHighlightedText: false, }; } - // handles changes during preview - componentDidUpdate(prevProps) { - // Only process props if they actually changed - if ( - prevProps.tokens !== this.props.tokens || - prevProps.linesOfCode !== this.props.linesOfCode || - prevProps.highlight !== this.props.highlight - ) { - this.processProps(this.props); - // If you need to update state based on props changes, you can do it here - // but be careful to avoid infinite loops - } - } - - processProps({ tokens, linesOfCode, highlight }) { - this.linesOfTokens = !linesOfCode ? splitTokensIntoLines(tokens) : linesOfCode; - - // highlight is either a single line index/substring or a collection of line indexes and substrings - this.highlight = convertToList(highlight); - } - componentDidMount() { addHighlightedTextListener(this); } @@ -99,14 +77,16 @@ class SimpleCodeSnippet extends React.Component { render() { this.hiddenLinesContainerRef = React.createRef(); const { clickedReadMore } = this.state; - const { wrap, isPresentation, slideIdx, references } = this.props; + const { wrap, isPresentation, slideIdx, references, tokens, linesOfCode, highlight } = this.props; // slideIdx === 0 means no highlights, 1 - first highlight, etc const highlightIsVisible = !isPresentation || slideIdx > 0; - const linesOfTokens = this.linesOfTokens; + const linesOfTokens = !linesOfCode ? splitTokensIntoLines(tokens) : linesOfCode; + const highlightList = convertToList(highlight); + const visibleLines = - this.limitLines(this.props) && !clickedReadMore && !isPresentation + this.limitLines(linesOfTokens, this.props) && !clickedReadMore && !isPresentation ? linesOfTokens.slice(0, this.readMoreVisibleLines(this.props)) : linesOfTokens; @@ -115,7 +95,7 @@ class SimpleCodeSnippet extends React.Component { const linesToRender = this.processLinesToRender(visibleLines); const mergedReferences = mergeWithGlobalDocReferences(references); - const isHighlightedByIdx = highlightIsVisible ? linesToRender.map((_, lineIdx) => this.isHighlighted(lineIdx)) : []; + const isHighlightedByIdx = highlightIsVisible ? linesToRender.map((_, lineIdx) => this.isHighlighted(highlightList, lineIdx)) : []; return (
@@ -157,9 +137,11 @@ class SimpleCodeSnippet extends React.Component {
 
   renderReadMore() {
     const { clickedReadMore } = this.state;
-    const { isPresentation } = this.props;
+    const { isPresentation, tokens, linesOfCode } = this.props;
+
+    const linesOfTokens = !linesOfCode ? splitTokensIntoLines(tokens) : linesOfCode;
 
-    if (isPresentation || !this.limitLines(this.props)) {
+    if (isPresentation || !this.limitLines(linesOfTokens, this.props)) {
       return null;
     }
 
@@ -208,20 +190,20 @@ class SimpleCodeSnippet extends React.Component {
     );
   };
 
-  limitLines(props) {
-    return this.linesOfTokens.length >= this.readMoreVisibleLines(props) && props.readMore;
+  limitLines(linesOfTokens, props) {
+    return linesOfTokens.length >= this.readMoreVisibleLines(props) && props.readMore;
   }
 
   readMoreVisibleLines(props) {
     return props.readMoreVisibleLines || 8;
   }
 
-  isHighlighted(lineIdx) {
+  isHighlighted(highlightList, lineIdx) {
     const { meta, isPresentation, slideIdx, revealLineStop } = this.props;
 
-    const highlightSliceIdx = calcHighlightSliceIdx(this.highlight);
+    const highlightSliceIdx = calcHighlightSliceIdx(highlightList);
 
-    const highlight = !isPresentation ? this.highlight : this.highlight.slice(0, highlightSliceIdx);
+    const highlight = !isPresentation ? highlightList : highlightList.slice(0, highlightSliceIdx);
 
     if (!highlight) {
       return false;
diff --git a/znai-tests/src/test/groovy/pages/DocContent.groovy b/znai-tests/src/test/groovy/pages/DocContent.groovy
index cba260ad0..41617f335 100644
--- a/znai-tests/src/test/groovy/pages/DocContent.groovy
+++ b/znai-tests/src/test/groovy/pages/DocContent.groovy
@@ -26,6 +26,10 @@ class DocContent {
     def mainPanelScrollTop = mainPanel.scrollTop
     def mermaidClickableNodes = $(".znai-mermaid .clickable")
 
+    def tabNames = $(".tabs-area .tab-name")
+    def activeTabName = $(".tabs-area .tab-name.active")
+    def tabsSnippet = $(".tabs-area .snippet")
+
     void clickMermaidNode() {
         // GeckoDriver can't click elements inside SVG (even HTML inside foreignObject),
         // use DOM .click() which creates a trusted event
diff --git a/znai-tests/src/test/groovy/sampledoc/toc b/znai-tests/src/test/groovy/sampledoc/toc
index 74b7a75df..82c3c4895 100644
--- a/znai-tests/src/test/groovy/sampledoc/toc
+++ b/znai-tests/src/test/groovy/sampledoc/toc
@@ -2,6 +2,7 @@ outside-chapter-file.md
 chapter-one
     links
     target
+    tabs
 chapter-two
     doxygen-from-zip
 chapter-three
diff --git a/znai-tests/src/test/groovy/scenarios/sampleDoc.groovy b/znai-tests/src/test/groovy/scenarios/sampleDoc.groovy
index 4ae784ead..c53444ab9 100644
--- a/znai-tests/src/test/groovy/scenarios/sampleDoc.groovy
+++ b/znai-tests/src/test/groovy/scenarios/sampleDoc.groovy
@@ -45,6 +45,29 @@ scenario("check redirect page") {
     docContent.title.waitToBe == "Links"
 }
 
+scenario("switch tabs and validate snippet content") {
+    def snippets = [
+            Java  : 'System.out.println("hello from java");',
+            Python: 'print("hello from python")',
+            Ruby  : 'puts "hello from ruby"',
+    ]
+
+    def assertActiveTab = { String name ->
+        docContent.activeTabName.waitTo == name
+        docContent.tabsSnippet.waitTo == snippets[name]
+    }
+
+    standardView.tocItems.get("Tabs").click()
+    docContent.title.waitTo == "Tabs"
+
+    assertActiveTab("Java")
+
+    ["Python", "Ruby", "Java"].each { name ->
+        docContent.tabNames.get(name).click()
+        assertActiveTab(name)
+    }
+}
+
 scenario("validate uploads files") {
     def baseUrl = "http://localhost:$port/preview"
 

From cbbc8d8c077982acdedf77ab17079559cb7a1268 Mon Sep 17 00:00:00 2001
From: MykolaGolubyev 
Date: Mon, 6 Apr 2026 21:40:31 -0400
Subject: [PATCH 2/2] tests: add missing tabs.md test fixture

---
 .../test/groovy/sampledoc/chapter-one/tabs.md | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)
 create mode 100644 znai-tests/src/test/groovy/sampledoc/chapter-one/tabs.md

diff --git a/znai-tests/src/test/groovy/sampledoc/chapter-one/tabs.md b/znai-tests/src/test/groovy/sampledoc/chapter-one/tabs.md
new file mode 100644
index 000000000..e5a50eae4
--- /dev/null
+++ b/znai-tests/src/test/groovy/sampledoc/chapter-one/tabs.md
@@ -0,0 +1,20 @@
+# Tabs Switching
+
+Tabs with code snippets for e2e testing of tab switching.
+
+````tabs
+Java:
+```java
+System.out.println("hello from java");
+```
+
+Python:
+```python
+print("hello from python")
+```
+
+Ruby:
+```ruby
+puts "hello from ruby"
+```
+````