diff --git a/docs/data/joy/components/aspect-ratio/ListStackRatio.js b/docs/data/joy/components/aspect-ratio/ListStackRatio.js index f6fd806102bba3..4d492d407d3f46 100644 --- a/docs/data/joy/components/aspect-ratio/ListStackRatio.js +++ b/docs/data/joy/components/aspect-ratio/ListStackRatio.js @@ -38,7 +38,7 @@ export default function FlexRowRatio() { borderRadius: 'sm', }} > - + {data.map((item, index) => ( diff --git a/docs/data/joy/components/aspect-ratio/ListStackRatio.tsx b/docs/data/joy/components/aspect-ratio/ListStackRatio.tsx index f6fd806102bba3..4d492d407d3f46 100644 --- a/docs/data/joy/components/aspect-ratio/ListStackRatio.tsx +++ b/docs/data/joy/components/aspect-ratio/ListStackRatio.tsx @@ -38,7 +38,7 @@ export default function FlexRowRatio() { borderRadius: 'sm', }} > - + {data.map((item, index) => ( diff --git a/docs/data/joy/components/list/ActionableList.js b/docs/data/joy/components/list/ActionableList.js new file mode 100644 index 00000000000000..242650638322c6 --- /dev/null +++ b/docs/data/joy/components/list/ActionableList.js @@ -0,0 +1,34 @@ +import * as React from 'react'; +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; +import ListItemDecorator from '@mui/joy/ListItemDecorator'; +import ListItemButton from '@mui/joy/ListItemButton'; +import OpenInNew from '@mui/icons-material/OpenInNew'; +import Info from '@mui/icons-material/Info'; + +export default function ActionableList() { + return ( + + + alert('You clicked')}> + + + + Clickable item + + + + + + + + Open a new tab + + + + ); +} diff --git a/docs/data/joy/components/list/BasicList.js b/docs/data/joy/components/list/BasicList.js new file mode 100644 index 00000000000000..d6893d890c20e9 --- /dev/null +++ b/docs/data/joy/components/list/BasicList.js @@ -0,0 +1,25 @@ +import * as React from 'react'; +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; +import Typography from '@mui/joy/Typography'; + +export default function BasicList() { + return ( +
+ + Ingredients + + + 1 red onion + 2 red peppers + 120g bacon + +
+ ); +} diff --git a/docs/data/joy/components/list/DecoratedList.js b/docs/data/joy/components/list/DecoratedList.js new file mode 100644 index 00000000000000..51184be1f5fa1c --- /dev/null +++ b/docs/data/joy/components/list/DecoratedList.js @@ -0,0 +1,35 @@ +import * as React from 'react'; +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; +import ListItemDecorator from '@mui/joy/ListItemDecorator'; +import Typography from '@mui/joy/Typography'; + +export default function DecoratedList() { + return ( +
+ + Ingredients + + + + 🧅 1 red onion + + + 🍤 2 Shrimps + + + 🥓 120g bacon + + +
+ ); +} diff --git a/docs/data/joy/components/list/DividedList.js b/docs/data/joy/components/list/DividedList.js new file mode 100644 index 00000000000000..4c396cb1fcce15 --- /dev/null +++ b/docs/data/joy/components/list/DividedList.js @@ -0,0 +1,55 @@ +import * as React from 'react'; +import Avatar from '@mui/joy/Avatar'; +import Box from '@mui/joy/Box'; +import List from '@mui/joy/List'; +import ListDivider from '@mui/joy/ListDivider'; +import ListItem from '@mui/joy/ListItem'; +import ListItemDecorator from '@mui/joy/ListItemDecorator'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; + +export default function DividedList() { + return ( + + {[undefined, 'gutter', 'startDecorator', 'startContent'].map((inset) => ( + + + {inset ? `inset="${inset}"` : '(default)'} + + + + + + + + Mabel Boyle + + + + + + + Boyd Burt + + + + + ))} + + ); +} diff --git a/docs/data/joy/components/list/EllipsisList.js b/docs/data/joy/components/list/EllipsisList.js new file mode 100644 index 00000000000000..b4d8a1a00795d3 --- /dev/null +++ b/docs/data/joy/components/list/EllipsisList.js @@ -0,0 +1,52 @@ +import * as React from 'react'; +import Avatar from '@mui/joy/Avatar'; +import Box from '@mui/joy/Box'; +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; +import ListItemContent from '@mui/joy/ListItemContent'; +import ListItemDecorator from '@mui/joy/ListItemDecorator'; +import Typography from '@mui/joy/Typography'; + +export default function EllipsisList() { + return ( + + + Inbox + + + + + + + + Brunch this weekend? + + I'll be in your neighborhood doing errands this Tuesday. + + + + + + + + + Summer BBQ + + Wish I could come, but I'm out of town this Friday. + + + + + + ); +} diff --git a/docs/data/joy/components/list/ExampleCollapsibleList.js b/docs/data/joy/components/list/ExampleCollapsibleList.js new file mode 100644 index 00000000000000..d5e477687f4e36 --- /dev/null +++ b/docs/data/joy/components/list/ExampleCollapsibleList.js @@ -0,0 +1,173 @@ +import * as React from 'react'; +import Box from '@mui/joy/Box'; +import List from '@mui/joy/List'; +import ListItem, { listItemClasses } from '@mui/joy/ListItem'; +import ListItemButton, { listItemButtonClasses } from '@mui/joy/ListItemButton'; +import IconButton from '@mui/joy/IconButton'; +import Typography from '@mui/joy/Typography'; +import ReceiptLong from '@mui/icons-material/ReceiptLong'; +import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown'; + +export default function ExampleCollapsibleList() { + const [open, setOpen] = React.useState(false); + const [open2, setOpen2] = React.useState(false); + return ( + + ({ + // Gatsby colors + '--joy-palette-primary-plainColor': '#8a4baf', + '--joy-palette-neutral-plainHoverBg': 'transparent', + '--joy-palette-neutral-plainActiveBg': 'transparent', + '--joy-palette-primary-plainHoverBg': 'transparent', + '--joy-palette-primary-plainActiveBg': 'transparent', + [theme.getColorSchemeSelector('dark')]: { + '--joy-palette-text-secondary': '#635e69', + '--joy-palette-primary-plainColor': '#d48cff', + }, + + '--List-insetStart': '32px', + '--List-item-paddingY': '0px', + '--List-item-paddingRight': '16px', + '--List-item-paddingLeft': '21px', + '--List-item-startActionWidth': '0px', + '--List-item-startActionTranslateX': '-50%', + + [`& .${listItemButtonClasses.root}`]: { + borderLeft: '1px solid', + borderColor: 'divider', + }, + [`& .${listItemButtonClasses.root}.${listItemButtonClasses.selected}`]: { + borderColor: 'currentColor', + }, + [`& .${listItemClasses.nested} > .${listItemButtonClasses.root}`]: { + border: 'none', + }, + '& [class*="startAction"]': { + color: 'var(--joy-palette-text-tertiary)', + }, + })} + > + + }> + + Documentation + + + + + Overview + + + + + Quick Start + + setOpen(!open)} + > + + + } + > + + + Tutorial + + + 9 + + + {open && ( + + + Overview + + + + 0. Set Up Your Development Environment + + + + + 1. Create and Deploy Your First Gatsby Site + + + + 2. Use and Style React components + + + )} + + setOpen2((bool) => !bool)} + > + + + } + > + + + How-to Guides + + + 39 + + + {open2 && ( + + + Overview + + + Local Development + + + Routing + + + Styling + + + )} + + + + ); +} diff --git a/docs/data/joy/components/list/ExampleGmailList.js b/docs/data/joy/components/list/ExampleGmailList.js new file mode 100644 index 00000000000000..db63dd77aaa62e --- /dev/null +++ b/docs/data/joy/components/list/ExampleGmailList.js @@ -0,0 +1,116 @@ +import * as React from 'react'; +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; +import ListItemDecorator, { + listItemDecoratorClasses, +} from '@mui/joy/ListItemDecorator'; +import ListItemContent from '@mui/joy/ListItemContent'; +import ListItemButton from '@mui/joy/ListItemButton'; +import Typography from '@mui/joy/Typography'; +import Box from '@mui/joy/Box'; +import ArrowDropDown from '@mui/icons-material/ArrowDropDown'; +import InboxIcon from '@mui/icons-material/Inbox'; +import Label from '@mui/icons-material/Label'; +import People from '@mui/icons-material/People'; +import Info from '@mui/icons-material/Info'; +import Star from '@mui/icons-material/Star'; + +export default function ExampleGmailList() { + const [index, setIndex] = React.useState(0); + return ( + + theme.vars.palette.text.secondary, + '--List-item-minHeight': '32px', + '--List-nestedInsetStart': '13px', + [`& .${listItemDecoratorClasses.root}`]: { + justifyContent: 'flex-end', + pr: '18px', + }, + '& [role="button"]': { + borderRadius: '0 20px 20px 0', + }, + }} + > + + setIndex(0)} + > + + + + Inbox + + 1,950 + + + + + setIndex(1)} + > + + + + Starred + + + + setIndex(2)} + > + + + + Categories + + + + setIndex(3)} + > + + + + Social + 4,320 + + + + setIndex(4)} + > + + + + Updates + 22,252 + + + + + + + ); +} diff --git a/docs/data/joy/components/list/ExampleIOSList.js b/docs/data/joy/components/list/ExampleIOSList.js new file mode 100644 index 00000000000000..9af36d3c3d9481 --- /dev/null +++ b/docs/data/joy/components/list/ExampleIOSList.js @@ -0,0 +1,194 @@ +import * as React from 'react'; +import Avatar from '@mui/joy/Avatar'; +import List from '@mui/joy/List'; +import ListDivider from '@mui/joy/ListDivider'; +import ListItem from '@mui/joy/ListItem'; +import ListItemContent from '@mui/joy/ListItemContent'; +import ListItemDecorator from '@mui/joy/ListItemDecorator'; +import ListItemButton from '@mui/joy/ListItemButton'; +import Typography from '@mui/joy/Typography'; +import Sheet, { sheetClasses } from '@mui/joy/Sheet'; +import Switch, { switchClasses } from '@mui/joy/Switch'; +import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRightRounded'; +import Flight from '@mui/icons-material/Flight'; +import Wifi from '@mui/icons-material/Wifi'; +import Bluetooth from '@mui/icons-material/Bluetooth'; +import Podcasts from '@mui/icons-material/Podcasts'; + +export default function ExampleIOSList() { + return ( + + + Settings + + ({ + '& ul': { + '--List-gap': '0px', + bgcolor: 'background.surface', + '& > li:first-child > [role="button"]': { + borderTopRightRadius: 'var(--List-radius)', + borderTopLeftRadius: 'var(--List-radius)', + }, + '& > li:last-child > [role="button"]': { + borderBottomRightRadius: 'var(--List-radius)', + borderBottomLeftRadius: 'var(--List-radius)', + }, + }, + '--List-radius': '8px', + '--List-gap': '1rem', + '--List-divider-gap': '0px', + '--List-item-paddingY': '0.5rem', + // override global variant tokens + '--joy-palette-neutral-plainHoverBg': 'rgba(0 0 0 / 0.08)', + '--joy-palette-neutral-plainActiveBg': 'rgba(0 0 0 / 0.12)', + [theme.getColorSchemeSelector('light')]: { + '--joy-palette-divider': 'rgba(0 0 0 / 0.08)', + }, + [theme.getColorSchemeSelector('dark')]: { + '--joy-palette-neutral-plainHoverBg': 'rgba(255 255 255 / 0.1)', + '--joy-palette-neutral-plainActiveBg': 'rgba(255 255 255 / 0.16)', + }, + })} + > + + + + + + MB + + +
+ Murphy Bates + + Apple ID, iCloud, Media & Purchase + +
+
+ + + + iCloud+ Feature Updates + + + +
+
+ + + + Apple TV+ Free Year Available + + + + Included with your recent Apple device purchase. Must be accepted within + 90 days of activation. + + + + + + + + + + + + Airplane Mode + + ({ + '--Switch-track-width': '48px', + '--Switch-track-height': '28px', + '--Switch-thumb-shadow': theme.vars.shadow.sm, + '--Switch-track-background': theme.vars.palette.background.level3, + '&:hover': { + '--Switch-track-background': + theme.vars.palette.background.level3, + }, + '&:active': { + '--Switch-thumb-width': '32px', + [`& .${switchClasses.thumb}`]: { + transition: 'width 0.2s, left 0.2s', + }, + }, + [`&.${switchClasses.checked}`]: { + '--Switch-track-background': theme.vars.palette.success[500], + '&:hover': { + '--Switch-track-background': theme.vars.palette.success[500], + }, + }, + })} + /> + + + + + + + + + + Wi-Fi + Mars + + + + + + + + + + + + Bluetooth + On + + + + + + + + + + + + Cellular + + + + + +
+
+ ); +} diff --git a/docs/data/joy/components/list/ExampleNavigationMenu.js b/docs/data/joy/components/list/ExampleNavigationMenu.js new file mode 100644 index 00000000000000..c6ab55a0cb7f53 --- /dev/null +++ b/docs/data/joy/components/list/ExampleNavigationMenu.js @@ -0,0 +1,353 @@ +import * as React from 'react'; +import PopperUnstyled from '@mui/base/PopperUnstyled'; +import ClickAwayListener from '@mui/base/ClickAwayListener'; +import Box from '@mui/joy/Box'; +import IconButton from '@mui/joy/IconButton'; +import Chip from '@mui/joy/Chip'; +import List from '@mui/joy/List'; +import ListDivider from '@mui/joy/ListDivider'; +import ListItem from '@mui/joy/ListItem'; +import ListItemContent from '@mui/joy/ListItemContent'; +import ListItemButton from '@mui/joy/ListItemButton'; +import ListItemDecorator from '@mui/joy/ListItemDecorator'; +import Sheet from '@mui/joy/Sheet'; +import HomeRounded from '@mui/icons-material/HomeRounded'; +import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown'; +import Person from '@mui/icons-material/Person'; +import Apps from '@mui/icons-material/Apps'; +import FactCheck from '@mui/icons-material/FactCheck'; +import BookmarkAdd from '@mui/icons-material/BookmarkAdd'; + +const useRovingIndex = (options) => { + const { initialActiveIndex = 0, vertical = false, handlers = {} } = options || {}; + const [activeIndex, setActiveIndex] = React.useState(initialActiveIndex); + const targetRefs = React.useRef([]); + const targets = targetRefs.current; + const focusNext = () => { + let newIndex = activeIndex + 1; + if (newIndex >= targets.length) { + newIndex = 0; + } + targets[newIndex]?.focus(); + setActiveIndex(newIndex); + }; + const focusPrevious = () => { + let newIndex = activeIndex - 1; + if (newIndex < 0) { + newIndex = targets.length - 1; + } + targets[newIndex]?.focus(); + setActiveIndex(newIndex); + }; + const getTargetProps = (index) => ({ + ref: (ref) => { + if (ref) { + targets[index] = ref; + } + }, + tabIndex: activeIndex === index ? 0 : -1, + onKeyDown: (e) => { + if (Number.isInteger(activeIndex)) { + if (e.key === (vertical ? 'ArrowDown' : 'ArrowRight')) { + focusNext(); + } + if (e.key === (vertical ? 'ArrowUp' : 'ArrowLeft')) { + focusPrevious(); + } + handlers.onKeyDown?.(e, { setActiveIndex }); + } + }, + onClick: () => { + setActiveIndex(index); + }, + }); + return { + activeIndex, + setActiveIndex, + targets, + getTargetProps, + focusNext, + focusPrevious, + }; +}; + +const AboutMenu = React.forwardRef(({ focusNext, focusPrevious, ...props }, ref) => { + const [anchorEl, setAnchorEl] = React.useState(null); + const { targets, setActiveIndex, getTargetProps } = useRovingIndex({ + initialActiveIndex: null, + vertical: true, + handlers: { + onKeyDown: (event, fns) => { + if (event.key.match(/(ArrowDown|ArrowUp|ArrowLeft|ArrowRight)/)) { + event.preventDefault(); + } + if (event.key === 'Tab') { + setAnchorEl(null); + fns.setActiveIndex(null); + } + if (event.key === 'ArrowLeft') { + setAnchorEl(null); + focusPrevious(); + } + if (event.key === 'ArrowRight') { + setAnchorEl(null); + focusNext(); + } + }, + }, + }); + + const open = Boolean(anchorEl); + const id = open ? 'about-popper' : undefined; + return ( + setAnchorEl(null)}> + setAnchorEl(null)}> + { + props.onKeyDown?.(event); + if (event.key.match(/(ArrowLeft|ArrowRight|Tab)/)) { + setAnchorEl(null); + } + if (event.key === 'ArrowDown') { + event.preventDefault(); + targets[0]?.focus(); + setActiveIndex(0); + } + }} + onFocus={(event) => setAnchorEl(event.currentTarget)} + onMouseEnter={(event) => { + props.onMouseEnter?.(event); + setAnchorEl(event.currentTarget); + }} + sx={(theme) => ({ + ...(open && theme.variants.plainHover.neutral), + })} + > + About + + + + + + + + + + Overview + + + + + + + + Administration + + + + + + + + Facts + + + + + + + + ); +}); + +const AdmissionsMenu = React.forwardRef( + ({ focusNext, focusPrevious, ...props }, ref) => { + const [anchorEl, setAnchorEl] = React.useState(null); + const { targets, setActiveIndex, getTargetProps } = useRovingIndex({ + initialActiveIndex: null, + vertical: true, + handlers: { + onKeyDown: (event, fns) => { + if (event.key.match(/(ArrowDown|ArrowUp|ArrowLeft|ArrowRight)/)) { + event.preventDefault(); + } + if (event.key === 'Tab') { + setAnchorEl(null); + fns.setActiveIndex(null); + } + if (event.key === 'ArrowLeft') { + setAnchorEl(null); + focusPrevious(); + } + if (event.key === 'ArrowRight') { + setAnchorEl(null); + focusNext(); + } + }, + }, + }); + + const open = Boolean(anchorEl); + const id = open ? 'admissions-popper' : undefined; + return ( + setAnchorEl(null)}> + setAnchorEl(null)}> + { + props.onKeyDown?.(event); + if (event.key.match(/(ArrowLeft|ArrowRight|Tab)/)) { + setAnchorEl(null); + } + if (event.key === 'ArrowDown') { + event.preventDefault(); + targets[0]?.focus(); + setActiveIndex(0); + } + }} + onFocus={(event) => setAnchorEl(event.currentTarget)} + onMouseEnter={(event) => { + props.onMouseEnter?.(event); + setAnchorEl(event.currentTarget); + }} + sx={(theme) => ({ + ...(open && theme.variants.plainHover.neutral), + })} + > + Admissions + + + + + + + Apply + + Last 2 days! + + + + + + + Visit + + + + + + } + > + + Photo tour + + + + + + + + ); + }, +); + +export default function ExampleNavigationMenu() { + const { targets, getTargetProps, setActiveIndex, focusNext, focusPrevious } = + useRovingIndex(); + return ( + + + + + + + + Home + + + + { + setActiveIndex(1); + targets[1].focus(); + }} + focusNext={focusNext} + focusPrevious={focusPrevious} + {...getTargetProps(1)} + /> + + + { + setActiveIndex(2); + targets[2].focus(); + }} + focusNext={focusNext} + focusPrevious={focusPrevious} + {...getTargetProps(2)} + /> + + + + ); +} diff --git a/docs/data/joy/components/list/HorizontalList.js b/docs/data/joy/components/list/HorizontalList.js new file mode 100644 index 00000000000000..952a6278e60018 --- /dev/null +++ b/docs/data/joy/components/list/HorizontalList.js @@ -0,0 +1,52 @@ +import * as React from 'react'; +import Box from '@mui/joy/Box'; +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; +import ListItemButton from '@mui/joy/ListItemButton'; +import Home from '@mui/icons-material/Home'; +import Person from '@mui/icons-material/Person'; + +export default function HorizontalList() { + return ( + + + + + + + + + + Products + + + + + Blog + + + + + + + + + + ); +} diff --git a/docs/data/joy/components/list/ListVariables.js b/docs/data/joy/components/list/ListVariables.js new file mode 100644 index 00000000000000..e43801493b7dcd --- /dev/null +++ b/docs/data/joy/components/list/ListVariables.js @@ -0,0 +1,107 @@ +import * as React from 'react'; +import JoyVariablesDemo from 'docs/src/modules/components/JoyVariablesDemo'; +import Avatar from '@mui/joy/Avatar'; +import IconButton from '@mui/joy/IconButton'; +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; +import ListItemButton from '@mui/joy/ListItemButton'; +import ListItemDecorator from '@mui/joy/ListItemDecorator'; +import ListDivider from '@mui/joy/ListDivider'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; +import Home from '@mui/icons-material/Home'; +import Apps from '@mui/icons-material/Apps'; +import MoreVert from '@mui/icons-material/MoreVert'; + +export default function ListVariables() { + return ( + ( + ({ ...sx, width: 300, ...theme.variants.outlined.neutral })} + > + + + + + + Home + + + + + + + + Products + + + + + + + } + > + Online people + + + + + + + } + > + + + + + Mabel Boyle + + + + + + + } + > + + + + + Boyd Burt + + + + + + )} + /> + ); +} diff --git a/docs/data/joy/components/list/NavList.js b/docs/data/joy/components/list/NavList.js new file mode 100644 index 00000000000000..121e54fbef2882 --- /dev/null +++ b/docs/data/joy/components/list/NavList.js @@ -0,0 +1,30 @@ +import * as React from 'react'; +import List from '@mui/joy/List'; +import ListItemDecorator from '@mui/joy/ListItemDecorator'; +import ListItemButton from '@mui/joy/ListItemButton'; +import Videocam from '@mui/icons-material/Videocam'; +import Image from '@mui/icons-material/Image'; + +export default function NavList() { + return ( + + + + + + Add another image + + + + + + Add another video + + + ); +} diff --git a/docs/data/joy/components/list/NestedList.js b/docs/data/joy/components/list/NestedList.js new file mode 100644 index 00000000000000..449d676923f282 --- /dev/null +++ b/docs/data/joy/components/list/NestedList.js @@ -0,0 +1,81 @@ +import * as React from 'react'; +import Box from '@mui/joy/Box'; +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; +import ListItemButton from '@mui/joy/ListItemButton'; +import Typography from '@mui/joy/Typography'; +import Switch from '@mui/joy/Switch'; +import Sheet from '@mui/joy/Sheet'; + +export default function NestedList() { + const [small, setSmall] = React.useState(false); + return ( + + setSmall(event.target.checked)} + endDecorator={ + Toggle small nested list + } + sx={{ mb: 2 }} + /> + + + + + + Category 1 + + + + + Subitem 1 + + + Subitem 2 + + + + + + + Category 2 + + + + + Subitem 1 + + + Subitem 2 + + + + + + + ); +} diff --git a/docs/data/joy/components/list/SecondaryList.js b/docs/data/joy/components/list/SecondaryList.js new file mode 100644 index 00000000000000..86589eadffc791 --- /dev/null +++ b/docs/data/joy/components/list/SecondaryList.js @@ -0,0 +1,32 @@ +import * as React from 'react'; +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; +import ListItemButton from '@mui/joy/ListItemButton'; +import IconButton from '@mui/joy/IconButton'; +import Add from '@mui/icons-material/Add'; +import Delete from '@mui/icons-material/Delete'; + +export default function SecondaryList() { + return ( + + + + + } + > + Item 1 + + + + + } + > + Item 2 + + + ); +} diff --git a/docs/data/joy/components/list/SelectedList.js b/docs/data/joy/components/list/SelectedList.js new file mode 100644 index 00000000000000..419d9a3f4b7035 --- /dev/null +++ b/docs/data/joy/components/list/SelectedList.js @@ -0,0 +1,40 @@ +import * as React from 'react'; +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; +import ListItemDecorator from '@mui/joy/ListItemDecorator'; +import ListItemButton from '@mui/joy/ListItemButton'; +import Home from '@mui/icons-material/Home'; +import Apps from '@mui/icons-material/Apps'; + +export default function SelectedList() { + return ( + + + + + + + Home + + + + + + + + Apps + + + + + + Settings + + + + ); +} diff --git a/docs/data/joy/components/list/SizesList.js b/docs/data/joy/components/list/SizesList.js new file mode 100644 index 00000000000000..760c076334a30e --- /dev/null +++ b/docs/data/joy/components/list/SizesList.js @@ -0,0 +1,50 @@ +import * as React from 'react'; +import Box from '@mui/joy/Box'; +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; +import ListItemDecorator from '@mui/joy/ListItemDecorator'; +import ListItemButton from '@mui/joy/ListItemButton'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; +import Home from '@mui/icons-material/Home'; + +export default function SizesList() { + return ( + *': { minWidth: 0, flexBasis: 120 }, + }} + > + {['sm', 'md', 'lg'].map((size) => ( + + + size="{size}" + + + + + + + + + Home + + + + Projects + + + Settings + + + + + ))} + + ); +} diff --git a/docs/data/joy/components/list/StickyList.js b/docs/data/joy/components/list/StickyList.js new file mode 100644 index 00000000000000..a7c7d42de53934 --- /dev/null +++ b/docs/data/joy/components/list/StickyList.js @@ -0,0 +1,43 @@ +import * as React from 'react'; +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; +import ListItemButton from '@mui/joy/ListItemButton'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; + +export default function StickyList() { + return ( + + + {[...Array(5)].map((_, categoryIndex) => ( + + + + Category {categoryIndex + 1} + + + + {[...Array(10)].map((__, index) => ( + + Subitem {index + 1} + + ))} + + + ))} + + + ); +} diff --git a/docs/data/joy/components/list/VariantsColorsList.js b/docs/data/joy/components/list/VariantsColorsList.js new file mode 100644 index 00000000000000..989226eef6d3f5 --- /dev/null +++ b/docs/data/joy/components/list/VariantsColorsList.js @@ -0,0 +1,49 @@ +import * as React from 'react'; +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; +import ListItemContent from '@mui/joy/ListItemContent'; +import ListItemDecorator from '@mui/joy/ListItemDecorator'; +import ListItemButton from '@mui/joy/ListItemButton'; +import Home from '@mui/icons-material/Home'; +import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight'; +import JoyUsageDemo from 'docs/src/modules/components/JoyUsageDemo'; + +export default function VariantsColorsList() { + return ( + ( + + + + + + + Home + + + + + )} + /> + ); +} diff --git a/docs/data/joy/components/list/list.md b/docs/data/joy/components/list/list.md new file mode 100644 index 00000000000000..06f9063cae196f --- /dev/null +++ b/docs/data/joy/components/list/list.md @@ -0,0 +1,206 @@ +--- +product: joy-ui +title: React List component +githubLabel: 'component: list' +--- + +# Lists + +

Lists are continuous, vertical indexes of text or images.

+ +## Introduction + +Joy UI provides four list-related components: + +- `List`: A wrapper for list items (defaulting as `ul`). +- `ListItem`: A common list item (default as `li`). +- `ListItemButton`: Ans action element to be used inside a list item. +- `ListItemDecorator`: A decorator of a list item, usually used to display an icon. +- `ListItemContent`: A container inside a list item, used to display text content. +- `ListDivider`: A separator between list items. + +## Component + +After installation, you can start building with this component using the following basic elements: + +```jsx +import List from '@mui/joy/List'; +import ListItem from '@mui/joy/ListItem'; + +export default function MyApp() { + return ( + + Hello, world! + Bye bye, world! + + ); +} +``` + +### Basic usage + +Use the `List` and `ListItem` components to create a basic, non-interactive, list. +Make sure to use a meaningful name that describe the content of the list in the `aria-labelledby` prop. + +{{"demo": "BasicList.js"}} + +### Sizes + +Use the `size` prop to control font-size and general list density. + +{{"demo": "SizesList.js"}} + +### Decorator + +Use the `ListItemDecorator` component to add supporting icons or elements to the list item. + +It comes with a minimum set width that you can adjust via the `--List-decorator-width` CSS variable within the `List` component. + +{{"demo": "DecoratedList.js"}} + +### Ellipsis content + +When dealing with long content, use the `ListItemComponent` together with `` to show ellipsis. + +{{"demo": "EllipsisList.js"}} + +### Divider + +The `ListDivider` component comes with four `inset` patterns: + +- Default (without providing the `inset` prop): stretches from edge to edge of the list. +- `inset="gutter"`: from the start of the decorator to the end of the content. +- `inset="startDecorator"`: from the start of the decorator to the end of the list. +- `inset="startContent"`: from the start of the content to the end of the list. + +{{"demo": "DividedList.js"}} + +### Sticky item + +To have a sticky list item, use a `List` as a child of the `Sheet` component. +Then, on the item you wish to stick, add the `sticky` prop. + +The `Sheet` component automatically adjusts the `sticky` list item to have the same background so that the content does not overflow when scroll. +It works by default on both light and dark modes. + +{{"demo": "StickyList.js"}} + +### Nested list + +Use the `nested` prop, within the `ListItem` component, to create a nested list. +Note that layout and spacing of the nested list remain intact, as if it isn't nested. + +The nested list inherits the list `size` and a few other CSS variables, such as `--List-radius` and `--List-item-radius` from the root `List` component to adjust the design consistently. + +{{"demo": "NestedList.js"}} + +:::info +**Note:** By default, nested lists stick to the left of the root list. +To add spacing to the start of the nested list, use `--List-nestedInsetStart: ${value}`: + +```js + {/* This is the root List */} +``` + +::: + +### Horizontal list + +To show a list in a horizontal direction, use the `row` prop on the `List` component. + +:::warning +**Note:** Nested lists don't work in the horizontal direction. +To do that, create a custom pop-up component instead (see the [Navigation menu](#navigation-menu) example). +::: + +{{"demo": "HorizontalList.js"}} + +### Changing the semantic element + +To control which HTML tag should be rendered in a given, one-off, situation, use the `component` prop. + +```js + +``` + +#### Non-list + +In the example below, we're rendering a `List` as a HTML `