UI Logo

Current UI

Tabs

A set of layered sections of content—known as tab panels—that are displayed one at a time.

Radix UI

Canon R6 Mark II Overview

Matching strong photo performance with apt video capabilities, the Canon EOS R6 Mark II is a versatile mirrorless body for the multimedia creator. An updated 24.2MP CMOS sensor pairs with updated processing for more improved AF, impressive 4K 60p 10-bit video, and faster overall performance. Also, the camera body has been updated for more intuitive handling, including a redesigned top plate for easier access to different shooting modes.

24.2MP Full-Frame Sensor and DIGIC X Processing

Hitting a sweet-spot in terms of resolution, the R6 Mark II incorporates a new 24.2MP CMOS sensor that's versatile for both photo and video applications, performs well in low-light conditions, and yields striking and accurate colors.

import { Tabs, TabsList, TabsTrigger, TabsContent } from '../ui/Tabs'

export default function TabsDemo() {
  return (
    <div>
      <Tabs defaultValue='description' className='rounded-lg py-1 max-w-[500px] lg:max-w-[1000px] lg:w-[500px]'>
        <TabsList aria-label='tabs example'>
          <TabsTrigger variant='underline' value='description'>
            Description
          </TabsTrigger>
          <TabsTrigger variant='underline' value='specifications'>
            Specifications
          </TabsTrigger>
          <TabsTrigger variant='underline' value='reviews'>
            Reviews
          </TabsTrigger>
        </TabsList>

        <TabsContent value='description'>
          <Description />
        </TabsContent>

        <TabsContent value='specifications'>
          <Specifications />
        </TabsContent>

        <TabsContent value='reviews'>
          <Reviews />
        </TabsContent>
      </Tabs>
    </div>
  )
}

export const Description = () => {
  return (
    <div className='flex flex-col gap-3 p-7'>
      <h2 className='text-base font-semibold'>Canon R6 Mark II Overview</h2>
      <p>
        Matching strong photo performance with apt video capabilities, the Canon
        EOS R6 Mark II is a versatile mirrorless body for the multimedia
        creator. An updated 24.2MP CMOS sensor pairs with updated processing for
        more improved AF, impressive 4K 60p 10-bit video, and faster overall
        performance. Also, the camera body has been updated for more intuitive
        handling, including a redesigned top plate for easier access to
        different shooting modes.
      </p>
      <h3 className='font-semibold'>
        24.2MP Full-Frame Sensor and DIGIC X Processing
      </h3>
      <p>
        Hitting a sweet-spot in terms of resolution, the R6 Mark II incorporates
        a new 24.2MP CMOS sensor that's versatile for both photo and video
        applications, performs well in low-light conditions, and yields striking
        and accurate colors.
      </p>
    </div>
  )
}

export const Specifications = () => {
  return (
    <div className='flex flex-col gap-3.5 p-7'>
      <h2 className='pb-2 text-base font-semibold'>Key Specs</h2>
      <div className='flex justify-between border-b py-1 gap-5'>
        <p className='font-semibold'>Lens Mount</p>
        <p className='text-right'>Canon RF</p>
      </div>
      <div className='flex justify-between border-b py-1 gap-5'>
        <p className='font-semibold'>Sensor Resolution</p>
        <p className='text-right'>Actual: 25.6 Megapixel</p>
      </div>
      <div className='flex justify-between border-b py-1 gap-5'>
        <p className='font-semibold'>Image Sensor</p>
        <p className='text-right'>35.9 x 23.9 mm Full-Frame CMOS</p>
      </div>
      <div className='flex justify-between border-b py-1 gap-5'>
        <p className='font-semibold'>Image Stabilization</p>
        <p className='text-right'>Sensor-Shift, 5-Axis</p>
      </div>
      <div className='flex justify-between border-b py-1 gap-5'>
        <p className='font-semibold'>ISO Sensitivity</p>
        <p className='text-right'>100 to 102,400 in Manual, Auto Mode</p>
      </div>
      <div className='flex justify-between border-b py-1 gap-5'>
        <p className='font-semibold'>External Recording Modes</p>
        <p className='text-right'>6144 x 4032 up to 59.94 fps</p>
      </div>
    </div>
  )
}

export const Reviews = () => {
  return (
    <div className='flex flex-col gap-3.5 p-7'>
      <h3 className='text-base font-bold'>Reviews (3)</h3>
      <div className='flex flex-col justify-between gap-2 border-b py-2'>
        <h4 className='font-semibold'>Excellent camera</h4>
        <div className='flex gap-3.5 text-xs'>
          <p className='font-semibold'>5.0</p>
          <span className='text-neutral-400'>|</span>
          <p className='text-neutral-500'>8/16/2023</p>
          <span className='text-neutral-400'>|</span>
          <p className='text-neutral-500'>Scott</p>
        </div>
        <p className='text-xs'>
          The R6 M2 is a worthy upgrade to my EOS R. The auto focus performance
          is a huge improvement -- the eye detect AF is superb.
        </p>
      </div>
      <div className='flex flex-col justify-between gap-2 border-b py-2'>
        <h4 className='font-semibold'>So far, so good.</h4>
        <div className='flex gap-3.5 text-xs'>
          <p className='font-semibold'>4.0</p>
          <span className='text-neutral-400'>|</span>
          <p className='text-neutral-500'>8/14/2023</p>
          <span className='text-neutral-400'>|</span>
          <p className='text-neutral-500'>Robert</p>
        </div>
        <p className='text-xs'>
          So far I am happy with this solution as a lower-cost back-up for my R5
          since the image quality is on par, I can configure it the same and it
          uses the same batteries.
        </p>
      </div>
      <div className='flex flex-col justify-between gap-2 border-b py-2'>
        <h4 className='font-semibold'>Great Camera That Does It All</h4>
        <div className='flex gap-3.5 text-xs'>
          <p className='font-semibold'>5.0</p>
          <span className='text-neutral-400'>|</span>
          <p className='text-neutral-500'>8/14/2023</p>
          <span className='text-neutral-400'>|</span>
          <p className='text-neutral-500'>Bob</p>
        </div>
        <p className='text-xs'>
          Super upgrade from my EOS 5D III. Haven't used a lot yet but so far I
          am very happy with this camera. Pleasantly surprised how bright the
          viewfinder looks.
        </p>
      </div>
    </div>
  )
}

Installation

Install the following dependencies:

npm install @radix-ui/react-tabs

Copy and paste the following code into your project.

'use client'

import * as React from 'react'
import * as TabsPrimitive from '@radix-ui/react-tabs'
import { cva, type VariantProps } from 'class-variance-authority'

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

const tabsTriggerVariants = cva(
  'inline-flex items-start justify-center whitespace-nowrap text-sm font-medium text-muted-foreground ring-offset-background',
  {
    variants: {
      variant: {
        underline:
          'px-5 py-2.5 data-[state=active]:border-b-2 data-[state=active]:border-foreground data-[state=active]:text-foreground',
        button:
          'my-2 ml-2 rounded-md px-4 py-2 data-[state=active]:bg-muted data-[state=active]:text-foreground',
      },
    },
    defaultVariants: {
      variant: 'underline',
    },
  }
)

const Tabs = React.forwardRef<
  React.ElementRef<typeof TabsPrimitive.Root>,
  React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>
>(({ className, ...props }, ref) => {
  return (
    <TabsPrimitive.Root
      ref={ref}
      className={cn('bg-primary-foreground', className)}
      {...props}
    />
  )
})

const TabsList = React.forwardRef<
  React.ElementRef<typeof TabsPrimitive.List>,
  React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => {
  return (
    <TabsPrimitive.List ref={ref} className={cn('border-b border-b-border', className)} {...props} />
  )
})

interface TabsTriggerProps
  extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>,
    VariantProps<typeof tabsTriggerVariants> {}

const TabsTrigger = React.forwardRef<
  React.ElementRef<typeof TabsPrimitive.Trigger>,
  TabsTriggerProps
>(({ variant, className, ...props }, ref) => {
  return (
    <TabsPrimitive.Trigger
      ref={ref}
      className={cn(tabsTriggerVariants({ variant, className }))}
      {...props}
    />
  )
})

const TabsContent = React.forwardRef<
  React.ElementRef<typeof TabsPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
>(({ className, children, ...props }, ref) => {
  return (
    <TabsPrimitive.Content
      ref={ref}
      className={cn('h-fit', className)}
      {...props}
    >
      {children}
    </TabsPrimitive.Content>
  )
})

export { Tabs, TabsList, TabsTrigger, TabsContent }

Update the import paths to match your project setup.

Anatomy

Import all parts and piece them together.

import { Tabs, TabsList, TabsTrigger, TabsContent } from '../ui/Tabs'
<Tabs defaultValue='tab1'>
  <TabsList>
    <TabsTrigger value='tab1'>Tab 1</TabsTrigger>
    <TabsTrigger value='tab2'>Tab 2</TabsTrigger>
  </TabsList>
  <TabsContent value='tab1'>Tab 1 Content</TabsContent>
  <TabsContent value='tab2'>Tab 2 Content</TabsContent>
</Tabs>