Skip to content

Commit

Permalink
feat(ui): add a banner to the page in demo mode (#2058)
Browse files Browse the repository at this point in the history
* feat(ui): add banner to the page in demo mode

* fix

* [autofix.ci] apply automated fixes

* update

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Meng Zhang <[email protected]>
  • Loading branch information
3 people authored May 6, 2024
1 parent c63e3fe commit 4b54d34
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 27 deletions.
25 changes: 25 additions & 0 deletions ee/tabby-ui/app/(dashboard)/components/main-content.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use client'

import { ScrollArea } from '@/components/ui/scroll-area'
import { BANNER_HEIGHT, useShowDemoBanner } from '@/components/demo-banner'
import { Header } from '@/components/header'

export default function MainContent({
children
}: {
children: React.ReactNode
}) {
const [isShowDemoBanner] = useShowDemoBanner()
const style = isShowDemoBanner
? { height: `calc(100vh - ${BANNER_HEIGHT})` }
: { height: '100vh' }
return (
<>
{/* Wraps right hand side into ScrollArea, making scroll bar consistent across all browsers */}
<ScrollArea className={'flex flex-1 flex-col'} style={style}>
<Header />
<div className="flex-1 p-4 lg:p-10">{children}</div>
</ScrollArea>
</>
)
}
13 changes: 10 additions & 3 deletions ee/tabby-ui/app/(dashboard)/components/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {
IconLightingBolt,
IconUser
} from '@/components/ui/icons'
import { ScrollArea } from '@/components/ui/scroll-area'
import { BANNER_HEIGHT, useShowDemoBanner } from '@/components/demo-banner'

export interface SidebarProps {
children?: React.ReactNode
Expand All @@ -30,12 +32,17 @@ export interface SidebarProps {

export default function Sidebar({ children, className }: SidebarProps) {
const [{ data }] = useMe()
const [isShowDemoBanner] = useShowDemoBanner()
const isAdmin = data?.me.isAdmin
const style = isShowDemoBanner
? { height: `calc(100vh - ${BANNER_HEIGHT})` }
: { height: '100vh' }
return (
<div
<ScrollArea
className={cn('grid overflow-hidden md:grid-cols-[280px_1fr]', className)}
style={style}
>
<div className="fixed inset-y-0 left-0 hidden w-[280px] border-r pt-4 md:block">
<div className="hidden w-[280px] border-r pt-4 md:block">
<nav className="flex h-full flex-col overflow-hidden text-sm font-medium">
<Link href="/" className="flex justify-center pb-4">
<Image
Expand Down Expand Up @@ -108,7 +115,7 @@ export default function Sidebar({ children, className }: SidebarProps) {
</div>
</nav>
</div>
</div>
</ScrollArea>
)
}

Expand Down
19 changes: 6 additions & 13 deletions ee/tabby-ui/app/(dashboard)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { Metadata } from 'next'

import { ScrollArea } from '@/components/ui/scroll-area'
import { Header } from '@/components/header'

import MainContent from './components/main-content'
import Sidebar from './components/sidebar'

export const metadata: Metadata = {
Expand All @@ -12,20 +10,15 @@ export const metadata: Metadata = {
}
}

interface DashboardLayoutProps {
export default function RootLayout({
children
}: {
children: React.ReactNode
}

export default function RootLayout({ children }: DashboardLayoutProps) {
}) {
return (
<main className="flex flex-1">
<Sidebar />

{/* Wraps right hand side into ScrollArea, making scroll bar consistent across all browsers */}
<ScrollArea className="flex h-[100vh] flex-1 flex-col">
<Header />
<div className="flex-1 p-4 lg:p-10">{children}</div>
</ScrollArea>
<MainContent>{children}</MainContent>
</main>
)
}
6 changes: 5 additions & 1 deletion ee/tabby-ui/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import '@/app/globals.css'

import { fontMono, fontSans } from '@/lib/fonts'
import { cn } from '@/lib/utils'
import { DemoBanner } from '@/components/demo-banner'
import { Providers } from '@/components/providers'
import { TailwindIndicator } from '@/components/tailwind-indicator'

Expand Down Expand Up @@ -37,7 +38,10 @@ export default function RootLayout({ children }: RootLayoutProps) {
)}
>
<Providers attribute="class" defaultTheme="system" enableSystem>
<div className="flex min-h-screen flex-col">{children}</div>
<div className="flex min-h-screen flex-col">
<DemoBanner />
{children}
</div>
<Toaster richColors closeButton />
<TailwindIndicator />
</Providers>
Expand Down
96 changes: 96 additions & 0 deletions ee/tabby-ui/components/demo-banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
'use client'

import { useEffect, useState } from 'react'
import { isNil } from 'lodash-es'
import { useTheme } from 'next-themes'
import useSWRImmutable from 'swr/immutable'

import { useIsDemoMode } from '@/lib/hooks/use-server-info'
import { cn } from '@/lib/utils'
import {
IconClose,
IconGitFork,
IconGithub,
IconStar
} from '@/components/ui/icons'

export const BANNER_HEIGHT = '3.5rem'

export function useShowDemoBanner(): [boolean, (isShow: boolean) => void] {
const isDemoMode = useIsDemoMode()
const [isShow, setIsShow] = useState(false)

useEffect(() => {
if (!isNil(isDemoMode)) {
setIsShow(isDemoMode)
}
}, [isDemoMode])

return [isShow, setIsShow]
}

export function DemoBanner() {
const [isShow, setIsShow] = useShowDemoBanner()
const [slackIconFill, setSlackIconFill] = useState('')
const { theme } = useTheme()
const { data } = useSWRImmutable(
'https://api.github.com/repos/TabbyML/tabby',
(url: string) => fetch(url).then(res => res.json())
)

useEffect(() => {
setSlackIconFill(theme === 'dark' ? '#171615' : '#ECECEC')
}, [isShow, theme])

const style = isShow ? { height: BANNER_HEIGHT } : { height: 0 }
return (
<div
className={cn(
'flex items-center justify-between bg-primary px-4 text-primary-foreground transition-all md:px-5',
{
'opacity-100 pointer-events-auto': isShow,
'opacity-0 pointer-events-none': !isShow
}
)}
style={style}
>
<a
href="https://links.tabbyml.com/schedule-a-demo"
target="_blank"
className="flex items-center gap-x-2 text-xs font-semibold underline md:text-sm"
>
<span>📆</span>
<span>Book a 30-minute product demo.</span>
</a>

<div className="flex items-center gap-x-4 md:gap-x-8">
<a
href="https://github.com/TabbyML/tabby"
target="_blank"
className="flex items-center transition-all hover:opacity-70"
>
<IconGithub />
<div className="ml-2 hidden md:block">
<p className="text-xs font-semibold">TabbyML/tabby</p>
<div
className={cn('flex items-center text-xs transition-all', {
'h-4 opacity-70': data,
'h-0 opacity-0': !data
})}
>
<IconStar className="mr-1 h-2.5 w-2.5" />
<span>{data?.stargazers_count}</span>
<IconGitFork className="ml-2 mr-1 h-2.5 w-2.5" />
<span>{data?.forks_count}</span>
</div>
</div>
</a>

<IconClose
className="cursor-pointer transition-all hover:opacity-70"
onClick={() => setIsShow(false)}
/>
</div>
</div>
)
}
36 changes: 26 additions & 10 deletions ee/tabby-ui/components/ui/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import * as React from 'react'
// FIXME(wwayne): Review each icons and consider re-export from `lucide-react`.
import { BookOpenText, ChevronsDownUp, Mail } from 'lucide-react'
import { BookOpenText, ChevronsDownUp, GitFork, Mail, Star } from 'lucide-react'

import { cn } from '@/lib/utils'

Expand Down Expand Up @@ -561,44 +561,44 @@ function IconSlack({ className, ...props }: React.ComponentProps<'svg'>) {
<g>
<g>
<path
style={{ fill: '#E01E5A' }}
style={{ fill: props.fill || '#E01E5A' }}
d="M99.4,151.2c0,7.1-5.8,12.9-12.9,12.9c-7.1,0-12.9-5.8-12.9-12.9c0-7.1,5.8-12.9,12.9-12.9h12.9V151.2z"
/>
<path
style={{ fill: '#E01E5A' }}
style={{ fill: props.fill || '#E01E5A' }}
d="M105.9,151.2c0-7.1,5.8-12.9,12.9-12.9s12.9,5.8,12.9,12.9v32.3c0,7.1-5.8,12.9-12.9,12.9
s-12.9-5.8-12.9-12.9V151.2z"
/>
</g>
<g>
<path
style={{ fill: '#36C5F0' }}
style={{ fill: props.fill || '#36C5F0' }}
d="M118.8,99.4c-7.1,0-12.9-5.8-12.9-12.9c0-7.1,5.8-12.9,12.9-12.9s12.9,5.8,12.9,12.9v12.9H118.8z"
/>
<path
style={{ fill: '#36C5F0' }}
style={{ fill: props.fill || '#36C5F0' }}
d="M118.8,105.9c7.1,0,12.9,5.8,12.9,12.9s-5.8,12.9-12.9,12.9H86.5c-7.1,0-12.9-5.8-12.9-12.9
s5.8-12.9,12.9-12.9H118.8z"
/>
</g>
<g>
<path
style={{ fill: '#2EB67D' }}
style={{ fill: props.fill || '#2EB67D' }}
d="M170.6,118.8c0-7.1,5.8-12.9,12.9-12.9c7.1,0,12.9,5.8,12.9,12.9s-5.8,12.9-12.9,12.9h-12.9V118.8z"
/>
<path
style={{ fill: '#2EB67D' }}
style={{ fill: props.fill || '#2EB67D' }}
d="M164.1,118.8c0,7.1-5.8,12.9-12.9,12.9c-7.1,0-12.9-5.8-12.9-12.9V86.5c0-7.1,5.8-12.9,12.9-12.9
c7.1,0,12.9,5.8,12.9,12.9V118.8z"
/>
</g>
<g>
<path
style={{ fill: '#ECB22E' }}
style={{ fill: props.fill || '#ECB22E' }}
d="M151.2,170.6c7.1,0,12.9,5.8,12.9,12.9c0,7.1-5.8,12.9-12.9,12.9c-7.1,0-12.9-5.8-12.9-12.9v-12.9H151.2z"
/>
<path
style={{ fill: '#ECB22E' }}
style={{ fill: props.fill || '#ECB22E' }}
d="M151.2,164.1c-7.1,0-12.9-5.8-12.9-12.9c0-7.1,5.8-12.9,12.9-12.9h32.3c7.1,0,12.9,5.8,12.9,12.9
c0,7.1-5.8,12.9-12.9,12.9H151.2z"
/>
Expand Down Expand Up @@ -1400,6 +1400,20 @@ function IconChevronsDownUp({
)
}

const IconStar = ({
className,
...props
}: React.ComponentProps<typeof Star>) => (
<Star className={cn('h4 w-4', className)} {...props} />
)

const IconGitFork = ({
className,
...props
}: React.ComponentProps<typeof GitFork>) => (
<GitFork className={cn('h4 w-4', className)} {...props} />
)

export {
IconEdit,
IconNextChat,
Expand Down Expand Up @@ -1471,5 +1485,7 @@ export {
IconActivity,
IconBookOpenText,
IconMail,
IconChevronsDownUp
IconChevronsDownUp,
IconStar,
IconGitFork
}

0 comments on commit 4b54d34

Please sign in to comment.