Skip to content

Add Floating Tabs in Large Popup Page #23

@ThePyProgrammer

Description

@ThePyProgrammer

For now, the webview only needs to render the following "Tabs" internally:

  • Chat
  • Settings

v0 has kindly given me some (probably broken) code for this, as follows:

import React, { useState, useRef, useEffect } from 'react'
import { Tabs, Tab, styled, Typography, Box } from '@mui/material'
import { Home, Favorite, Settings } from '@mui/icons-material'
import { motion, AnimatePresence } from 'framer-motion'

const StyledTabs = styled(Tabs)({
  position: 'fixed',
  top: 20,
  right: 20,
  backgroundColor: 'rgba(156, 39, 176, 0.1)',
  borderRadius: 20,
  minHeight: 'unset',
  padding: 4,
  '& .MuiTabs-indicator': {
    display: 'none',
  },
})

const StyledTab = styled(Tab)(({ theme }) => ({
  minWidth: 'unset',
  minHeight: 'unset',
  padding: theme.spacing(1),
  borderRadius: '50%',
  zIndex: 1,
}))

const IconWrapper = styled(motion.div)({
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  width: 24,
  height: 24,
})

const SelectionBackground = styled(motion.div)({
  width: 40,
  height: 40,
  borderRadius: '50%',
  backgroundColor: '#9c27b0',
  position: 'absolute',
  zIndex: 0,
})

const TabView = () => {
  const [value, setValue] = useState(0)
  const tabRefs = useRef<(HTMLButtonElement | null)[]>([])
  const [selectionPosition, setSelectionPosition] = useState({ left: 0, top: 0 })

  const tabContent = [
    { icon: <Home />, label: 'Home', content: 'Welcome to the Home tab!' },
    { icon: <Favorite />, label: 'Favorites', content: 'Here are your favorite items.' },
    { icon: <Settings />, label: 'Settings', content: 'Adjust your settings here.' },
  ]

  const handleChange = (event: React.SyntheticEvent, newValue: number) => {
    if (newValue >= 0 && newValue < tabContent.length) {
      setValue(newValue)
      updateSelectionPosition(newValue)
    }
  }

  const updateSelectionPosition = (index: number) => {
    const currentTab = tabRefs.current[index]
    if (currentTab) {
      const { offsetLeft, offsetTop } = currentTab
      setSelectionPosition({ left: offsetLeft, top: offsetTop })
    }
  }

  useEffect(() => {
    updateSelectionPosition(0)
  }, [])

  return (
    <>
      <StyledTabs value={value} onChange={handleChange} aria-label="icon tabs example">
        <SelectionBackground
          initial={false}
          animate={{
            left: selectionPosition.left,
            top: selectionPosition.top,
          }}
          transition={{ type: 'spring', stiffness: 300, damping: 30 }}
        />
        {tabContent.map((tab, index) => (
          <StyledTab
            key={index}
            icon={
              <IconWrapper>
                <AnimatePresence mode="wait" initial={false}>
                  <motion.div
                    key={index}
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    exit={{ opacity: 0 }}
                    transition={{ duration: 0.2 }}
                  >
                    {React.cloneElement(tab.icon, {
                      style: { color: value === index ? '#ffffff' : 'rgba(156, 39, 176, 0.7)' },
                    })}
                  </motion.div>
                </AnimatePresence>
              </IconWrapper>
            }
            aria-label={tab.label}
            ref={(el) => (tabRefs.current[index] = el)}
          />
        ))}
      </StyledTabs>
      <Box p={3} mt={10}>
        {tabContent[value] && (
          <>
            <Typography variant="h4" gutterBottom>
              {tabContent[value].label}
            </Typography>
            <Typography variant="body1">
              {tabContent[value].content}
            </Typography>
          </>
        )}
      </Box>
    </>
  )
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureA (major) new feature to add

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions