Add IconButtonWithMenu component with label support
Add LearnMoreButton with some instruction on task modal
This commit is contained in:
commit
c8ac925146
4 changed files with 266 additions and 142 deletions
|
@ -1,9 +1,10 @@
|
||||||
import { Chip, Menu, MenuItem, Typography } from '@mui/joy'
|
import { Button, Chip, Menu, MenuItem, Typography } from '@mui/joy'
|
||||||
import IconButton from '@mui/joy/IconButton'
|
import IconButton from '@mui/joy/IconButton'
|
||||||
import React, { useEffect, useRef, useState } from 'react'
|
import React, { useEffect, useRef, useState } from 'react'
|
||||||
import { getTextColorFromBackgroundColor } from '../../utils/Colors.jsx'
|
import { getTextColorFromBackgroundColor } from '../../utils/Colors.jsx'
|
||||||
|
|
||||||
const IconButtonWithMenu = ({
|
const IconButtonWithMenu = ({
|
||||||
|
label,
|
||||||
key,
|
key,
|
||||||
icon,
|
icon,
|
||||||
options,
|
options,
|
||||||
|
@ -39,18 +40,36 @@ const IconButtonWithMenu = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<IconButton
|
{!label && (
|
||||||
onClick={handleMenuOpen}
|
<IconButton
|
||||||
variant='outlined'
|
onClick={handleMenuOpen}
|
||||||
color={isActive ? 'primary' : 'neutral'}
|
variant='outlined'
|
||||||
size='sm'
|
color={isActive ? 'primary' : 'neutral'}
|
||||||
sx={{
|
size='sm'
|
||||||
height: 24,
|
sx={{
|
||||||
borderRadius: 24,
|
height: 24,
|
||||||
}}
|
borderRadius: 24,
|
||||||
>
|
}}
|
||||||
{icon}
|
>
|
||||||
</IconButton>
|
{icon}
|
||||||
|
{label ? label : null}
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
{label && (
|
||||||
|
<Button
|
||||||
|
onClick={handleMenuOpen}
|
||||||
|
variant='outlined'
|
||||||
|
color={isActive ? 'primary' : 'neutral'}
|
||||||
|
size='sm'
|
||||||
|
startDecorator={icon}
|
||||||
|
sx={{
|
||||||
|
height: 24,
|
||||||
|
borderRadius: 24,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
<Menu
|
<Menu
|
||||||
key={key}
|
key={key}
|
||||||
|
|
|
@ -390,26 +390,25 @@ const MyChores = () => {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{activeTextField != 'task' && (
|
{activeTextField != 'task' && (
|
||||||
<Button
|
<IconButton
|
||||||
variant='outlined'
|
variant='outlined'
|
||||||
size='sm'
|
size='sm'
|
||||||
color='neutral'
|
color='neutral'
|
||||||
sx={{
|
sx={{
|
||||||
height: 24,
|
height: 24,
|
||||||
borderRadius: 24,
|
borderRadius: 24,
|
||||||
minWidth: 100,
|
// minWidth: 100,
|
||||||
}}
|
}}
|
||||||
startDecorator={<EditCalendar />}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActiveTextField('task')
|
setActiveTextField('task')
|
||||||
setTaskInputFocus(taskInputFocus + 1)
|
setTaskInputFocus(taskInputFocus + 1)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Task
|
<EditCalendar />
|
||||||
</Button>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
{activeTextField != 'search' && (
|
{activeTextField != 'search' && (
|
||||||
<Button
|
<IconButton
|
||||||
variant='outlined'
|
variant='outlined'
|
||||||
color='neutral'
|
color='neutral'
|
||||||
size='sm'
|
size='sm'
|
||||||
|
@ -417,7 +416,6 @@ const MyChores = () => {
|
||||||
height: 24,
|
height: 24,
|
||||||
borderRadius: 24,
|
borderRadius: 24,
|
||||||
}}
|
}}
|
||||||
startDecorator={<Search />}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActiveTextField('search')
|
setActiveTextField('search')
|
||||||
setSearchInputFocus(searchInputFocus + 1)
|
setSearchInputFocus(searchInputFocus + 1)
|
||||||
|
@ -429,119 +427,11 @@ const MyChores = () => {
|
||||||
searchInputRef.current.value?.length
|
searchInputRef.current.value?.length
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Search
|
<Search />
|
||||||
</Button>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
<Divider orientation='vertical' />
|
<Divider orientation='vertical' />
|
||||||
<IconButtonWithMenu
|
|
||||||
icon={<PriorityHigh />}
|
|
||||||
title='Filter by Priority'
|
|
||||||
options={Priorities}
|
|
||||||
selectedItem={selectedFilter}
|
|
||||||
onItemSelect={selected => {
|
|
||||||
handleLabelFiltering({ priority: selected.value })
|
|
||||||
}}
|
|
||||||
mouseClickHandler={handleMenuOutsideClick}
|
|
||||||
isActive={selectedFilter.startsWith('Priority: ')}
|
|
||||||
/>
|
|
||||||
<IconButtonWithMenu
|
|
||||||
icon={<Style />}
|
|
||||||
// TODO : this need simplification we want to display both user labels and chore labels
|
|
||||||
// that why we are merging them here.
|
|
||||||
// we also filter out the labels that user created as those will be part of user labels
|
|
||||||
title='Filter by Label'
|
|
||||||
options={[
|
|
||||||
...userLabels,
|
|
||||||
...chores
|
|
||||||
.map(c => c.labelsV2)
|
|
||||||
.flat()
|
|
||||||
.filter(l => l.created_by !== userProfile.id)
|
|
||||||
.map(l => {
|
|
||||||
// if user created it don't show it:
|
|
||||||
return {
|
|
||||||
...l,
|
|
||||||
name: l.name + ' (Shared Label)',
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
]}
|
|
||||||
selectedItem={selectedFilter}
|
|
||||||
onItemSelect={selected => {
|
|
||||||
handleLabelFiltering({ label: selected })
|
|
||||||
}}
|
|
||||||
isActive={selectedFilter.startsWith('Label: ')}
|
|
||||||
mouseClickHandler={handleMenuOutsideClick}
|
|
||||||
useChips
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
onClick={handleFilterMenuOpen}
|
|
||||||
variant='outlined'
|
|
||||||
color={
|
|
||||||
selectedFilter &&
|
|
||||||
FILTERS[selectedFilter] &&
|
|
||||||
selectedFilter != 'All'
|
|
||||||
? 'primary'
|
|
||||||
: 'neutral'
|
|
||||||
}
|
|
||||||
size='sm'
|
|
||||||
sx={{
|
|
||||||
height: 24,
|
|
||||||
borderRadius: 24,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FilterAlt />
|
|
||||||
</IconButton>
|
|
||||||
<List
|
|
||||||
orientation='horizontal'
|
|
||||||
wrap
|
|
||||||
sx={{
|
|
||||||
mt: 0.2,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Menu
|
|
||||||
ref={menuRef}
|
|
||||||
anchorEl={anchorEl}
|
|
||||||
open={Boolean(anchorEl)}
|
|
||||||
onClose={handleFilterMenuClose}
|
|
||||||
>
|
|
||||||
{Object.keys(FILTERS).map((filter, index) => (
|
|
||||||
<MenuItem
|
|
||||||
key={`filter-list-${filter}-${index}`}
|
|
||||||
onClick={() => {
|
|
||||||
const filterFunction = FILTERS[filter]
|
|
||||||
const filteredChores =
|
|
||||||
filterFunction.length === 2
|
|
||||||
? filterFunction(chores, userProfile.id)
|
|
||||||
: filterFunction(chores)
|
|
||||||
setFilteredChores(filteredChores)
|
|
||||||
setSelectedFilter(filter)
|
|
||||||
handleFilterMenuClose()
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{filter}
|
|
||||||
<Chip
|
|
||||||
color={selectedFilter === filter ? 'primary' : 'neutral'}
|
|
||||||
>
|
|
||||||
{FILTERS[filter].length === 2
|
|
||||||
? FILTERS[filter](chores, userProfile.id).length
|
|
||||||
: FILTERS[filter](chores).length}
|
|
||||||
</Chip>
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
{selectedFilter.startsWith('Label: ') ||
|
|
||||||
(selectedFilter.startsWith('Priority: ') && (
|
|
||||||
<MenuItem
|
|
||||||
key={`filter-list-cancel-all-filters`}
|
|
||||||
onClick={() => {
|
|
||||||
setFilteredChores(chores)
|
|
||||||
setSelectedFilter('All')
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cancel All Filters
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Menu>
|
|
||||||
</List>
|
|
||||||
<Divider orientation='vertical' />
|
|
||||||
<IconButtonWithMenu
|
<IconButtonWithMenu
|
||||||
title='Group by'
|
title='Group by'
|
||||||
icon={<Sort />}
|
icon={<Sort />}
|
||||||
|
@ -561,6 +451,113 @@ const MyChores = () => {
|
||||||
mouseClickHandler={handleMenuOutsideClick}
|
mouseClickHandler={handleMenuOutsideClick}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
{activeTextField === 'search' && (
|
||||||
|
<div className='flex gap-4'>
|
||||||
|
<div className='grid flex-1 grid-cols-3 gap-4'>
|
||||||
|
<IconButtonWithMenu
|
||||||
|
label={' Priority'}
|
||||||
|
key={'icon-menu-labels-filter'}
|
||||||
|
icon={<PriorityHigh />}
|
||||||
|
options={Priorities}
|
||||||
|
selectedItem={selectedFilter}
|
||||||
|
onItemSelect={selected => {
|
||||||
|
handleLabelFiltering({ priority: selected.value })
|
||||||
|
}}
|
||||||
|
mouseClickHandler={handleMenuOutsideClick}
|
||||||
|
isActive={selectedFilter.startsWith('Priority: ')}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<IconButtonWithMenu
|
||||||
|
key={'icon-menu-labels-filter'}
|
||||||
|
label={' Labels'}
|
||||||
|
icon={<Style />}
|
||||||
|
options={userLabels}
|
||||||
|
selectedItem={selectedFilter}
|
||||||
|
onItemSelect={selected => {
|
||||||
|
handleLabelFiltering({ label: selected })
|
||||||
|
}}
|
||||||
|
isActive={selectedFilter.startsWith('Label: ')}
|
||||||
|
mouseClickHandler={handleMenuOutsideClick}
|
||||||
|
useChips
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
onClick={handleFilterMenuOpen}
|
||||||
|
variant='outlined'
|
||||||
|
startDecorator={<FilterAlt />}
|
||||||
|
color={
|
||||||
|
selectedFilter &&
|
||||||
|
FILTERS[selectedFilter] &&
|
||||||
|
selectedFilter != 'All'
|
||||||
|
? 'primary'
|
||||||
|
: 'neutral'
|
||||||
|
}
|
||||||
|
size='sm'
|
||||||
|
sx={{
|
||||||
|
height: 24,
|
||||||
|
borderRadius: 24,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{' Other'}
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<List
|
||||||
|
orientation='horizontal'
|
||||||
|
wrap
|
||||||
|
sx={{
|
||||||
|
mt: 0.2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Menu
|
||||||
|
ref={menuRef}
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
open={Boolean(anchorEl)}
|
||||||
|
onClose={handleFilterMenuClose}
|
||||||
|
>
|
||||||
|
{Object.keys(FILTERS).map((filter, index) => (
|
||||||
|
<MenuItem
|
||||||
|
key={`filter-list-${filter}-${index}`}
|
||||||
|
onClick={() => {
|
||||||
|
const filterFunction = FILTERS[filter]
|
||||||
|
const filteredChores =
|
||||||
|
filterFunction.length === 2
|
||||||
|
? filterFunction(chores, userProfile.id)
|
||||||
|
: filterFunction(chores)
|
||||||
|
setFilteredChores(filteredChores)
|
||||||
|
setSelectedFilter(filter)
|
||||||
|
handleFilterMenuClose()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{filter}
|
||||||
|
<Chip
|
||||||
|
color={
|
||||||
|
selectedFilter === filter ? 'primary' : 'neutral'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{FILTERS[filter].length === 2
|
||||||
|
? FILTERS[filter](chores, userProfile.id).length
|
||||||
|
: FILTERS[filter](chores).length}
|
||||||
|
</Chip>
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{selectedFilter.startsWith('Label: ') ||
|
||||||
|
(selectedFilter.startsWith('Priority: ') && (
|
||||||
|
<MenuItem
|
||||||
|
key={`filter-list-cancel-all-filters`}
|
||||||
|
onClick={() => {
|
||||||
|
setFilteredChores(chores)
|
||||||
|
setSelectedFilter('All')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel All Filters
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Menu>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{selectedFilter !== 'All' && (
|
{selectedFilter !== 'All' && (
|
||||||
<Chip
|
<Chip
|
||||||
level='title-md'
|
level='title-md'
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { useNavigate } from 'react-router-dom'
|
||||||
import { CSSTransition } from 'react-transition-group'
|
import { CSSTransition } from 'react-transition-group'
|
||||||
import { UserContext } from '../../contexts/UserContext'
|
import { UserContext } from '../../contexts/UserContext'
|
||||||
import { CreateChore } from '../../utils/Fetcher'
|
import { CreateChore } from '../../utils/Fetcher'
|
||||||
|
import LearnMoreButton from './LearnMore'
|
||||||
const VALID_DAYS = {
|
const VALID_DAYS = {
|
||||||
monday: 'Monday',
|
monday: 'Monday',
|
||||||
mon: 'Monday',
|
mon: 'Monday',
|
||||||
|
@ -203,7 +204,7 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
{
|
{
|
||||||
frequencyType: 'days_of_the_week',
|
frequencyType: 'days_of_the_week',
|
||||||
regex: /every ([\w, ]+(?:day)?(?:, [\w, ]+(?:day)?)*)$/i,
|
regex: /every ([\w, ]+(?:day)?(?:, [\w, ]+(?:day)?)*)$/i,
|
||||||
name: 'Every {days} of the week',
|
name: 'Every {days}',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
frequencyType: 'day_of_the_month',
|
frequencyType: 'day_of_the_month',
|
||||||
|
@ -314,7 +315,6 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
const handleTextChange = e => {
|
const handleTextChange = e => {
|
||||||
if (!e.target.value) {
|
if (!e.target.value) {
|
||||||
setTaskText('')
|
setTaskText('')
|
||||||
setOpenModal(false)
|
|
||||||
setDueDate(null)
|
setDueDate(null)
|
||||||
setFrequency(null)
|
setFrequency(null)
|
||||||
setFrequencyHumanReadable(null)
|
setFrequencyHumanReadable(null)
|
||||||
|
@ -327,6 +327,13 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
if (priority.result) setPriority(priority.result)
|
if (priority.result) setPriority(priority.result)
|
||||||
cleanedSentence = priority.cleanedSentence
|
cleanedSentence = priority.cleanedSentence
|
||||||
|
|
||||||
|
const repeat = parseRepeatV2(cleanedSentence)
|
||||||
|
if (repeat.result) {
|
||||||
|
setFrequency(repeat.result)
|
||||||
|
setFrequencyHumanReadable(repeat.name)
|
||||||
|
cleanedSentence = repeat.cleanedSentence
|
||||||
|
}
|
||||||
|
|
||||||
const parsedDueDate = chrono.parse(cleanedSentence, new Date(), {
|
const parsedDueDate = chrono.parse(cleanedSentence, new Date(), {
|
||||||
forwardDate: true,
|
forwardDate: true,
|
||||||
})
|
})
|
||||||
|
@ -337,13 +344,6 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
cleanedSentence = cleanedSentence.replace(parsedDueDate[0].text, '')
|
cleanedSentence = cleanedSentence.replace(parsedDueDate[0].text, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
const repeat = parseRepeatV2(cleanedSentence)
|
|
||||||
if (repeat.result) {
|
|
||||||
setFrequency(repeat.result)
|
|
||||||
setFrequencyHumanReadable(repeat.name)
|
|
||||||
cleanedSentence = repeat.cleanedSentence
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priority.result || parsedDueDate[0]?.index > -1 || repeat.result) {
|
if (priority.result || parsedDueDate[0]?.index > -1 || repeat.result) {
|
||||||
setOpenModal(true)
|
setOpenModal(true)
|
||||||
}
|
}
|
||||||
|
@ -425,7 +425,7 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
</Button> */}
|
</Button> */}
|
||||||
<Typography level='h4'>Create new task</Typography>
|
<Typography level='h4'>Create new task</Typography>
|
||||||
<Chip startDecorator='🚧' variant='soft' color='warning' size='sm'>
|
<Chip startDecorator='🚧' variant='soft' color='warning' size='sm'>
|
||||||
Experimental
|
Experimental Feature
|
||||||
</Chip>
|
</Chip>
|
||||||
<Box>
|
<Box>
|
||||||
<Typography level='body-sm'>Task in a sentence:</Typography>
|
<Typography level='body-sm'>Task in a sentence:</Typography>
|
||||||
|
@ -438,13 +438,54 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
placeholder='Type your full text here...'
|
placeholder='Type your full text here...'
|
||||||
sx={{ width: '100%', fontSize: '16px' }}
|
sx={{ width: '100%', fontSize: '16px' }}
|
||||||
/>
|
/>
|
||||||
|
<LearnMoreButton
|
||||||
|
content={
|
||||||
|
<>
|
||||||
|
<Typography level='body-sm' sx={{ mb: 1 }}>
|
||||||
|
This feature lets you create a task simply by typing a
|
||||||
|
sentence. It attempt parses the sentence to identify the
|
||||||
|
task's due date, priority, and frequency.
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Typography
|
||||||
|
level='body-sm'
|
||||||
|
sx={{ fontWeight: 'bold', mt: 2 }}
|
||||||
|
>
|
||||||
|
Examples:
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Typography
|
||||||
|
level='body-sm'
|
||||||
|
component='ul'
|
||||||
|
sx={{ pl: 2, mt: 1, listStyle: 'disc' }}
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<strong>Priority:</strong>For highest priority any of the
|
||||||
|
following keyword <em>P1</em>, <em>Urgent</em>,{' '}
|
||||||
|
<em>Important</em>, or <em>ASAP</em>. For lower
|
||||||
|
priorities, use <em>P2</em>, <em>P3</em>, or <em>P4</em>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Due date:</strong> Specify dates with phrases like{' '}
|
||||||
|
<em>tomorrow</em>, <em>next week</em>, <em>Monday</em>, or{' '}
|
||||||
|
<em>August 1st at 12pm</em>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Frequency:</strong> Set recurring tasks with terms
|
||||||
|
like <em>daily</em>, <em>weekly</em>, <em>monthly</em>,{' '}
|
||||||
|
<em>yearly</em>, or patterns such as{' '}
|
||||||
|
<em>every Tuesday and Thursday</em>.
|
||||||
|
</li>
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
<Typography level='body-sm'>Title:</Typography>
|
<Typography level='body-sm'>Title:</Typography>
|
||||||
<Input
|
<Input
|
||||||
value={taskTitle}
|
value={taskTitle}
|
||||||
onChange={e => setTaskTitle(e.target.value)}
|
onChange={e => setTaskTitle(e.target.value)}
|
||||||
placeholder='Type your full text here...'
|
|
||||||
sx={{ width: '100%', fontSize: '16px' }}
|
sx={{ width: '100%', fontSize: '16px' }}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
67
src/views/components/LearnMore.jsx
Normal file
67
src/views/components/LearnMore.jsx
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import { Info } from '@mui/icons-material'
|
||||||
|
import { Box, Button, Sheet } from '@mui/joy'
|
||||||
|
import React, { useRef, useState } from 'react'
|
||||||
|
|
||||||
|
const LearnMoreButton = ({ content }) => {
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
const anchorRef = useRef(null)
|
||||||
|
|
||||||
|
const handleToggle = () => {
|
||||||
|
setOpen(prev => !prev)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClickOutside = event => {
|
||||||
|
if (anchorRef.current && !anchorRef.current.contains(event.target)) {
|
||||||
|
setOpen(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (open) {
|
||||||
|
document.addEventListener('mousedown', handleClickOutside)
|
||||||
|
} else {
|
||||||
|
document.removeEventListener('mousedown', handleClickOutside)
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('mousedown', handleClickOutside)
|
||||||
|
}
|
||||||
|
}, [open])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ position: 'relative', display: 'inline-block' }}>
|
||||||
|
<Button
|
||||||
|
ref={anchorRef}
|
||||||
|
variant='plain'
|
||||||
|
startDecorator={<Info />}
|
||||||
|
size='sm'
|
||||||
|
color='primary'
|
||||||
|
onClick={handleToggle}
|
||||||
|
>
|
||||||
|
Learn More
|
||||||
|
</Button>
|
||||||
|
{open && (
|
||||||
|
<Sheet
|
||||||
|
variant='outlined'
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: '100%',
|
||||||
|
left: 0,
|
||||||
|
mt: 1,
|
||||||
|
zIndex: 1000,
|
||||||
|
p: 2,
|
||||||
|
borderRadius: 'sm',
|
||||||
|
boxShadow: 'md',
|
||||||
|
backgroundColor: 'background.surface',
|
||||||
|
minWidth: 240,
|
||||||
|
maxHeight: 260,
|
||||||
|
overflowY: 'auto',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
</Sheet>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LearnMoreButton
|
Loading…
Add table
Reference in a new issue