diff --git a/CHANGELOG.md b/CHANGELOG.md index c11ac2ae50..0a7c34f088 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Fixed Shift+Tab navigation from `DropdownSelectedItem` @silviuavram ([#1004](https://github.com/stardust-ui/react/pull/1004)) - Fixed color of the `timestamp` in `ChatMessages` marked as `mine` in Teams theme @mnajdova ([#1010](https://github.com/stardust-ui/react/pull/1010)) - Updated table `Icon` & search `Icon` ([#1011](https://github.com/stardust-ui/react/pull/1011)) +- Improve `Menu` styling, vertical menu in Teams theme ([#934](https://github.com/stardust-ui/react/pull/934)) ### Features - Add `delay` prop for `Loader` component @layershifter ([#969](https://github.com/stardust-ui/react/pull/969)) diff --git a/docs/src/components/Sidebar/Sidebar.tsx b/docs/src/components/Sidebar/Sidebar.tsx index e1d0f33f6a..0bf919b7e7 100644 --- a/docs/src/components/Sidebar/Sidebar.tsx +++ b/docs/src/components/Sidebar/Sidebar.tsx @@ -134,12 +134,14 @@ class Sidebar extends React.Component { paddingRight: '0em', paddingTop: '0em', paddingBottom: '0em', + background: '#201f1f', } const menuSectionStyles: ICSSInJSStyle = { fontWeight: fontWeightBold, margin: '0 0 .5rem', padding: '0 1.2857rem', + background: '#201f1f', color: 'white', ':hover': { background: 'none', @@ -157,6 +159,7 @@ class Sidebar extends React.Component { fontSize: '0.85714286em', fontWeight: 400, color: '#ffffff80', + background: '#201f1f', ':hover': { color: 'white', backgroundColor: 'none', @@ -170,11 +173,13 @@ class Sidebar extends React.Component { const dividerStyles: ICSSInJSStyle = { marginTop: '.5em', paddingBottom: '.5em', + background: '#201f1f', } const navBarStyles: ICSSInJSStyle = { color: '#ffffff80', padding: '0px', + backgroundColor: '#201f1f', } const logoStyles: ICSSInJSStyle = { diff --git a/docs/src/examples/components/Menu/Usages/MenuExampleToolbar.shorthand.tsx b/docs/src/examples/components/Menu/Usages/MenuExampleToolbar.shorthand.tsx index fa85ac5e90..5cb5bd5660 100644 --- a/docs/src/examples/components/Menu/Usages/MenuExampleToolbar.shorthand.tsx +++ b/docs/src/examples/components/Menu/Usages/MenuExampleToolbar.shorthand.tsx @@ -66,7 +66,7 @@ const items = [ 'aria-label': 'Book Tool', }, { - key: 'menuButton', + key: 'menuButton2', icon: { name: 'more', outline: true, @@ -74,18 +74,50 @@ const items = [ accessibility: toolbarButtonBehavior, 'aria-label': 'More options', indicator: false, - menu: [ - { key: '1', content: 'item1' }, - { - key: '2', - content: 'item2', - }, - { - key: '3', - content: 'item3', - menu: [{ key: '1', content: 'item3.1' }, { key: '2', content: 'item3.2' }], - }, - ], + menu: { + items: [ + { + key: '5', + content: 'item1', + icon: { + name: 'bookmark', + outline: true, + }, + }, + { + key: 'divider', + kind: 'divider', + }, + { + key: '6', + content: 'item2', + icon: { + name: 'mark-as-unread', + outline: true, + }, + }, + { + key: '7', + content: 'item3', + icon: { + name: 'translation', + outline: true, + }, + }, + { + key: 'divider2', + kind: 'divider', + }, + { + key: '8', + content: 'item3', + icon: { + name: 'trash-can', + outline: true, + }, + }, + ], + }, }, ] diff --git a/packages/react/src/components/Menu/Menu.tsx b/packages/react/src/components/Menu/Menu.tsx index fab8fa8943..e470ea4f90 100644 --- a/packages/react/src/components/Menu/Menu.tsx +++ b/packages/react/src/components/Menu/Menu.tsx @@ -166,6 +166,7 @@ class Menu extends AutoControlledComponent, MenuState> { vertical, variables, styles: styles.divider, + inSubmenu: submenu, }, }) } diff --git a/packages/react/src/components/Menu/MenuDivider.tsx b/packages/react/src/components/Menu/MenuDivider.tsx index c98890fcc9..a10b10abc6 100644 --- a/packages/react/src/components/Menu/MenuDivider.tsx +++ b/packages/react/src/components/Menu/MenuDivider.tsx @@ -30,6 +30,7 @@ export interface MenuDividerProps vertical?: boolean primary?: boolean secondary?: boolean + inSubmenu?: boolean } /** @@ -52,6 +53,7 @@ class MenuDivider extends UIComponent> { primary: PropTypes.bool, secondary: PropTypes.bool, vertical: PropTypes.bool, + inSubmenu: PropTypes.bool, } renderComponent({ ElementType, classes, unhandledProps, accessibility }) { diff --git a/packages/react/src/themes/teams-dark/components/Menu/menuVariables.ts b/packages/react/src/themes/teams-dark/components/Menu/menuVariables.ts index 88b7a92609..4f5937ea75 100644 --- a/packages/react/src/themes/teams-dark/components/Menu/menuVariables.ts +++ b/packages/react/src/themes/teams-dark/components/Menu/menuVariables.ts @@ -1,9 +1,16 @@ -export interface MenuVariables { - color: string -} - -export default (siteVars: any): MenuVariables => { - return { - color: siteVars.colors.white, - } -} +import { pxToRem } from '../../../../lib' +import { MenuVariables } from '../../../teams/components/Menu/menuVariables' + +export default (siteVars: any): Partial => ({ + verticalBorderColor: siteVars.black, + + focusedBorder: `solid ${pxToRem(1)} ${siteVars.colors.white}`, + focusedBackgroundColor: 'transparent', + + hoverBackgroundColor: siteVars.gray08, + + activeColor: siteVars.colors.white, + activeBackgroundColor: siteVars.gray08, + + verticalBackgroundColor: siteVars.gray10, +}) diff --git a/packages/react/src/themes/teams-dark/siteVariables.ts b/packages/react/src/themes/teams-dark/siteVariables.ts index c553dea107..6064d903db 100644 --- a/packages/react/src/themes/teams-dark/siteVariables.ts +++ b/packages/react/src/themes/teams-dark/siteVariables.ts @@ -30,11 +30,6 @@ export const red = '#d74654' // no mapping color export const red08 = '#4f232b' // no mapping color export const green04 = naturalColors.lightGreen[900] -// -// SHADOW LEVELS -// -export const shadowLevel1 = '0 .2rem .4rem -.075rem rgba(255, 255, 255, 0.1)' - // // SEMANTIC ASSIGNMENTS // diff --git a/packages/react/src/themes/teams-high-contrast/components/Menu/menuItemStyles.ts b/packages/react/src/themes/teams-high-contrast/components/Menu/menuItemStyles.ts index 89bb4bc300..c9e3aa6d45 100644 --- a/packages/react/src/themes/teams-high-contrast/components/Menu/menuItemStyles.ts +++ b/packages/react/src/themes/teams-high-contrast/components/Menu/menuItemStyles.ts @@ -1,27 +1,50 @@ import { ComponentSlotStylesInput, ICSSInJSStyle } from '../../../types' -import { MenuVariables } from './menuVariables' +import { MenuVariables } from '../../../teams/components/Menu/menuVariables' import { MenuItemProps, MenuItemState } from '../../../../components/Menu/MenuItem' type MenuItemPropsAndState = MenuItemProps & MenuItemState const menuItemStyles: ComponentSlotStylesInput = { - wrapper: ({ props, variables }): ICSSInJSStyle => { - const { iconOnly, isFromKeyboard } = props + wrapper: ({ props: p, variables: v }): ICSSInJSStyle => { + const { iconOnly, isFromKeyboard, vertical, active, underlined, primary } = p return { - ...(iconOnly && { - // focus styles + ':hover': { + color: v.activeColor, + ...(!active && { + background: v.focusedBackgroundColor, + }), + }, + + ...(active && { + background: v.activeBackgroundColor, + color: v.activeColor, + }), + + ...((iconOnly || vertical) && { ...(isFromKeyboard && { - color: variables.activeColor, - background: variables.activeBackgroundColor, + color: v.activeColor, + background: v.focusedBackgroundColor, + }), + + ...(active && { + color: v.activeColor, + background: v.activeBackgroundColor, }), - // hover styles ':hover': { - color: variables.activeColor, - background: variables.activeBackgroundColor, + color: v.activeColor, + background: v.focusedBackgroundColor, }, }), + + ...((underlined || primary) && { + ...(!active && { + ':hover': { + color: v.color, + }, + }), + }), } }, diff --git a/packages/react/src/themes/teams-high-contrast/components/Menu/menuVariables.ts b/packages/react/src/themes/teams-high-contrast/components/Menu/menuVariables.ts index 5ca3949a01..4c5f3a40a3 100644 --- a/packages/react/src/themes/teams-high-contrast/components/Menu/menuVariables.ts +++ b/packages/react/src/themes/teams-high-contrast/components/Menu/menuVariables.ts @@ -1,13 +1,10 @@ -export interface MenuVariables { - color: string - activeColor: string - activeBackgroundColor: string -} +import { MenuVariables } from '../../../teams/components/Menu/menuVariables' -export default (siteVars: any): MenuVariables => { - return { - color: siteVars.white, - activeColor: siteVars.black, - activeBackgroundColor: siteVars.accessibleYellow, - } -} +export default (siteVars: any): Partial => ({ + color: siteVars.white, + activeColor: siteVars.black, + focusedBackgroundColor: siteVars.accessibleYellow, + activeBackgroundColor: siteVars.accessibleCyan, + + verticalBackgroundColor: siteVars.colors.black, +}) diff --git a/packages/react/src/themes/teams/components/Menu/menuDividerStyles.ts b/packages/react/src/themes/teams/components/Menu/menuDividerStyles.ts index 450a610dee..31a2d14f9b 100644 --- a/packages/react/src/themes/teams/components/Menu/menuDividerStyles.ts +++ b/packages/react/src/themes/teams/components/Menu/menuDividerStyles.ts @@ -19,6 +19,10 @@ const menuDividerStyles: ComponentSlotStylesInput ({ }) const getActionStyles = ({ - props: { primary, underlined, iconOnly, isFromKeyboard }, + props: { primary, underlined, iconOnly }, variables: v, color, }: { @@ -48,8 +48,8 @@ const getFocusedStyles = ({ variables: MenuVariables color: string }): ICSSInJSStyle => { - const { primary, underlined, isFromKeyboard, active } = props - if (active && !underlined) return {} + const { primary, underlined, isFromKeyboard, active, vertical, pointing } = props + if (active && !underlined && !vertical) return {} return { ...(underlined && !isFromKeyboard ? { @@ -62,8 +62,17 @@ const getFocusedStyles = ({ } : { color, - background: v.focusedBackgroundColor, + background: v.hoverBackgroundColor, }), + + ...(vertical && isFromKeyboard && !pointing && !primary + ? { + border: v.focusedBorder, + outline: v.focusedOutline, + margin: pxToRem(1), + background: v.focusedBackgroundColor, + } + : {}), } } @@ -71,19 +80,20 @@ const itemSeparator: ComponentSlotStyleFunction { - const { iconOnly, pointing, pills, primary, underlined, vertical } = props + const { iconOnly, pills, primary, underlined, vertical } = props return ( + !vertical && !pills && !underlined && - !(pointing && vertical) && !iconOnly && { '::before': { position: 'absolute', content: '""', top: 0, right: 0, - ...(vertical ? { width: '100%', height: '1px' } : { width: '1px', height: '100%' }), + width: pxToRem(1), + height: '100%', ...(primary ? { background: v.primaryBorderColor } : { background: v.borderColor }), }, } @@ -168,6 +178,10 @@ const menuItemStyles: ComponentSlotStylesInput { + root: ({ props: p, variables: v }): ICSSInJSStyle => { const { active, iconOnly, @@ -284,7 +284,7 @@ const menuItemStyles: ComponentSlotStylesInput ({ + menu: ({ props: p }) => ({ zIndex: '1000', position: 'absolute', - top: vertical ? '0' : '100%', - left: vertical ? '100%' : '0', + top: p.vertical ? '0' : '100%', + left: p.vertical ? '100%' : '0', }), indicator: () => ({ diff --git a/packages/react/src/themes/teams/components/Menu/menuStyles.ts b/packages/react/src/themes/teams/components/Menu/menuStyles.ts index f9e066f68c..dfbff64008 100644 --- a/packages/react/src/themes/teams/components/Menu/menuStyles.ts +++ b/packages/react/src/themes/teams/components/Menu/menuStyles.ts @@ -10,18 +10,24 @@ import { type MenuPropsAndState = MenuProps & MenuState -const solidBorder = (color: string) => ({ - border: `1px solid ${color}`, -}) - export default { - root: ({ props, variables }): ICSSInJSStyle => { - const { iconOnly, fluid, pointing, pills, primary, underlined, vertical } = props + root: ({ props: p, variables: v }): ICSSInJSStyle => { + const { iconOnly, fluid, pointing, pills, primary, underlined, vertical, submenu } = p + return { display: 'flex', + minHeight: pxToRem(24), + margin: 0, + padding: 0, + listStyleType: 'none', ...(iconOnly && { alignItems: 'center' }), ...(vertical && { flexDirection: 'column', + backgroundColor: v.verticalBackgroundColor, + padding: `${pxToRem(8)} 0`, + ...(submenu && { + boxShadow: v.verticalBoxShadow, + }), ...(!fluid && { width: pxToRem(200) }), ...(iconOnly && { display: 'inline-block', @@ -32,19 +38,15 @@ export default { !iconOnly && !(pointing && vertical) && !underlined && { - ...solidBorder(variables.borderColor), + border: `${v.borderWidth} solid ${v.borderColor}`, ...(primary && { - ...solidBorder(variables.primaryBorderColor), + border: `${v.borderWidth} solid ${v.primaryBorderColor}`, }), borderRadius: pxToRem(4), }), ...(underlined && { - borderBottom: `2px solid ${variables.primaryUnderlinedBorderColor}`, + borderBottom: `${v.underlinedBottomBorderWidth} solid ${v.primaryUnderlinedBorderColor}`, }), - minHeight: pxToRem(24), - margin: 0, - padding: 0, - listStyleType: 'none', } }, divider: ({ props: { pointing, vertical, pills } }) => ({ diff --git a/packages/react/src/themes/teams/components/Menu/menuVariables.ts b/packages/react/src/themes/teams/components/Menu/menuVariables.ts index edd0b0bf23..d7a4c315a2 100644 --- a/packages/react/src/themes/teams/components/Menu/menuVariables.ts +++ b/packages/react/src/themes/teams/components/Menu/menuVariables.ts @@ -2,13 +2,19 @@ import { pxToRem } from '../../../../lib' export interface MenuVariables { color: string + borderColor: string + verticalBorderColor: string - activeColor: string - activeBackgroundColor: string + focusedBorder: string + focusedOutline: string focusedBackgroundColor: string - borderColor: string + hoverBackgroundColor: string + + activeColor: string + activeBackgroundColor: string iconOnlyActiveColor: string + primaryActiveColor: string primaryActiveBackgroundColor: string primaryActiveBorderColor: string @@ -21,22 +27,36 @@ export interface MenuVariables { primaryUnderlinedBorderColor: string disabledColor: string - lineHeightBase: string - horizontalPadding: string + + verticalBackgroundColor: string + verticalItemPadding: string + verticalBoxShadow: string + verticalDividerMargin: string + verticalItemBorder: string + + underlinedBottomBorderWidth: string + + dividerHeight: string + borderWidth: string } export default (siteVars: any): MenuVariables => { return { color: siteVars.gray02, + borderColor: siteVars.gray08, + verticalBorderColor: siteVars.gray08, - iconOnlyActiveColor: siteVars.colors.primary[500], + focusedBorder: `solid ${pxToRem(1)} ${siteVars.colors.white}`, + focusedOutline: `solid ${pxToRem(1)} ${siteVars.colors.black}`, + focusedBackgroundColor: siteVars.gray09, - activeColor: siteVars.colors.grey[900], + hoverBackgroundColor: siteVars.gray14, + + activeColor: siteVars.colors.black, activeBackgroundColor: siteVars.gray10, - focusedBackgroundColor: siteVars.gray14, - borderColor: siteVars.gray08, + iconOnlyActiveColor: siteVars.colors.primary[500], primaryActiveColor: siteVars.colors.white, primaryActiveBackgroundColor: siteVars.brand08, @@ -45,14 +65,23 @@ export default (siteVars: any): MenuVariables => { primaryFocusedColor: siteVars.colors.white, primaryFocusedBackgroundColor: siteVars.colors.primary[200], - primaryBorderColor: siteVars.brand08, + primaryBorderColor: siteVars.gray10, primaryHoverBorderColor: siteVars.gray08, primaryUnderlinedBorderColor: siteVars.gray08, disabledColor: siteVars.gray06, - lineHeightBase: siteVars.lineHeightMedium, - horizontalPadding: `${pxToRem(14)} ${pxToRem(18)} ${pxToRem(14)} ${pxToRem(18)}`, + + verticalBackgroundColor: siteVars.colors.white, + verticalItemPadding: `${pxToRem(9)} ${pxToRem(16)} ${pxToRem(9)} ${pxToRem(16)}`, + verticalBoxShadow: siteVars.shadowLevel3, + verticalDividerMargin: `${pxToRem(8)} 0`, + verticalItemBorder: `solid ${pxToRem(2)} transparent`, + + underlinedBottomBorderWidth: pxToRem(2), + + dividerHeight: pxToRem(1), + borderWidth: pxToRem(1), } } diff --git a/packages/react/src/themes/teams/siteVariables.ts b/packages/react/src/themes/teams/siteVariables.ts index 860b1016c3..5225ae026f 100644 --- a/packages/react/src/themes/teams/siteVariables.ts +++ b/packages/react/src/themes/teams/siteVariables.ts @@ -30,7 +30,11 @@ export const red08 = '#F3D6DB' // no mapping color // // SHADOW LEVELS // -export const shadowLevel1 = '0 .2rem .4rem -.075rem rgba(0, 0, 0, 0.1)' +export const shadowLevel1 = '0 .2rem .4rem -.075rem rgba(0, 0, 0, .1)' +export const shadowLevel2 = '0 .4rem 0.7rem -0.1rem rgba(0, 0, 0, .1)' +export const shadowLevel3 = '0 .8rem 1rem -0.2rem rgba(0, 0, 0, .1)' +export const shadowLevel4 = '0 .6rem 1.8rem -0.4rem rgba(0, 0, 0, .1)' + export const shadowLevel1Darker = '0 .2rem .4rem -.075rem rgba(0, 0, 0, 0.5)' //