@mui/icons-material#ExpandLess TypeScript Examples
The following examples show how to use
@mui/icons-material#ExpandLess.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: GroupFilter.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 6 votes |
export default function GroupFilter(props: Props) {
const {
state,
name,
position,
updateFilterValue,
update,
} = props;
const [open, setOpen] = React.useState(false);
const handleClick = () => {
setOpen(!open);
};
return (
<>
<ListItemButton onClick={handleClick}>
<ListItemText primary={name} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open}>
<List disablePadding>
<Options
sourceFilter={state}
group={position}
updateFilterValue={updateFilterValue}
update={update}
/>
</List>
</Collapse>
</>
);
}
Example #2
Source File: ExpandableListItem.tsx From frontend with MIT License | 6 votes |
ExpandableListItem = ({ header, content }: Props) => {
const [open, setOpen] = useState(false)
return (
<List
sx={{
my: 0,
mx: { xs: 0, md: 3 },
cursor: 'pointer',
}}>
<Paper elevation={1} sx={{ borderRadius: 2 }}>
<Box
sx={{ display: 'flex', alignItems: 'center', px: 3, py: 1 }}
onClick={() => setOpen(!open)}>
<ListItemText
primary={header}
primaryTypographyProps={{
variant: 'subtitle1',
color: `${withAccentColor(open)}`,
}}
/>
{open ? (
<ExpandLess sx={{ color: `${withAccentColor(open)}` }} />
) : (
<ExpandMore sx={{ color: `${withAccentColor(open)}` }} />
)}
</Box>
<Collapse in={open}>
<List>
<Box sx={{ pl: { xs: 3, md: 6 }, pb: 2, pr: 2 }}>{content}</Box>
</List>
</Collapse>
</Paper>
</List>
)
}
Example #3
Source File: SortFilter.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 5 votes |
export default function SortFilter(props: Props) {
const {
values,
name,
state,
position,
group,
updateFilterValue,
update,
} = props;
const [val, setval] = React.useState(state);
const [open, setOpen] = React.useState(false);
const handleClick = () => {
setOpen(!open);
};
if (values) {
const handleChange = (event:
React.MouseEvent<HTMLDivElement, MouseEvent>, index: number) => {
const tmp = val;
if (tmp.index === index) {
tmp.ascending = !tmp.ascending;
} else {
tmp.ascending = true;
}
tmp.index = index;
setval(tmp);
const upd = update.filter((e: {
position: number; group: number | undefined;
}) => !(position === e.position && group === e.group));
updateFilterValue([...upd, { position, state: JSON.stringify(tmp), group }]);
};
const ret = (
<FormControl fullWidth>
<ListItemButton onClick={handleClick}>
<ListItemText primary={name} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open}>
<List>
{values.map((value: string, index: number) => {
let icon;
if (val.index === index) {
icon = val.ascending ? (<ArrowUpwardIcon color="primary" />)
: (<ArrowDownwardIcon color="primary" />);
}
return (
<ListItem disablePadding key={`${name} ${value}`}>
<ListItemButton
onClick={(event) => handleChange(event, index)}
>
<ListItemIcon>
{icon}
</ListItemIcon>
<ListItemText primary={value} />
</ListItemButton>
</ListItem>
);
})}
</List>
</Collapse>
</FormControl>
);
return (
<Box key={name} sx={{ display: 'flex', flexDirection: 'column', minWidth: 120 }}>
{ret}
</Box>
);
}
return (<></>);
}
Example #4
Source File: AnonymousForm.tsx From frontend with MIT License | 5 votes |
export default function AnonymousForm() {
const [field] = useField('anonymousDonation')
const { t } = useTranslation('one-time-donation')
return (
<>
<CircleCheckboxField
label={
<Typography
fontSize={16}
display="inline-flex"
alignItems="center"
component="span"
color="#343434"
fontWeight="bold">
{t('anonymous-menu.checkbox-label')}
{field.value ? <ExpandLess /> : <ExpandMore />}
</Typography>
}
name="anonymousDonation"
/>
<Collapse in={field.value} timeout="auto" unmountOnExit>
<Grid container columnSpacing={3} rowSpacing={3}>
<Grid item xs={12} color="#343434" sx={{ opacity: 0.9 }}>
<Typography>{t('anonymous-menu.info-start')}</Typography>
</Grid>
<Grid item xs={12} md={6}>
<FormTextField
name="personsFirstName"
type="text"
label={t('anonymous-menu.firstName')}
fullWidth
/>
</Grid>
<Grid item xs={12} md={6}>
<FormTextField
name="personsLastName"
type="text"
label={t('anonymous-menu.lastName')}
fullWidth
/>
</Grid>
<Grid item xs={12} md={6}>
<FormTextField name="personsEmail" type="text" label="Email" fullWidth />
</Grid>
<Grid item xs={12} md={6}>
<FormTextField
name="personsPhone"
type="text"
label={t('anonymous-menu.phone')}
fullWidth
/>
</Grid>
<Grid item xs={12} color="GrayText">
<Typography>* {t('anonymous-menu.info-end')}</Typography>
</Grid>
</Grid>
</Collapse>
</>
)
}
Example #5
Source File: WidgetsSidebar.tsx From fluttertemplates.dev with MIT License | 4 votes |
function SingleSubGroupRenderer(props: SingleSubGroupRendererProps) {
const theme = useTheme();
const [expanded, setExpanded] = useState(false);
const [isSelected, setIsSelected] = useState(false);
const handleChange = () => {
setExpanded(!expanded);
};
useEffect(() => {
setExpanded(props.selectedSubGroup?.id === props.subgroup.id);
setIsSelected(props.selectedSubGroup?.id === props.subgroup.id);
}, [props.selectedSubGroup]);
return (
<>
<Grid
container
style={{
borderRadius: `0 1rem 1rem 0`,
backgroundColor: isSelected
? `${theme.palette.secondary.main}10`
: "",
}}
>
<Box sx={{ flexGrow: 1 }}>
<Link
href={`/widgets/${props.subgroup.id}`}
replace
key={`sub_group_${props.subgroup.id}`}
>
<a>
<ListItem
button
style={{
borderRadius: "0 1rem 1rem 0",
}}
>
<Typography
variant="body2"
style={{
color: isSelected ? theme.palette.secondary.main : "",
}}
>
{props.subgroup.title}
</Typography>
</ListItem>
</a>
</Link>
</Box>
<Grid item>
<IconButton onClick={() => handleChange()}>
{expanded ? <ExpandLess /> : <ExpandMore />}
</IconButton>
</Grid>
</Grid>
<AnimatePresence initial={false}>
{expanded && (
<motion.section
key="content"
initial="collapsed"
animate="open"
exit="collapsed"
variants={{
open: { opacity: 1, height: "auto" },
collapsed: { opacity: 0, height: 0 },
}}
>
<div
style={{
marginLeft: "1rem",
borderRadius: "0 0 1rem 1rem",
}}
>
{props.subgroup.widgets.map((widget, index) => (
<Link
href={
isSelected
? `#${widget.id.split("/").slice(-1)[0]}`
: `/widgets/${props.subgroup.id}#${
widget.id.split("/").slice(-1)[0]
}`
}
replace={!isSelected}
scroll={true}
key={`sub_group_${props.subgroup.id}_widget_${index}`}
>
<a>
<ListItem
button
style={{
borderRadius: "1rem",
}}
>
<Typography variant="body2">
{index + 1}. {widget.title}
</Typography>
</ListItem>
</a>
</Link>
))}
</div>
</motion.section>
)}
</AnimatePresence>
</>
);
}
Example #6
Source File: Config.tsx From NekoMaid with MIT License | 4 votes |
configs.push({
title: lang.config.serverConfig,
component () {
const plugin = usePlugin()
const globalData = useGlobalData()
const [flag, update] = useState(0)
const [info, setInfo] = useState<Record<string, string>>({ })
const [open, setOpen] = useState(false)
const [canGetData, setCanGetData] = useState(true)
const [loading, setLoading] = useState(false)
const setValue = (field: string, value: any, isGlobal = true) => {
plugin.emit('server:set', field, value)
success()
if (isGlobal) {
(globalData as any)[field] = value
update(flag + 1)
location.reload()
}
}
const createEditButtom = (field: string, isGlobal?: boolean, isInt = true) => <IconButton
onClick={() => dialog(
{
content: lang.inputValue,
input: isInt
? {
error: true,
type: 'number',
helperText: lang.invalidValue,
validator: (it: string) => /^\d+$/.test(it) && +it >= 0
}
: { }
}).then(res => res != null && setValue(field, isInt ? parseInt(res as any) : (res || null), isGlobal))}
><Edit /></IconButton>
const infoElm: JSX.Element[] = []
for (const key in info) {
const name = (lang.config as any)[key]
infoElm.push(<ListItem key={key} sx={{ pl: 4 }}>
<ListItemText
primary={key === 'isAikarFlags' ? <Link href='https://mcflags.emc.gs' target='_blank' rel='noopener'>{name}</Link> : name}
secondary={info[key].toString()}
/>
</ListItem>)
}
return <List>
<CircularLoading loading={loading} />
<ListItem secondaryAction={globalData.canSetMaxPlayers
? createEditButtom('maxPlayers')
: undefined}>
<ListItemText primary={lang.config.maxPlayers + ': ' + globalData.maxPlayers} />
</ListItem>
<ListItem secondaryAction={createEditButtom('spawnRadius')}>
<ListItemText primary={lang.config.spawnRadius + ': ' + globalData.spawnRadius} />
</ListItem>
<ListItem secondaryAction={createEditButtom('motd', false, false)}>
<ListItemText primary={lang.config.motd} />
</ListItem>
<ListItem secondaryAction={<Switch checked={globalData.hasWhitelist} onChange={e => setValue('hasWhitelist', e.target.checked)} />}>
<ListItemText primary={lang.config.whitelist} />
</ListItem>
{canGetData && <>
<ListItemButton onClick={() => {
if (infoElm.length) setOpen(!open)
else {
setLoading(true)
plugin.emit('server:fetchInfo', (data: any) => {
setLoading(false)
if (!data) {
failed(lang.unsupported)
setCanGetData(false)
return
}
setInfo(data)
setOpen(true)
})
}
}}>
<ListItemIcon><Equalizer /></ListItemIcon>
<ListItemText primary={lang.info} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open} timeout='auto' unmountOnExit>
<List component='div' dense disablePadding>{infoElm}</List>
</Collapse>
</>}
</List>
}
},
{
title: lang.history,
component () {
const [cur, update] = useState(0)
const list: ServerRecord[] = JSON.parse(localStorage.getItem('NekoMaid:servers') || '[]')
return <List>
{list.sort((a, b) => b.time - a.time).map(it => {
const i = it.address.indexOf('?')
return <ListItem
disablePadding
key={it.address}
secondaryAction={<IconButton edge='end' size='small' onClick={() => {
localStorage.setItem('NekoMaid:servers', JSON.stringify(list.filter(s => s.address !== it.address)))
success()
update(cur + 1)
}}><Delete /></IconButton>}
>
<ListItemButton onClick={() => {
location.hash = ''
location.search = it.address
}} dense>
<ListItemAvatar><Avatar src={it.icon} variant='rounded'><HelpOutline /></Avatar></ListItemAvatar>
<ListItemText primary={<Tooltip title={it.address.slice(i + 1)}>
<span>{it.address.slice(0, i)}</span></Tooltip>} secondary={dayjs(it.time).fromNow()} />
</ListItemButton>
</ListItem>
})}
</List>
}
},
{
title: lang.config.theme,
component () {
const color = localStorage.getItem('NekoMaid:color') || 'blue'
return <CardContent sx={{ textAlign: 'center' }}>
<Box>
<ToggleButtonGroup exclusive value={localStorage.getItem('NekoMaid:colorMode') || ''} onChange={(_, it) => {
localStorage.setItem('NekoMaid:colorMode', it)
location.reload()
}}>
<ToggleButton value='light'><Brightness7 /> {lang.config.light}</ToggleButton>
<ToggleButton value=''><SettingsBrightness /> {lang.config.system}</ToggleButton>
<ToggleButton value='dark'><Brightness4 /> {lang.config.dark}</ToggleButton>
</ToggleButtonGroup>
</Box>
<Paper sx={{ marginTop: 2, width: '176px', overflow: 'hidden', display: 'inline-block' }}>
{Object.keys(colors).slice(1, 17).map((key, i) => {
const checked = color === key
const elm = <Box
key={key}
onClick={() => {
localStorage.setItem('NekoMaid:color', key)
location.reload()
}}
sx={{
backgroundColor: (colors as any)[key][600],
width: '44px',
height: '44px',
display: 'inline-block',
cursor: 'pointer'
}}
><Check htmlColor='white' sx={{ top: '10px', position: 'relative', opacity: checked ? 1 : 0 }} /></Box>
return (i + 1) % 4 === 0 ? <React.Fragment key={key}>{elm}<br /></React.Fragment> : elm
})}
</Paper>
</CardContent>
}
})
Example #7
Source File: PlayerList.tsx From NekoMaid with MIT License | 4 votes |
PlayerInfo: React.FC<{ name?: string }> = React.memo(({ name }) => {
const plugin = usePlugin()
const globalData = useGlobalData()
const [open, setOpen] = useState(false)
const [info, setInfo] = useState<IPlayerInfo | undefined>()
const refresh = () => plugin.emit('playerList:query', setInfo, name)
useEffect(() => {
setInfo(undefined)
if (name) refresh()
}, [name])
return name && info
? <>
<Divider />
<List
sx={{ width: '100%' }}
component='nav'
subheader={<ListSubheader component='div' sx={{ backgroundColor: 'inherit' }}>{lang.playerList.details}</ListSubheader>}
>
<ListItem>
<ListItemIcon><AssignmentInd /></ListItemIcon>
<ListItemText primary={globalData.onlineMode
? <Link underline='hover' rel='noopener' target='_blank' href={'https://namemc.com/profile/' + info.id}>{info.id}</Link>
: info.id
} />
</ListItem>
{!info.hasPlayedBefore && <ListItem>
<ListItemIcon><ErrorOutline color='error' /></ListItemIcon>
<ListItemText primary={lang.playerList.hasNotPlayed} />
</ListItem>}
{info.ban != null && <ListItem>
<ListItemIcon><Block color='error' /></ListItemIcon>
<ListItemText primary={lang.playerList.banned + (info.ban ? ': ' + info.ban : '')} />
</ListItem>}
{info.whitelisted && <ListItem>
<ListItemIcon><Star color='warning' /></ListItemIcon>
<ListItemText primary={lang.playerList.whitelisted} />
</ListItem>}
{info.isOP && <ListItem>
<ListItemIcon><Security color='primary' /></ListItemIcon>
<ListItemText primary={lang.playerList.op} />
</ListItem>}
{info.hasPlayedBefore && <>
<ListItemButton onClick={() => setOpen(!open)}>
<ListItemIcon><Equalizer /></ListItemIcon>
<ListItemText primary={minecraft['gui.stats']} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component='div' dense disablePadding>
{[
minecraft['stat.minecraft.play_time'] + ': ' + dayjs.duration(info.playTime / 20, 'seconds').humanize(),
lang.playerList.firstPlay + ': ' + dayjs(info.firstPlay).fromNow(),
lang.playerList.lastPlay + ': ' + dayjs(info.lastOnline).fromNow(),
minecraft['stat.minecraft.leave_game'] + ': ' + info.quit,
minecraft['stat.minecraft.deaths'] + ': ' + info.death,
minecraft['stat.minecraft.player_kills'] + ': ' + info.playerKill,
minecraft['stat.minecraft.mob_kills'] + ': ' + info.entityKill,
lang.playerList.tnt + ': ' + info.tnt
].map((it, i) => <ListItem key={i} sx={{ pl: 4 }}>
<ListItemIcon>{icons[i]}</ListItemIcon>
<ListItemText primary={it} />
</ListItem>)}
</List>
</Collapse>
</>}
</List>
<CardActions disableSpacing sx={{ justifyContent: 'flex-end' }}>
<Tooltip title={lang.playerList[info.whitelisted ? 'clickToRemoveWhitelist' : 'clickToAddWhitelist']}>
<IconButton onClick={() => whitelist(name, plugin, refresh, !info.whitelisted)}>
{info.whitelisted ? <Star color='warning' /> : <StarBorder />}
</IconButton>
</Tooltip>
<Tooltip title={lang.playerList[info.ban == null ? 'clickToBan' : 'clickToPardon']}>
<IconButton onClick={() => banPlayer(name, plugin, refresh, info.ban == null)}>
<Block color={info.ban == null ? undefined : 'error'} />
</IconButton>
</Tooltip>
</CardActions>
</>
: <></>
})
Example #8
Source File: Worlds.tsx From NekoMaid with MIT License | 4 votes |
Worlds: React.FC = () => {
const plugin = usePlugin()
const globalData = useGlobalData()
const [worlds, setWorlds] = useState<World[]>([])
const [selected, setSelected] = useState('')
const [open, setOpen] = useState(false)
const update = () => plugin.emit('worlds:fetch', (data: World[]) => {
setWorlds(data)
if (data.length) setSelected(old => data.some(it => it.id === old) ? old : '')
})
useEffect(() => {
const offUpdate = plugin.on('worlds:update', update)
update()
return () => { offUpdate() }
}, [])
const sw = worlds.find(it => it.id === selected)
const getSwitch = (name: string, configId = name) => sw
? <ListItem
secondaryAction={<Switch disabled={!globalData.hasMultiverse} checked={(sw as any)[name]}
onChange={e => {
plugin.emit('worlds:set', sw.id, configId, e.target.checked.toString())
success()
}}
/>}><ListItemText primary={(lang.worlds as any)[name]} /></ListItem>
: null
return <Box sx={{ minHeight: '100%', py: 3 }}>
<Toolbar />
<Container maxWidth={false}>
<Grid container spacing={3}>
<Grid item lg={8} md={12} xl={9} xs={12}>
<Card>
<CardHeader title={lang.worlds.title} />
<Divider />
<Box sx={{ position: 'relative' }}>
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell padding='checkbox' />
<TableCell>{lang.worlds.name}</TableCell>
{globalData.hasMultiverse && <TableCell>{lang.worlds.alias}</TableCell>}
<TableCell>{lang.worlds.players}</TableCell>
<TableCell>{lang.worlds.chunks}</TableCell>
<TableCell>{lang.worlds.entities}</TableCell>
<TableCell>{lang.worlds.tiles}</TableCell>
<TableCell>{lang.worlds.time}</TableCell>
<TableCell>{lang.worlds.weather}</TableCell>
</TableRow>
</TableHead>
<TableBody>
{worlds.map(it => <TableRow key={it.id}>
<TableCell padding='checkbox'><Checkbox checked={selected === it.id} onClick={() => setSelected(it.id)} /></TableCell>
<TableCell><Tooltip title={it.id}><span>{it.name}</span></Tooltip></TableCell>
{globalData.hasMultiverse && <TableCell>{it.alias}
<IconButton size='small' onClick={() => dialog(lang.inputValue, lang.worlds.alias).then(res => {
if (res == null) return
plugin.emit('worlds:set', it.id, 'alias', res)
success()
})}><Edit fontSize='small' /></IconButton>
</TableCell>}
<TableCell>{it.players}</TableCell>
<TableCell>{it.chunks}</TableCell>
<TableCell>{it.entities}</TableCell>
<TableCell>{it.tiles}</TableCell>
<TableCell><Countdown time={it.time} max={24000} interval={50} /></TableCell>
<TableCell><IconButton size='small' onClick={() => {
plugin.emit('worlds:weather', it.id)
success()
}}>
{React.createElement((it.weather === 1 ? WeatherRainy : it.weather === 2 ? WeatherLightningRainy : WbSunny) as any)}
</IconButton></TableCell>
</TableRow>)}
</TableBody>
</Table>
</TableContainer>
</Box>
</Card>
</Grid>
<Grid item lg={4} md={6} xl={3} xs={12}>
<Card>
<CardHeader
title={lang.operations}
sx={{ position: 'relative' }}
action={<Tooltip title={lang.worlds.save} placement='left'>
<IconButton
size='small'
onClick={() => {
if (!sw) return
plugin.emit('worlds:save', sw.id)
success()
}}
sx={cardActionStyles}
><Save /></IconButton>
</Tooltip>}
/>
<Divider />
<Box sx={{ position: 'relative' }}>
{sw
? <List sx={{ width: '100%' }} component='nav'>
<ListItem secondaryAction={<ToggleButtonGroup
exclusive
color='primary'
size='small'
value={sw.difficulty}
onChange={(_, value) => {
plugin.emit('worlds:difficulty', sw.id, value)
success()
}}
>
{difficulties.map(it => <ToggleButton value={it.toUpperCase()} key={it}>{minecraft['options.difficulty.' + it]}</ToggleButton>)}
</ToggleButtonGroup>}><ListItemText primary={minecraft['options.difficulty']} /></ListItem>
<ListItem secondaryAction={<Switch checked={sw.pvp} onChange={e => {
plugin.emit('worlds:pvp', sw.id, e.target.checked)
success()
}} />}><ListItemText primary='PVP' /></ListItem>
{getSwitch('allowAnimals', 'spawning.animals.spawn')}
{getSwitch('allowMonsters', 'spawning.monsters.spawn')}
{globalData.hasMultiverse && <>
{getSwitch('allowFlight')}
{getSwitch('autoHeal')}
{getSwitch('hunger')}
</>}
<ListItem secondaryAction={globalData.canSetViewDistance
? <IconButton
onClick={() => dialog({
content: lang.inputValue,
input: {
error: true,
type: 'number',
helperText: lang.invalidValue,
validator: (it: string) => /^\d+$/.test(it) && +it > 1 && +it < 33
}
}).then(res => {
if (!res) return
plugin.emit('worlds:viewDistance', sw.id, parseInt(res as any))
success()
})}
><Edit /></IconButton>
: undefined}>
<ListItemText primary={lang.worlds.viewDistance + ': ' + sw.viewDistance} />
</ListItem>
<ListItem><ListItemText primary={minecraft['selectWorld.enterSeed']} secondary={sw.seed} /></ListItem>
<ListItemButton onClick={() => setOpen(!open)}>
<ListItemText primary={minecraft['selectWorld.gameRules']} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component='div' dense disablePadding>
{sw.rules.map(([key, value]) => {
const isTrue = value === 'true'
const isBoolean = isTrue || value === 'false'
const isNumber = /^\d+$/.test(value)
return <ListItem
key={key}
sx={{ pl: 4 }}
secondaryAction={isBoolean
? <Switch
checked={isTrue}
onChange={e => {
plugin.emit('worlds:rule', sw.id, key, e.target.checked.toString())
success()
}}
/>
: <IconButton
onClick={() => dialog({
content: lang.inputValue,
input: isNumber
? {
error: true,
type: 'number',
helperText: lang.invalidValue,
validator: (it: string) => /^\d+$/.test(it)
}
: { }
}).then(res => {
if (res == null) return
plugin.emit('worlds:rule', sw.id, key, res)
success()
})}
><Edit /></IconButton>}
>
<ListItemText primary={(minecraft['gamerule.' + key] || key) + (isBoolean ? '' : ': ' + value)} />
</ListItem>
})}
</List>
</Collapse>
</List>
: <CardContent><Empty /></CardContent>
}
</Box>
</Card>
</Grid>
</Grid>
</Container>
</Box>
}