diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fe13794b..6d1bd9402 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Not released +- Keyboard accessibility improvements in Widgets and DS components [#835](https://github.com/CartoDB/carto-react/pull/835) + ## 2.3 ### 2.3.10 (2024-01-31) diff --git a/packages/react-ui/src/localization/en.js b/packages/react-ui/src/localization/en.js index 3a9ec15a9..0ab4e6c73 100644 --- a/packages/react-ui/src/localization/en.js +++ b/packages/react-ui/src/localization/en.js @@ -79,6 +79,10 @@ const locales = { clear: 'Clear', selectedItems: '{items, plural, one{# selected} other{# selected}}', allSelected: 'All' + }, + chartLegend: { + next: 'Next page', + prev: 'Previous page' } } } diff --git a/packages/react-ui/src/localization/es.js b/packages/react-ui/src/localization/es.js index de111fd05..7168d0df7 100644 --- a/packages/react-ui/src/localization/es.js +++ b/packages/react-ui/src/localization/es.js @@ -79,6 +79,10 @@ const locales = { clear: 'Limpiar', selectedItems: '{items, plural, one {# seleccionado} other {# seleccionados}}', allSelected: 'Todos seleccionados' + }, + chartLegend: { + next: 'Página siguiente', + prev: 'Página anterior' } } } diff --git a/packages/react-ui/src/localization/id.js b/packages/react-ui/src/localization/id.js index 395e5bb11..5235aeb14 100644 --- a/packages/react-ui/src/localization/id.js +++ b/packages/react-ui/src/localization/id.js @@ -80,6 +80,10 @@ const locales = { clear: 'Bersihkan', selectedItems: '{items, plural, one{# terpilih} other{# terpilih}}', allSelected: 'Semua terpilih' + }, + chartLegend: { + next: 'Next page', + prev: 'Previous page' } } } diff --git a/packages/react-ui/src/theme/sections/components/dataDisplay.js b/packages/react-ui/src/theme/sections/components/dataDisplay.js index fcd242e4d..66b9595e0 100644 --- a/packages/react-ui/src/theme/sections/components/dataDisplay.js +++ b/packages/react-ui/src/theme/sections/components/dataDisplay.js @@ -59,6 +59,12 @@ export const dataDisplayOverrides = { } } } + }, + + '& .MuiListItemButton-root': { + '&:focus-visible': { + backgroundColor: 'transparent' + } } }) } diff --git a/packages/react-ui/src/theme/sections/components/forms.js b/packages/react-ui/src/theme/sections/components/forms.js index e021e262b..26e909c48 100644 --- a/packages/react-ui/src/theme/sections/components/forms.js +++ b/packages/react-ui/src/theme/sections/components/forms.js @@ -194,6 +194,19 @@ export const formsOverrides = { }, '&.Mui-disabled::placeholder': { color: theme.palette.text.disabled + }, + // Remove focus on keyboard navigation as the parent element has focus + '&:focus-visible': { + outline: 'none !important', + boxShadow: 'none !important' + } + }, + + '&.Mui-disabled': { + cursor: 'not-allowed', + + '& .Mui-disabled': { + cursor: 'not-allowed' } }, @@ -332,6 +345,11 @@ export const formsOverrides = { }, '&.Mui-disabled::placeholder': { color: theme.palette.text.disabled + }, + // Remove focus on keyboard navigation as the parent element has focus + '&:focus-visible': { + outline: 'none !important', + boxShadow: 'none !important' } }, @@ -513,6 +531,12 @@ export const formsOverrides = { '&:focus': { background: 'transparent' }, + // Remove focus on keyboard navigation as the parent element has focus + '&:focus-visible': { + outline: 'none !important', + boxShadow: 'none !important' + }, + '& .MuiTypography-root': { whiteSpace: 'nowrap', overflow: 'hidden', @@ -532,13 +556,10 @@ export const formsOverrides = { size: 'small', fullWidth: true, popupIcon: , - clearIcon: , + clearIcon: , ChipProps: { color: 'default' }, limitTags: 1, componentsProps: { - popupIndicator: { - disabled: true - }, paper: { elevation: 8 } @@ -631,7 +652,11 @@ export const formsOverrides = { popupIndicator: ({ theme }) => ({ width: ICON_SIZE_MEDIUM, height: ICON_SIZE_MEDIUM, + cursor: 'text', + '&:hover': { + backgroundColor: 'transparent' + }, '&.MuiButtonBase-root': { color: theme.palette.text.secondary }, diff --git a/packages/react-ui/src/theme/sections/components/navigation.js b/packages/react-ui/src/theme/sections/components/navigation.js index 0365dddcb..09b3a6a63 100644 --- a/packages/react-ui/src/theme/sections/components/navigation.js +++ b/packages/react-ui/src/theme/sections/components/navigation.js @@ -1,7 +1,7 @@ import { ICON_SIZE_MEDIUM } from '../../themeConstants'; export const navigationOverrides = { - // Menu + // Menu Item MuiMenuItem: { styleOverrides: { root: ({ theme }) => ({ @@ -19,6 +19,9 @@ export const navigationOverrides = { '&:focus-visible': { // Solves a known Mui issue: https://github.com/mui/material-ui/issues/23747 backgroundColor: 'transparent', + outline: `none !important`, + boxShadow: `inset 0 0 0 2px ${theme.palette.primary.main} !important`, + borderRadius: theme.shape.borderRadius, '&:hover': { backgroundColor: theme.palette.action.hover @@ -107,6 +110,11 @@ export const navigationOverrides = { '&:hover': { borderBottomColor: theme.palette.text.primary }, + '&:focus-visible': { + outline: `none !important`, + boxShadow: `inset 0 0 0 2px ${theme.palette.primary.main} !important`, + borderRadius: `${theme.shape.borderRadius}px ${theme.shape.borderRadius}px 0 0` + }, '&.Mui-selected': { pointerEvents: 'none', diff --git a/packages/react-ui/src/theme/sections/components/surfaces.js b/packages/react-ui/src/theme/sections/components/surfaces.js index 1d94adb19..dc5d0a9ba 100644 --- a/packages/react-ui/src/theme/sections/components/surfaces.js +++ b/packages/react-ui/src/theme/sections/components/surfaces.js @@ -65,6 +65,10 @@ export const surfacesOverrides = { '&.Mui-disabled': { opacity: 1, color: theme.palette.text.disabled + }, + '&.Mui-focusVisible': { + backgroundColor: 'transparent', + borderRadius: theme.shape.borderRadius } }), expandIconWrapper: ({ theme }) => ({ diff --git a/packages/react-ui/src/theme/sections/cssBaseline.js b/packages/react-ui/src/theme/sections/cssBaseline.js index 1f90ce66b..81156e10e 100644 --- a/packages/react-ui/src/theme/sections/cssBaseline.js +++ b/packages/react-ui/src/theme/sections/cssBaseline.js @@ -3,6 +3,13 @@ import { commonPalette } from './palette'; import { themeTypography } from './typography'; export const CssBaseline = { + // Accessibility focus (keyboard only) + '*:focus-visible': { + outline: `2px solid ${commonPalette.primary.main} !important`, + boxShadow: `0 0 0 4px ${commonPalette.primary.background} !important`, + borderRadius: '4px' + }, + // Custom scrollbars '*::-webkit-scrollbar': { position: 'fixed' diff --git a/packages/react-ui/src/widgets/BarWidgetUI/BarWidgetUI.js b/packages/react-ui/src/widgets/BarWidgetUI/BarWidgetUI.js index 0c9e08927..b5523550c 100644 --- a/packages/react-ui/src/widgets/BarWidgetUI/BarWidgetUI.js +++ b/packages/react-ui/src/widgets/BarWidgetUI/BarWidgetUI.js @@ -248,6 +248,11 @@ function BarWidgetUI(props) { onSelectedBarsChange([], []); } }; + const handleClearPress = (e) => { + if (e.key === 'Enter') { + clearBars(); + } + }; const clickEvent = useCallback( (params) => { @@ -311,7 +316,12 @@ function BarWidgetUI(props) { : intlConfig.formatMessage({ id: 'c4r.widgets.bar.all' })} {selectedBars && selectedBars.length > 0 && ( - clearBars()} underline='hover'> + clearBars()} + onKeyDown={handleClearPress} + underline='hover' + tabIndex={0} + > {intlConfig.formatMessage({ id: 'c4r.widgets.bar.clear' })} )} diff --git a/packages/react-ui/src/widgets/CategoryWidgetUI/CategoryWidgetUI.js b/packages/react-ui/src/widgets/CategoryWidgetUI/CategoryWidgetUI.js index 3e74f4bdf..6ccee369c 100644 --- a/packages/react-ui/src/widgets/CategoryWidgetUI/CategoryWidgetUI.js +++ b/packages/react-ui/src/widgets/CategoryWidgetUI/CategoryWidgetUI.js @@ -92,15 +92,30 @@ function CategoryWidgetUI(props) { const handleClearClicked = () => { props.onSelectedCategoriesChange([]); }; + const handleClearPress = (e) => { + if (e.key === 'Enter') { + handleClearClicked(); + } + }; const handleUnblockClicked = () => { props.onSelectedCategoriesChange([]); setBlockedCategories([]); }; + const handleUnblockPress = (e) => { + if (e.key === 'Enter') { + handleUnblockClicked(); + } + }; const handleBlockClicked = () => { setBlockedCategories(sortBlockedSameAsData(selectedCategories)); }; + const handleBlockPress = (e) => { + if (e.key === 'Enter') { + handleBlockClicked(); + } + }; const handleApplyClicked = () => { const blockedCategoriesOrdered = sortBlockedSameAsData(tempBlockedCategories); @@ -111,6 +126,11 @@ function CategoryWidgetUI(props) { setShowAll(false); setSearchValue(''); }; + const handleApplyPress = (e) => { + if (e.key === 'Enter') { + handleApplyClicked(); + } + }; const handleCancelClicked = () => { setSearchValue(''); @@ -303,6 +323,12 @@ function CategoryWidgetUI(props) { }; }, []); + const handleCategoryPress = (e) => { + if (e.key === 'Enter') { + onCategoryClick(); + } + }; + const unselected = !showAll && selectedCategories.length > 0 && @@ -313,13 +339,18 @@ function CategoryWidgetUI(props) { direction='row' spacing={1} onClick={filterable ? onCategoryClick : () => {}} + onKeyDown={handleCategoryPress} selectable={filterable} unselected={unselected} name={data.name === REST_CATEGORY ? REST_CATEGORY : ''} + tabIndex={filterable && showAll ? 0 : -1} > {filterable && showAll && ( - + )} @@ -371,21 +402,41 @@ function CategoryWidgetUI(props) { : intlConfig.formatMessage({ id: 'c4r.widgets.category.all' })} {showAll ? ( - + {intlConfig.formatMessage({ id: 'c4r.widgets.category.apply' })} ) : blockedCategories.length > 0 ? ( - + {intlConfig.formatMessage({ id: 'c4r.widgets.category.unlock' })} ) : ( selectedCategories.length > 0 && ( - + {intlConfig.formatMessage({ id: 'c4r.widgets.category.lock' })} - + {intlConfig.formatMessage({ id: 'c4r.widgets.category.clear' })} @@ -408,6 +459,9 @@ function CategoryWidgetUI(props) { ) }} + inputProps={{ + tabIndex: 0 + }} /> )} diff --git a/packages/react-ui/src/widgets/CategoryWidgetUI/CategoryWidgetUI.styled.js b/packages/react-ui/src/widgets/CategoryWidgetUI/CategoryWidgetUI.styled.js index 4a11a9908..68a01494a 100644 --- a/packages/react-ui/src/widgets/CategoryWidgetUI/CategoryWidgetUI.styled.js +++ b/packages/react-ui/src/widgets/CategoryWidgetUI/CategoryWidgetUI.styled.js @@ -28,6 +28,10 @@ export const CategoryItemGroup = styled(Grid, { '&:hover .progressbar div': { backgroundColor: theme.palette.secondary.dark + }, + '&:focus-visible': { + outline: `none !important`, + boxShadow: `inset 0 0 0 2px ${theme.palette.primary.main} !important` } }), ...(name === REST_CATEGORY && { diff --git a/packages/react-ui/src/widgets/ChartLegend.js b/packages/react-ui/src/widgets/ChartLegend.js index 129dfa249..a0598c7a4 100644 --- a/packages/react-ui/src/widgets/ChartLegend.js +++ b/packages/react-ui/src/widgets/ChartLegend.js @@ -1,8 +1,11 @@ import React, { useState, useRef, useEffect, useCallback } from 'react'; -import { Box, styled, IconButton, useTheme } from '@mui/material'; +import { useIntl } from 'react-intl'; + +import { Box, styled, IconButton, useTheme, Tooltip } from '@mui/material'; import { ChevronLeft, ChevronRight } from '@mui/icons-material'; import Typography from '../components/atoms/Typography'; +import useImperativeIntl from '../hooks/useImperativeIntl'; const Legend = styled(Box)(({ theme }) => ({ position: 'relative', @@ -15,7 +18,10 @@ const ItemsContainer = styled(Box)(({ theme }) => ({ display: 'flex', flexDirection: 'row', overflowX: 'hidden', - gap: theme.spacing(2) + gap: theme.spacing(2), + // Accessibility tweak to display focus indicator properly + padding: theme.spacing(0.5), + margin: theme.spacing(-0.5) })); const Item = styled(Box)(({ theme }) => ({ @@ -68,6 +74,9 @@ export default function ChartLegend({ series, selectedCategories, onCategoryClic const containerRef = useRef(null); const showMoreButtonsRef = useRef(null); + const intl = useIntl(); + const intlConfig = useImperativeIntl(intl); + const handleClickRight = () => { setOffset(offset + 1); }; @@ -76,6 +85,12 @@ export default function ChartLegend({ series, selectedCategories, onCategoryClic setOffset(Math.max(offset - 1)); }; + const onCategoryPress = (e, categoryName) => { + if (e.key === 'Enter') { + onCategoryClick(categoryName); + } + }; + const updateMaxWidth = useCallback(() => { const overflowing = containerRef.current && @@ -133,7 +148,11 @@ export default function ChartLegend({ series, selectedCategories, onCategoryClic return ( onCategoryClick(category.name) : undefined} + onKeyDown={ + onCategoryClick ? (e) => onCategoryPress(e, category.name) : undefined + } style={{ pointerEvents: !onCategoryClick || category.name === 'Others' ? 'none' : undefined @@ -153,12 +172,20 @@ export default function ChartLegend({ series, selectedCategories, onCategoryClic {(overflowing || offset > 0) && ( - - - - - - + + + + + + + + + + )} diff --git a/packages/react-ui/src/widgets/FeatureSelectionWidgetUI/FeatureSelectionUIGeometryChips.js b/packages/react-ui/src/widgets/FeatureSelectionWidgetUI/FeatureSelectionUIGeometryChips.js index 23ded43c0..c2b3de9b3 100644 --- a/packages/react-ui/src/widgets/FeatureSelectionWidgetUI/FeatureSelectionUIGeometryChips.js +++ b/packages/react-ui/src/widgets/FeatureSelectionWidgetUI/FeatureSelectionUIGeometryChips.js @@ -9,7 +9,7 @@ const ChipList = styled(List)(({ theme }) => ({ display: 'flex', alignItems: 'center', marginLeft: theme.spacing(1.5), - padding: 0, + padding: theme.spacing(0.5), overflowX: 'auto', maxWidth: '100%', scrollbarWidth: 'none', diff --git a/packages/react-ui/src/widgets/HistogramWidgetUI/HistogramWidgetUI.js b/packages/react-ui/src/widgets/HistogramWidgetUI/HistogramWidgetUI.js index 3d0bedcd5..114bda1ba 100644 --- a/packages/react-ui/src/widgets/HistogramWidgetUI/HistogramWidgetUI.js +++ b/packages/react-ui/src/widgets/HistogramWidgetUI/HistogramWidgetUI.js @@ -270,6 +270,12 @@ function HistogramWidgetUI({ 0 ); + const handleClearPress = (e) => { + if (e.key === 'Enter') { + onSelectedBarsChange([]); + } + }; + if (showSkeleton) return ; return ( @@ -285,7 +291,12 @@ function HistogramWidgetUI({ : intlConfig.formatMessage({ id: 'c4r.widgets.histogram.all' })} {selectedBars.length > 0 && ( - onSelectedBarsChange([])} underline='hover'> + onSelectedBarsChange([])} + onKeyDown={handleClearPress} + underline='hover' + tabIndex={0} + > {intlConfig.formatMessage({ id: 'c4r.widgets.histogram.clear' })} )} diff --git a/packages/react-ui/src/widgets/PieWidgetUI/PieWidgetUI.js b/packages/react-ui/src/widgets/PieWidgetUI/PieWidgetUI.js index db6bc97f8..2ba7b0006 100644 --- a/packages/react-ui/src/widgets/PieWidgetUI/PieWidgetUI.js +++ b/packages/react-ui/src/widgets/PieWidgetUI/PieWidgetUI.js @@ -199,6 +199,11 @@ function PieWidgetUI({ const handleClearSelectedCategories = () => { onSelectedCategoriesChange([]); }; + const handleClearPress = (e) => { + if (e.key === 'Enter') { + handleClearSelectedCategories(); + } + }; if (showSkeleton) return ; @@ -215,7 +220,12 @@ function PieWidgetUI({ : intlConfig.formatMessage({ id: 'c4r.widgets.pie.allSelected' })} {selectedCategories.length > 0 && ( - + {intlConfig.formatMessage({ id: 'c4r.widgets.pie.clear' })} )} diff --git a/packages/react-ui/src/widgets/RangeWidgetUI/RangeWidgetUI.js b/packages/react-ui/src/widgets/RangeWidgetUI/RangeWidgetUI.js index 971476dc6..e32aa08b1 100644 --- a/packages/react-ui/src/widgets/RangeWidgetUI/RangeWidgetUI.js +++ b/packages/react-ui/src/widgets/RangeWidgetUI/RangeWidgetUI.js @@ -164,6 +164,12 @@ function RangeWidgetUI({ data, min, max, limits, onSelectedRangeChange, isLoadin changeSliderValues([min, max]); }; + const handleClearPress = (e) => { + if (e.key === 'Enter') { + resetSlider(); + } + }; + if (showSkeleton) { return ; } @@ -173,7 +179,13 @@ function RangeWidgetUI({ data, min, max, limits, onSelectedRangeChange, isLoadin {hasBeenModified && ( - + {intlConfig.formatMessage({ id: 'c4r.widgets.range.clear' })} diff --git a/packages/react-ui/src/widgets/TimeSeriesWidgetUI/TimeSeriesWidgetUI.js b/packages/react-ui/src/widgets/TimeSeriesWidgetUI/TimeSeriesWidgetUI.js index ea3f9b0a9..b899f6bb8 100644 --- a/packages/react-ui/src/widgets/TimeSeriesWidgetUI/TimeSeriesWidgetUI.js +++ b/packages/react-ui/src/widgets/TimeSeriesWidgetUI/TimeSeriesWidgetUI.js @@ -304,6 +304,11 @@ function TimeSeriesWidgetUIContent({ setTimeWindow([]); onSelectedCategoriesChange?.([]); }; + const handleClearPress = (e) => { + if (e.key === 'Enter') { + handleClear(); + } + }; const handleCategoryClick = useCallback( (category) => { @@ -340,6 +345,8 @@ function TimeSeriesWidgetUIContent({ variant='caption' style={{ cursor: 'pointer' }} onClick={handleClear} + onKeyDown={handleClearPress} + tabIndex={0} underline='hover' > {intl.formatMessage({ id: 'c4r.widgets.timeSeries.clear' })} diff --git a/packages/react-ui/src/widgets/WrapperWidgetUI.js b/packages/react-ui/src/widgets/WrapperWidgetUI.js index 2d2673901..06ef08bce 100644 --- a/packages/react-ui/src/widgets/WrapperWidgetUI.js +++ b/packages/react-ui/src/widgets/WrapperWidgetUI.js @@ -69,7 +69,8 @@ const HeaderButton = styled(Button, { alignItems: 'flex-start', justifyContent: 'flex-start', height: 'auto', - minHeight: theme.spacing(4), + minHeight: 'auto', + marginBottom: theme.spacing(1), cursor: expandable ? 'pointer' : 'default', '& .MuiButton-startIcon': { @@ -198,6 +199,7 @@ function WrapperWidgetUI(props) { props.expandable && {expanded ? : } } onClick={handleExpandClick} + tabIndex={props.expandable ? 0 : -1} > @@ -265,6 +267,7 @@ function WrapperWidgetUI(props) { )} + {/* TODO: check collapse error */} diff --git a/packages/react-ui/storybook/stories/organisms/AppBar.stories.js b/packages/react-ui/storybook/stories/organisms/AppBar.stories.js index a679c32d1..de1caa950 100644 --- a/packages/react-ui/storybook/stories/organisms/AppBar.stories.js +++ b/packages/react-ui/storybook/stories/organisms/AppBar.stories.js @@ -157,7 +157,11 @@ const commonArgs = { brandText: 'CARTO', secondaryText: 'Some text', showBurgerMenu: true, - brandLogo: + brandLogo: ( + + + + ) }; export const Basic = Template.bind({}); Basic.args = { ...commonArgs }; diff --git a/packages/react-ui/storybook/stories/organisms/Menu.stories.js b/packages/react-ui/storybook/stories/organisms/Menu.stories.js index 53f82dda6..17917c03d 100644 --- a/packages/react-ui/storybook/stories/organisms/Menu.stories.js +++ b/packages/react-ui/storybook/stories/organisms/Menu.stories.js @@ -1,5 +1,13 @@ -import React from 'react'; -import { Divider, ListItemIcon, ListItemText, MenuItem, MenuList } from '@mui/material'; +import React, { useState } from 'react'; +import { + Divider, + ListItemIcon, + ListItemText, + MenuItem, + MenuList, + Menu, + Box +} from '@mui/material'; import { CloudOutlined, ContentCopyOutlined, @@ -38,7 +46,79 @@ const options = { }; export default options; -const Template = ({ label, ...args }) => { +const TemplateMenu = ({ label, ...args }) => { + const [anchorEl, setAnchorEl] = useState(null); + + const open = Boolean(anchorEl); + + const openDropdown = (event) => { + setAnchorEl(event.currentTarget); + }; + + const closeDropdown = () => { + setAnchorEl(null); + }; + + return ( + + + + + + + + {label} + + ⌘X + + + + + + + {label} + + ⌘C + + + + + + + {label} + + ⌘V + + + + + + + + {label} + + + + ); +}; +const TemplateMenuList = ({ label, ...args }) => { return ( @@ -105,7 +185,10 @@ const DocTemplate = () => { const commonArgs = { label: 'Label', dense: false }; -export const Playground = Template.bind({}); -Playground.args = { ...commonArgs }; - export const Guide = DocTemplate.bind({}); + +export const MenuWrapper = TemplateMenu.bind({}); +MenuWrapper.args = { ...commonArgs }; + +export const MenuListWrapper = TemplateMenuList.bind({}); +MenuListWrapper.args = { ...commonArgs }; diff --git a/packages/react-ui/storybook/stories/widgetsUI/WrapperWidgetUI.stories.js b/packages/react-ui/storybook/stories/widgetsUI/WrapperWidgetUI.stories.js index 3bcd918a3..c1e00b6cf 100644 --- a/packages/react-ui/storybook/stories/widgetsUI/WrapperWidgetUI.stories.js +++ b/packages/react-ui/storybook/stories/widgetsUI/WrapperWidgetUI.stories.js @@ -1,4 +1,5 @@ import React from 'react'; +import { IntlProvider } from 'react-intl'; import ColorizeIcon from '@mui/icons-material/Colorize'; import MenuIcon from '@mui/icons-material/Menu'; import AddLocationIcon from '@mui/icons-material/AddLocation'; @@ -31,14 +32,16 @@ const options = { export default options; const Template = (args) => ( - -
Your Content
-
+ + +
Your Content
+
+
); const ResponsiveTemplate = (args) => { return ( - <> + @@ -54,7 +57,7 @@ const ResponsiveTemplate = (args) => {
Your Content
- +
); }; @@ -192,27 +195,29 @@ WithActionsTooltip.args = { }; export const BigScrollableContent = (args) => ( - -
-

- Note: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam, mi nibh - fames rhoncus id ultricies. Faucibus enim commodo morbi amet sit eget. Ut - pellentesque tellus iaculis diam. Ornare convallis dictum purus quisque nisl. -

-

- Vivamus imperdiet, urna eu blandit lobortis, tortor risus sodales urna, sit amet - tempor eros elit faucibus nulla. Donec vel tellus nec nibh molestie hendrerit. - Donec nulla massa, interdum ut nisl non, sollicitudin condimentum leo. Integer - eget accumsan sem. Aliquam tincidunt turpis et leo ac. -

-

- Vivamus imperdiet, urna eu blandit lobortis, tortor risus sodales urna, sit amet - tempor eros elit faucibus nulla. Donec vel tellus nec nibh molestie hendrerit. - Donec nulla massa, interdum ut nisl non, sollicitudin condimentum leo. Integer - eget accumsan sem. Aliquam tincidunt turpis et leo ac. -

-
-
+ + +
+

+ Note: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam, mi nibh + fames rhoncus id ultricies. Faucibus enim commodo morbi amet sit eget. Ut + pellentesque tellus iaculis diam. Ornare convallis dictum purus quisque nisl. +

+

+ Vivamus imperdiet, urna eu blandit lobortis, tortor risus sodales urna, sit amet + tempor eros elit faucibus nulla. Donec vel tellus nec nibh molestie hendrerit. + Donec nulla massa, interdum ut nisl non, sollicitudin condimentum leo. Integer + eget accumsan sem. Aliquam tincidunt turpis et leo ac. +

+

+ Vivamus imperdiet, urna eu blandit lobortis, tortor risus sodales urna, sit amet + tempor eros elit faucibus nulla. Donec vel tellus nec nibh molestie hendrerit. + Donec nulla massa, interdum ut nisl non, sollicitudin condimentum leo. Integer + eget accumsan sem. Aliquam tincidunt turpis et leo ac. +

+
+
+
); BigScrollableContent.args = { title: 'Big scrollable content',