diff --git a/packages/terra-application/CHANGELOG.md b/packages/terra-application/CHANGELOG.md index acedd6465..2ef015ee8 100644 --- a/packages/terra-application/CHANGELOG.md +++ b/packages/terra-application/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +* Changed + * Added support for theme data density. + ## 1.56.0 - (September 19, 2023) * Changed diff --git a/packages/terra-application/src/application-base/ApplicationBase.jsx b/packages/terra-application/src/application-base/ApplicationBase.jsx index d24773dfd..4caedf53b 100644 --- a/packages/terra-application/src/application-base/ApplicationBase.jsx +++ b/packages/terra-application/src/application-base/ApplicationBase.jsx @@ -65,6 +65,10 @@ const propTypes = { * The name of the theme to apply to the application using terra-theme-provider. */ themeName: PropTypes.string, + /** + * The density of the theme to apply to the application using terra-theme-provider. + */ + themeDensity: PropTypes.string, /** * By default, the elements rendered by ApplicationBase are fit to the Application's parent using 100% height. * If `fitToParentIsDisabled` is provided, the Application will render at its intrinsic content height and @@ -86,7 +90,7 @@ const propTypes = { }; const ApplicationBase = ({ - locale, customTranslatedMessages, translationsLoadingPlaceholder, themeName, fitToParentIsDisabled, children, unloadPromptIsDisabled, noScroll, + locale, customTranslatedMessages, translationsLoadingPlaceholder, themeName, themeDensity, fitToParentIsDisabled, children, unloadPromptIsDisabled, noScroll, }) => { const registeredPromptsRef = useRef(); @@ -122,11 +126,12 @@ const ApplicationBase = ({ // If the theme class name is undefined or an empty string, that indicates we have the root theme and should apply the root theme name. name: themeOverride || themeName || rootThemeName, className: themeOverride || themeName, - }), [themeOverride, themeName]); + density: themeDensity || themeConfig?.density, + }), [themeOverride, themeName, themeDensity]); return (
- + { @@ -44,4 +43,34 @@ describe('ApplicationBase', () => { )); expect(wrapper).toMatchSnapshot(); }); + + it('should render with theme and density', () => { + const wrapper = shallow(( + +
content
+
+ )); + + const themeProvider = wrapper.find('ThemeProvider'); + expect(themeProvider.props().themeName).toBe('test-theme'); + expect(themeProvider.props().density).toBe('compact'); + + const themeContext = wrapper.find('ThemeContextProvider'); + expect(themeContext.props().theme).toStrictEqual({ name: 'test-theme', className: 'test-theme', density: 'compact' }); + }); + + it('should render with density', () => { + const wrapper = shallow(( + +
content
+
+ )); + + const themeProvider = wrapper.find('ThemeProvider'); + expect(themeProvider.props().themeName).toBeUndefined(); + expect(themeProvider.props().density).toBe('compact'); + + const themeContext = wrapper.find('ThemeContextProvider'); + expect(themeContext.props().theme).toStrictEqual({ name: 'terra-default-theme', className: undefined, density: 'compact' }); + }); }); diff --git a/packages/terra-application/tests/jest/application-base/__snapshots__/ApplicationBase.test.jsx.snap b/packages/terra-application/tests/jest/application-base/__snapshots__/ApplicationBase.test.jsx.snap index f6e569b18..6f1611cba 100644 --- a/packages/terra-application/tests/jest/application-base/__snapshots__/ApplicationBase.test.jsx.snap +++ b/packages/terra-application/tests/jest/application-base/__snapshots__/ApplicationBase.test.jsx.snap @@ -12,6 +12,7 @@ exports[`ApplicationBase should render with all props 1`] = ` theme={ Object { "className": "test-theme", + "density": undefined, "name": "test-theme", } } @@ -73,6 +74,7 @@ exports[`ApplicationBase should render with minimal props 1`] = ` theme={ Object { "className": undefined, + "density": undefined, "name": "terra-default-theme", } } @@ -125,6 +127,7 @@ exports[`ApplicationBase should render with the preferred browser local 1`] = ` theme={ Object { "className": undefined, + "density": undefined, "name": "terra-default-theme", } } @@ -177,6 +180,7 @@ exports[`ApplicationBase should render without scroll 1`] = ` theme={ Object { "className": undefined, + "density": undefined, "name": "terra-default-theme", } } diff --git a/packages/terra-application/tests/jest/application-navigation/private/utility-menu/__snapshots__/UtilityMenu.test.jsx.snap b/packages/terra-application/tests/jest/application-navigation/private/utility-menu/__snapshots__/UtilityMenu.test.jsx.snap index 6ee89759f..a96c7c4e8 100644 --- a/packages/terra-application/tests/jest/application-navigation/private/utility-menu/__snapshots__/UtilityMenu.test.jsx.snap +++ b/packages/terra-application/tests/jest/application-navigation/private/utility-menu/__snapshots__/UtilityMenu.test.jsx.snap @@ -744,7 +744,7 @@ exports[`UtilityMenu should render with function callbacks 1`] = ` type="button" > { const appSettings = React.useContext(AppSettingsContext); - const [state, setState] = useState({ locale: appSettings.currentLocale, theme: appSettings.currentTheme, direction: appSettings.currentDirection }); + const [state, setState] = useState({ + locale: appSettings.currentLocale, theme: appSettings.currentTheme, density: appSettings.currentDensity, direction: appSettings.currentDirection, + }); const { - locale, theme, direction, + locale, theme, density, direction, } = state; const { locales, themes, directions } = appSettings; const disclosureManager = React.useContext(DisclosureManagerContext); @@ -41,6 +43,7 @@ const SettingsModal = () => { appSettings.onUpdate({ locale, theme, + density, direction, }); disclosureManager.dismiss(); @@ -74,6 +77,7 @@ const SettingsModal = () => { setState({ locale: event.currentTarget.value, theme, + density, direction, }); }} @@ -95,6 +99,7 @@ const SettingsModal = () => { setState({ locale, theme: event.currentTarget.value, + density, direction, }); }} @@ -102,6 +107,26 @@ const SettingsModal = () => { /> ) : undefined} + + { + setState({ + locale, + theme, + density: event.currentTarget.value, + direction, + }); + }} + options={[{ value: 'compact', display: 'compact' }, { value: 'comfortable', display: 'comfortable' }, { value: 'spacious', display: 'spacious' }]} + /> + {directions.length > 1 ? ( { const { defaultLocale = 'en', defaultTheme = defaultThemeName, + defaultDensity = themesConfig.density, defaultDirection = 'ltr', } = settingsConfig; const [currentLocale, setCurrentLocale] = useState(defaultLocale); const [currentDirection, setCurrentDirection] = useState(defaultDirection); const [currentTheme, setCurrentTheme] = useState(defaultTheme); + const [currentDensity, setCurrentDensity] = useState(defaultDensity); /** * Place settings on dom @@ -74,7 +76,9 @@ const AppSettingsProvider = ({ settingsConfig, children }) => { * Handle setting update and store new settings in state. * @param {*} newSettings */ - const onUpdate = ({ locale, theme, direction }) => { + const onUpdate = ({ + locale, theme, density, direction, + }) => { if (locale) { setCurrentLocale(locale); } @@ -83,6 +87,10 @@ const AppSettingsProvider = ({ settingsConfig, children }) => { setCurrentTheme(theme); } + if (density) { + setCurrentDensity(density); + } + if (direction) { setCurrentDirection(direction); } @@ -92,13 +100,14 @@ const AppSettingsProvider = ({ settingsConfig, children }) => { locales, currentLocale, currentTheme, + currentDensity, currentDirection, directions: ['ltr', 'rtl'], themes, currentThemeClassName: themesMap[currentTheme], onUpdate, }); - }, [currentLocale, currentTheme, currentDirection]); + }, [currentLocale, currentTheme, currentDensity, currentDirection]); return ( diff --git a/packages/terra-dev-site/src/site/_DevSiteApplicationBase.jsx b/packages/terra-dev-site/src/site/_DevSiteApplicationBase.jsx index 91a655e5f..38ccefe1b 100644 --- a/packages/terra-dev-site/src/site/_DevSiteApplicationBase.jsx +++ b/packages/terra-dev-site/src/site/_DevSiteApplicationBase.jsx @@ -18,12 +18,13 @@ const propTypes = { const DevSiteApplicationContainer = ({ children, ApplicationBase }) => { const isRaw = useRouteMatch('/raw'); - const { currentLocale, currentThemeClassName } = React.useContext(AppSettingsContext); + const { currentLocale, currentThemeClassName, currentDensity } = React.useContext(AppSettingsContext); const AppBase = ApplicationBase || TerraApplicationBase; return ( diff --git a/packages/terra-dev-site/tests/jest/site/AppSettingsProvider.test.jsx b/packages/terra-dev-site/tests/jest/site/AppSettingsProvider.test.jsx index f6323e974..240eb38d7 100644 --- a/packages/terra-dev-site/tests/jest/site/AppSettingsProvider.test.jsx +++ b/packages/terra-dev-site/tests/jest/site/AppSettingsProvider.test.jsx @@ -18,6 +18,7 @@ describe('ThemeContextProvider', () => { const config = { defaultLocale: 'es', defaultTheme: 'my theme', + defaultDensity: 'compact', defaultDirection: 'rtl', }; const wrapper = shallow(( diff --git a/packages/terra-dev-site/tests/jest/site/__snapshots__/AppSettingsProvider.test.jsx.snap b/packages/terra-dev-site/tests/jest/site/__snapshots__/AppSettingsProvider.test.jsx.snap index 3a76d4446..0cb3093fe 100644 --- a/packages/terra-dev-site/tests/jest/site/__snapshots__/AppSettingsProvider.test.jsx.snap +++ b/packages/terra-dev-site/tests/jest/site/__snapshots__/AppSettingsProvider.test.jsx.snap @@ -4,6 +4,7 @@ exports[`ThemeContextProvider Snapshots should render with default config specif