This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch fix/CAMEL-23934
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 4bf8ac86477279f3cb55dd58a4dc5919f4940e63
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Jul 8 15:03:29 2026 +0200

    CAMEL-23934: Theme-aware markdown styles, metrics panel, and tab key 
shortcuts
    
    - Add Theme.markdownStyles() for theme-aware MarkdownView heading/code/link
      colors and apply to all 5 MarkdownView usages (Help, AI, CVE, Endpoints, 
Doc)
    - Wrap MetricsTab empty state in bordered panel for visual consistency
    - Style tab bar key shortcuts (1-9, 0) with Theme.hintKey() so they stand 
out
      on light theme — primaryTabHeader now returns styled Span[] instead of 
String
    - Use Theme.hintKey() for More dropdown mnemonic keys
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../apache/camel/dsl/jbang/core/commands/tui/AiPanel.java   |  1 +
 .../camel/dsl/jbang/core/commands/tui/CamelMonitor.java     |  2 +-
 .../camel/dsl/jbang/core/commands/tui/CveAuditTab.java      |  1 +
 .../camel/dsl/jbang/core/commands/tui/DocViewerPopup.java   |  1 +
 .../camel/dsl/jbang/core/commands/tui/EndpointsTab.java     |  3 +++
 .../camel/dsl/jbang/core/commands/tui/HelpOverlay.java      |  1 +
 .../camel/dsl/jbang/core/commands/tui/MetricsTab.java       | 12 +++++++++---
 .../camel/dsl/jbang/core/commands/tui/PopupManager.java     |  2 +-
 .../org/apache/camel/dsl/jbang/core/commands/tui/Theme.java | 13 +++++++++++++
 .../apache/camel/dsl/jbang/core/commands/tui/TuiIcons.java  |  8 ++++++--
 .../camel/dsl/jbang/core/commands/tui/TabBarRenderTest.java | 10 ++++++----
 11 files changed, 43 insertions(+), 11 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/AiPanel.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/AiPanel.java
index ca82ea8274a5..6f24b8b1df65 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/AiPanel.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/AiPanel.java
@@ -585,6 +585,7 @@ class AiPanel {
         MarkdownView view = MarkdownView.builder()
                 .source(source)
                 .scroll(scroll)
+                .styles(Theme.markdownStyles())
                 .build();
         frame.renderWidget(view, contentArea);
 
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
index eb883ae17d27..37114e80abfb 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
@@ -1263,7 +1263,7 @@ public class CamelMonitor extends CamelCommand {
             // Infra mode: only Overview and Log tabs
             Line[] labels = {
                     Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_OVERVIEW, 
"1", "Overview")),
-                    Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_LOG, "2", 
"Log")),
+                    Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_LOG, "2", 
"Log"))
             };
 
             // Map real tab index to infra tab index for highlight
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
index 5da22a93da9c..201bbaac1b4d 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
@@ -307,6 +307,7 @@ class CveAuditTab extends AbstractTableTab {
                         .source(md.toString())
                         .scroll(detailScroll)
                         
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL).title(title).build())
+                        .styles(Theme.markdownStyles())
                         .build(),
                 area);
     }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DocViewerPopup.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DocViewerPopup.java
index ba52a1763926..c0db7d7a22dc 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DocViewerPopup.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DocViewerPopup.java
@@ -433,6 +433,7 @@ class DocViewerPopup {
                     .source(docContent)
                     .scroll(docScroll)
                     .block(block)
+                    .styles(Theme.markdownStyles())
                     .build();
             frame.renderWidget(view, popup);
         }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/EndpointsTab.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/EndpointsTab.java
index 63f8125da84c..866ce7fff829 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/EndpointsTab.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/EndpointsTab.java
@@ -699,6 +699,7 @@ class EndpointsTab extends AbstractTableTab {
                             .source("*Select an endpoint*")
                             
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
                                     .title(" Endpoint Detail ").build())
+                            .styles(Theme.markdownStyles())
                             .build(),
                     area);
             return;
@@ -713,6 +714,7 @@ class EndpointsTab extends AbstractTableTab {
                             .source("*No endpoint URI*")
                             
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
                                     .title(" Endpoint Detail ").build())
+                            .styles(Theme.markdownStyles())
                             .build(),
                     area);
             return;
@@ -812,6 +814,7 @@ class EndpointsTab extends AbstractTableTab {
                         .scroll(detailScroll)
                         
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
                                 .title(title).build())
+                        .styles(Theme.markdownStyles())
                         .build(),
                 area);
     }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HelpOverlay.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HelpOverlay.java
index fa96d14819e8..2e1dcafaf377 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HelpOverlay.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HelpOverlay.java
@@ -103,6 +103,7 @@ class HelpOverlay {
                 .source(markdown)
                 .scroll(scroll)
                 .block(block)
+                .styles(Theme.markdownStyles())
                 .build();
         frame.renderWidget(view, popup);
     }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/MetricsTab.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/MetricsTab.java
index dd5f8ddfc9e3..580f1c3b93bd 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/MetricsTab.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/MetricsTab.java
@@ -227,9 +227,15 @@ class MetricsTab extends AbstractTableTab {
     @Override
     protected void renderContent(Frame frame, Rect area, IntegrationInfo info) 
{
         if (info.meters.isEmpty()) {
-            Paragraph p = Paragraph.from(Line.from(
-                    Span.styled("No metrics available. Run with --observe to 
enable micrometer.", LABEL)));
-            frame.renderWidget(p, area);
+            frame.renderWidget(
+                    Paragraph.builder()
+                            .text(Text.from(Line.from(
+                                    Span.styled("  No metrics available. Run 
with --observe to enable micrometer.",
+                                            LABEL))))
+                            
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
+                                    .title(" Metrics ").build())
+                            .build(),
+                    area);
             return;
         }
 
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/PopupManager.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/PopupManager.java
index c65df93f072e..8fd96eab495a 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/PopupManager.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/PopupManager.java
@@ -409,7 +409,7 @@ class PopupManager {
 
         frame.renderWidget(Clear.INSTANCE, popup);
 
-        Style keyStyle = Theme.label().bold();
+        Style keyStyle = Theme.hintKey();
         ListItem[] items = morePopupItems(keyStyle);
         ListWidget list = ListWidget.builder()
                 .items(items)
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java
index 08fbe9d892a9..2952d7b3c31c 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java
@@ -244,6 +244,19 @@ public final class Theme {
         return style("search-match", FALLBACK_SEARCH_MATCH);
     }
 
+    /** Theme-aware markdown styles for MarkdownView headings and other 
elements. */
+    public static dev.tamboui.markdown.MarkdownStyles markdownStyles() {
+        return dev.tamboui.markdown.MarkdownStyles.builder()
+                .heading(1, label().bold())
+                .heading(2, label().bold())
+                .heading(3, label().bold())
+                .inlineCode(Style.EMPTY.fg(accent()))
+                .codeBlock(muted())
+                .listMarker(Style.EMPTY.fg(accent()))
+                .link(Style.EMPTY.fg(accent()).underlined())
+                .build();
+    }
+
     /** Diagram box-drawing border color. */
     public static synchronized Color diagramBorder() {
         return color("diagram-border", FALLBACK_DIAGRAM_BORDER);
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiIcons.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiIcons.java
index 9d524eef2624..c719a4221e7e 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiIcons.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiIcons.java
@@ -172,8 +172,12 @@ final class TuiIcons {
      * Primary tab bar label of the form {@code "<icon>  <key> <name>"} with 
two spaces between the emoji and the key
      * digit so the two do not visually collide. Rendered without outer 
padding (compact) for every tab.
      */
-    static String primaryTabHeader(String icon, String key, String name) {
-        return icon + "  " + key + " " + name;
+    static dev.tamboui.text.Span[] primaryTabHeader(String icon, String key, 
String name) {
+        return new dev.tamboui.text.Span[] {
+                dev.tamboui.text.Span.raw(icon + "  "),
+                dev.tamboui.text.Span.styled(key, Theme.hintKey()),
+                dev.tamboui.text.Span.raw(" " + name)
+        };
     }
 
     /** Removes the {@value #MNEMONIC_MARKER} mnemonic marker from a label for 
display. */
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/TabBarRenderTest.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/TabBarRenderTest.java
index 7fa84d60afac..9f149007bae8 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/TabBarRenderTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/TabBarRenderTest.java
@@ -35,7 +35,9 @@ class TabBarRenderTest {
     void primaryTabHeadersStartWithIconAndTwoSpaces() {
         String[] names = { "Overview", "Log", "Diagram", "Route", "Endpoint", 
"HTTP", "Health", "Inspect", "Errors" };
         for (int i = 0; i < names.length; i++) {
-            String header = 
TuiIcons.primaryTabHeader(TuiIcons.PRIMARY_TAB_ICONS.get(i), String.valueOf(i + 
1), names[i]);
+            String header
+                    = 
Line.from(TuiIcons.primaryTabHeader(TuiIcons.PRIMARY_TAB_ICONS.get(i), 
String.valueOf(i + 1), names[i]))
+                            .rawContent();
             assertTrue(header.startsWith(TuiIcons.PRIMARY_TAB_ICONS.get(i) + " 
 " + (i + 1)),
                     "Tab header should be '<icon>  <key> <name>': " + header);
         }
@@ -43,7 +45,7 @@ class TabBarRenderTest {
 
     @Test
     void moreTabHeaderIncludesIconAndChevron() {
-        String header = TuiIcons.primaryTabHeader(TuiIcons.TAB_MORE, "0", 
TuiIcons.moreTabLabel());
+        String header = Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_MORE, 
"0", TuiIcons.moreTabLabel())).rawContent();
         assertTrue(header.startsWith(TuiIcons.TAB_MORE));
         assertTrue(header.contains(TuiIcons.MORE_CHEVRON));
     }
@@ -51,8 +53,8 @@ class TabBarRenderTest {
     @Test
     void routeAndTopLabelsHaveEqualWidth() {
         // toggling Top mode must not shift the tab bar
-        int route = 
CharWidth.of(TuiIcons.primaryTabHeader(TuiIcons.TAB_ROUTES, "4", "Route"));
-        int top = CharWidth.of(TuiIcons.primaryTabHeader(TuiIcons.TAB_ROUTES, 
"4", " Top "));
+        int route = Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_ROUTES, 
"4", "Route")).width();
+        int top = Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_ROUTES, 
"4", " Top ")).width();
         assertEquals(route, top, "Route and Top tab cells must be the same 
width");
     }
 

Reply via email to