HelpLogin
© 2022-2025 Spice AI, Inc.
SQL Query ReferenceDocsFAQSupport
PrivacyTerms
Status
Home
Datasets
Models
trunk
Edit on GitHub
Fork
/docs/website/src/components/molecules/install-options/install-options.tsx
1'use client'
2
3import clsx from 'clsx'
4import { useEffect, useRef, useState } from 'react'
5
6import { CopyCode } from '../copy-code/copy-code'
7import { Button } from '../../atoms/button/button'
8import { Icon } from '../../atoms/icon/icon'
9
10let allTabs = [
11 {
12 id: 'mac',
13 name: 'mac OS',
14 command: 'curl https://install.spiceai.org | /bin/bash'
15 },
16 {
17 id: 'linux',
18 name: 'Linux',
19 command: 'curl -o install.sh https://install.spiceai.org'
20 },
21 {
22 id: 'windows',
23 name: 'Windows',
24 command: 'iex ((New-Object System.Net.WebClient).DownloadString("https://install.spiceai.org/Install.ps1"))'
25 }
26]
27
28export const InstallOptions = () => {
29 const tabsRef = useRef<(HTMLElement | null)[]>([])
30 const [activeTabIndex, setActiveTabIndex] = useState<number | null>(0)
31 const [tabUnderlineWidth, setTabUnderlineWidth] = useState(0)
32 const [tabUnderlineLeft, setTabUnderlineLeft] = useState(0)
33
34 useEffect(() => {
35 if (activeTabIndex === null) {
36 return
37 }
38
39 const setTabPosition = () => {
40 const currentTab = tabsRef.current[activeTabIndex] as HTMLElement
41 setTabUnderlineLeft(currentTab?.offsetLeft ?? 8)
42 setTabUnderlineWidth(currentTab?.clientWidth ?? 126)
43 }
44
45 setTabPosition()
46 }, [activeTabIndex])
47
48 return (
49 <div className='pt-14'>
50 <div className='flew-row relative mx-auto grid h-12 grid-cols-3 gap-2 px-2 backdrop-blur-sm md:flex'>
51 <span
52 className={clsx(
53 'absolute bottom-0 top-0 -z-10 rounded-lg bg-alpha-100 px-4 py-3 transition-all duration-300',
54 tabUnderlineLeft === 0 ? 'opacity-0' : 'opacity-100'
55 )}
56 style={{ left: tabUnderlineLeft, width: tabUnderlineWidth }}
57 />
58 {allTabs.map((tab, index) => {
59 const isActive = activeTabIndex === index
60
61 return (
62 <Button
63 key={index}
64 variant='tag'
65 ref={(el) => {
66 tabsRef.current[index] = el
67 }}
68 className={clsx(
69 'relative bottom-1 flex items-center justify-center gap-2 md:bottom-0 md:active:bg-alpha-50',
70 isActive && 'hover:bg-transparent'
71 )}
72 onClick={() => setActiveTabIndex(index)}
73 aria-label={`Go to tab ${index + 1}`}
74 >
75 <>
76 {index === 0 && <Icon iconName='apple' className='h-7 w-7' />}
77 {index === 1 && <Icon iconName='linux' className='h-6 w-6' />}
78 {index === 2 && <Icon iconName='windows' className='h-6 w-6' />}
79
80 <span className='hidden md:block'>{tab.name}</span>
81 </>
82 </Button>
83 )
84 })}
85 </div>
86 {activeTabIndex !== null && <CopyCode code={allTabs[activeTabIndex].command} />}
87 </div>
88 )
89}
90
1'use client'
2
3import clsx from 'clsx'
4import { useEffect, useRef, useState } from 'react'
5
6import { CopyCode } from '../copy-code/copy-code'
7import { Button } from '../../atoms/button/button'
8import { Icon } from '../../atoms/icon/icon'
9
10let allTabs = [
11 {
12 id: 'mac',
13 name: 'mac OS',
14 command: 'curl https://install.spiceai.org | /bin/bash'
15 },
16 {
17 id: 'linux',
18 name: 'Linux',
19 command: 'curl -o install.sh https://install.spiceai.org'
20 },
21 {
22 id: 'windows',
23 name: 'Windows',
24 command: 'iex ((New-Object System.Net.WebClient).DownloadString("https://install.spiceai.org/Install.ps1"))'
25 }
26]
27
28export const InstallOptions = () => {
29 const tabsRef = useRef<(HTMLElement | null)[]>([])
30 const [activeTabIndex, setActiveTabIndex] = useState<number | null>(0)
31 const [tabUnderlineWidth, setTabUnderlineWidth] = useState(0)
32 const [tabUnderlineLeft, setTabUnderlineLeft] = useState(0)
33
34 useEffect(() => {
35 if (activeTabIndex === null) {
36 return
37 }
38
39 const setTabPosition = () => {
40 const currentTab = tabsRef.current[activeTabIndex] as HTMLElement
41 setTabUnderlineLeft(currentTab?.offsetLeft ?? 8)
42 setTabUnderlineWidth(currentTab?.clientWidth ?? 126)
43 }
44
45 setTabPosition()
46 }, [activeTabIndex])
47
48 return (
49 <div className='pt-14'>
50 <div className='flew-row relative mx-auto grid h-12 grid-cols-3 gap-2 px-2 backdrop-blur-sm md:flex'>
51 <span
52 className={clsx(
53 'absolute bottom-0 top-0 -z-10 rounded-lg bg-alpha-100 px-4 py-3 transition-all duration-300',
54 tabUnderlineLeft === 0 ? 'opacity-0' : 'opacity-100'
55 )}
56 style={{ left: tabUnderlineLeft, width: tabUnderlineWidth }}
57 />
58 {allTabs.map((tab, index) => {
59 const isActive = activeTabIndex === index
60
61 return (
62 <Button
63 key={index}
64 variant='tag'
65 ref={(el) => {
66 tabsRef.current[index] = el
67 }}
68 className={clsx(
69 'relative bottom-1 flex items-center justify-center gap-2 md:bottom-0 md:active:bg-alpha-50',
70 isActive && 'hover:bg-transparent'
71 )}
72 onClick={() => setActiveTabIndex(index)}
73 aria-label={`Go to tab ${index + 1}`}
74 >
75 <>
76 {index === 0 && <Icon iconName='apple' className='h-7 w-7' />}
77 {index === 1 && <Icon iconName='linux' className='h-6 w-6' />}
78 {index === 2 && <Icon iconName='windows' className='h-6 w-6' />}
79
80 <span className='hidden md:block'>{tab.name}</span>
81 </>
82 </Button>
83 )
84 })}
85 </div>
86 {activeTabIndex !== null && <CopyCode code={allTabs[activeTabIndex].command} />}
87 </div>
88 )
89}
90