You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pinot.apache.org by xi...@apache.org on 2026/03/21 07:03:48 UTC

(pinot-site) branch new-site-dev updated: feat: make Terminal component interactive with click-through query examples (#163)

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

xiangfu pushed a commit to branch new-site-dev
in repository https://gitbox.apache.org/repos/asf/pinot-site.git


The following commit(s) were added to refs/heads/new-site-dev by this push:
     new 5bcbd654 feat: make Terminal component interactive with click-through query examples (#163)
5bcbd654 is described below

commit 5bcbd65475d0b220735472da96faba6cb5f9de2a
Author: Xiang Fu <xi...@gmail.com>
AuthorDate: Sat Mar 21 00:03:40 2026 -0700

    feat: make Terminal component interactive with click-through query examples (#163)
    
    Transform Terminal into an interactive multi-step component that guides users through
    the Pinot getting started journey:
    - Step 1: Start Pinot (Docker quickstart with x86/ARM64 tabs)
    - Step 2: Create Table (schema creation via curl)
    - Step 3: Query Data (sample SQL query on airlineStats)
    - Step 4: See Results (JSON response output)
    
    All steps maintain existing terminal styling (traffic light dots, Source_Code_Pro font,
    vine-100 accent border). Each tab is clickable and shows the step number and title.
    The copy button works for whichever step is currently active.
    
    Also updated TextCodeSplitSection to include subheading: 'From install to first query
    in under 5 minutes.' for better UX context.
    
    Co-authored-by: Claude Bot <bo...@example.com>
---
 components/Terminal.tsx             | 130 ++++++++++++++++++++++++++++--------
 components/TextCodeSplitSection.tsx |   5 +-
 2 files changed, 106 insertions(+), 29 deletions(-)

diff --git a/components/Terminal.tsx b/components/Terminal.tsx
index f5a5ec26..b3406608 100644
--- a/components/Terminal.tsx
+++ b/components/Terminal.tsx
@@ -2,33 +2,85 @@
 import React, { FC, useState } from 'react';
 import { Button } from './ui/button';
 
+interface Step {
+    id: string;
+    title: string;
+    content: string[];
+}
+
 const Terminal: FC = () => {
-    const [activeTab, setActiveTab] = useState<'x86' | 'ARM64'>('x86');
+    const [activeStep, setActiveStep] = useState<string>('step-1');
+    const [activeArch, setActiveArch] = useState<'x86' | 'ARM64'>('x86');
     const [copied, setCopied] = useState(false);
 
-    const commands = {
-        x86: [
-            'docker run -p 9000:9000 \\',
-            'apachepinot.docker.scarf.sh/apachepinot/pinot:1.4.0 \\',
-            'QuickStart -type hybrid'
-        ],
-        ARM64: [
-            'docker run -p 9000:9000 \\',
-            'apachepinot.docker.scarf.sh/apachepinot/pinot:1.4.0-arm64 \\',
-            'QuickStart -type hybrid'
-        ]
-    };
+    const steps: Step[] = [
+        {
+            id: 'step-1',
+            title: 'Start Pinot',
+            content: activeArch === 'x86'
+                ? [
+                    'docker run -p 9000:9000 \\',
+                    'apachepinot.docker.scarf.sh/apachepinot/pinot:1.4.0 \\',
+                    'QuickStart -type hybrid'
+                ]
+                : [
+                    'docker run -p 9000:9000 \\',
+                    'apachepinot.docker.scarf.sh/apachepinot/pinot:1.4.0-arm64 \\',
+                    'QuickStart -type hybrid'
+                ]
+        },
+        {
+            id: 'step-2',
+            title: 'Create Table',
+            content: [
+                'curl -X POST http://localhost:9000/schemas \\',
+                "  -H 'Content-Type: application/json' \\",
+                '  -d @examples/batch/airlineStats/airlineStats_schema.json'
+            ]
+        },
+        {
+            id: 'step-3',
+            title: 'Query Data',
+            content: [
+                'SELECT carrier, count(*) AS flights,',
+                '       avg(arrDelay) AS avg_delay',
+                'FROM airlineStats',
+                "WHERE destState = 'CA'",
+                'GROUP BY carrier',
+                'ORDER BY flights DESC',
+                'LIMIT 10;'
+            ]
+        },
+        {
+            id: 'step-4',
+            title: 'See Results',
+            content: [
+                '[',
+                '  {"carrier":"WN","flights":3214,"avg_delay":5.2},',
+                '  {"carrier":"UA","flights":2104,"avg_delay":8.7},',
+                '  {"carrier":"AA","flights":1893,"avg_delay":6.1}',
+                ']'
+            ]
+        }
+    ];
+
+    const currentStep = steps.find(s => s.id === activeStep) || steps[0];
 
     const handleCopy = async () => {
         try {
-            await navigator.clipboard.writeText(commands[activeTab].join('\n'));
+            const textToCopy = currentStep.content.join('\n');
+            await navigator.clipboard.writeText(textToCopy);
             setCopied(true);
-            setTimeout(() => setCopied(false), 2000); // Show copied status for 2 seconds
+            setTimeout(() => setCopied(false), 2000);
         } catch (err) {
             console.error('Failed to copy text: ', err);
         }
     };
 
+    const handleArchChange = (arch: 'x86' | 'ARM64') => {
+        setActiveArch(arch);
+    };
+
     const renderCommandWithNumbers = (commandLines: string[]) => {
         return commandLines.map((line, index) => (
             <div className="table-row" key={index}>
@@ -49,26 +101,48 @@ const Terminal: FC = () => {
                         <div className="h-3 w-3 rounded-full bg-green-500"></div>
                     </div>
                 </div>
-                {/* Tab buttons */}
-                <div className="mb-2 ml-8 flex space-x-1 border-b-2">
-                    {(['x86', 'ARM64'] as const).map((arch) => (
+
+                {/* Step tabs */}
+                <div className="mb-2 ml-8 flex flex-wrap space-x-1 border-b-2">
+                    {steps.map((step) => (
                         <button
-                            key={arch}
-                            className={`border-b-4 px-4 py-2
-                                        pt-5 font-[Source_Code_Pro]
+                            key={step.id}
+                            className={`border-b-4 px-4 py-2 pt-5 font-[Source_Code_Pro] text-sm transition-all
                             ${
-                                activeTab === arch
+                                activeStep === step.id
                                     ? 'border-rose-700 text-base font-semibold'
-                                    : 'border-transparent opacity-30'
+                                    : 'border-transparent opacity-30 hover:opacity-60'
                             }`}
-                            onClick={() => setActiveTab(arch)}
+                            onClick={() => setActiveStep(step.id)}
                         >
-                            {arch}
+                            {step.id.split('-')[1]}. {step.title}
                         </button>
                     ))}
                 </div>
-                <div className="table w-full whitespace-pre-wrap p-4 font-[Source_Code_Pro] leading-loose">
-                    {renderCommandWithNumbers(commands[activeTab])}
+
+                {/* Architecture selector - only shown for step 1 */}
+                {activeStep === 'step-1' && (
+                    <div className="ml-8 flex space-x-2 border-b border-gray-200 pb-2">
+                        {(['x86', 'ARM64'] as const).map((arch) => (
+                            <button
+                                key={arch}
+                                className={`px-3 py-1 text-xs font-[Source_Code_Pro] transition-colors
+                                ${
+                                    activeArch === arch
+                                        ? 'bg-vine-100 text-gray-900'
+                                        : 'bg-gray-200 text-gray-600 hover:bg-gray-300'
+                                }`}
+                                onClick={() => handleArchChange(arch)}
+                            >
+                                {arch}
+                            </button>
+                        ))}
+                    </div>
+                )}
+
+                {/* Command content */}
+                <div className="table w-full whitespace-pre-wrap p-4 font-[Source_Code_Pro] leading-loose text-gray-100">
+                    {renderCommandWithNumbers(currentStep.content)}
                 </div>
             </div>
 
@@ -85,4 +159,4 @@ const Terminal: FC = () => {
     );
 };
 
-export default Terminal;
+export default Terminal;
\ No newline at end of file
diff --git a/components/TextCodeSplitSection.tsx b/components/TextCodeSplitSection.tsx
index 46e0a95e..8c4ab443 100644
--- a/components/TextCodeSplitSection.tsx
+++ b/components/TextCodeSplitSection.tsx
@@ -20,6 +20,9 @@ const TextCodeSplitSection: React.FC<TextCodeSplitSectionProps> = ({ title }) =>
                         <h2 className=" text-[2rem] font-bold leading-10 text-gray-900 dark:text-white md:text-5xl md:leading-[4rem]">
                             {title}
                         </h2>
+                        <p className="mt-2 text-lg text-gray-600 dark:text-gray-300">
+                            From install to first query in under 5 minutes.
+                        </p>
                     </header>
                     <div className="flex justify-start pb-6">
                         <Button
@@ -41,4 +44,4 @@ const TextCodeSplitSection: React.FC<TextCodeSplitSectionProps> = ({ title }) =>
     );
 };
 
-export default TextCodeSplitSection;
+export default TextCodeSplitSection;
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org