diff --git a/.styleguidist/styleguidist.sections.js b/.styleguidist/styleguidist.sections.js index cec5fad61..9403cc076 100644 --- a/.styleguidist/styleguidist.sections.js +++ b/.styleguidist/styleguidist.sections.js @@ -134,8 +134,9 @@ module.exports = { { name: 'LanguageMenu', components: getComponentWithVariants('LanguageMenu')([ - 'LanguageMenuItemLanguage', - 'LanguageMenuLinkLanguage', + 'LanguageMenu/LanguageMenu', + 'LanguageMenuItem/LanguageMenuItem', + 'LanguageMenuLink/LanguageMenuLink', ]), }, { diff --git a/src/components/LanguageMenu/LanguageMenu.tsx b/src/components/LanguageMenu/LanguageMenu.tsx deleted file mode 100644 index 297d1b6f6..000000000 --- a/src/components/LanguageMenu/LanguageMenu.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import React, { Component, ReactNode, Fragment } from 'react'; -import classnames from 'classnames'; -import { HtmlSpan } from '../../reset/HtmlSpan/HtmlSpan'; -import { - Menu, - MenuButton, - MenuItems, - MenuItem, - MenuLink, - MenuPopover, - MenuPopoverProps, -} from '@reach/menu-button'; -import { positionDefault } from '@reach/popover'; -import { PRect } from '@reach/rect'; -import { logger } from '../../utils/logger'; - -export { MenuItems, MenuItem, MenuLink, MenuPopover, MenuPopoverProps, PRect }; - -const baseClassName = 'fi-language-menu'; -export interface LanguageMenuItemProps { - /** Operation to run on select */ - onSelect: () => void; - /** Item content */ - children: ReactNode; -} - -type SupportedMenuLinkComponent = keyof JSX.IntrinsicElements; - -interface LanguageMenuLinkPropsWithType { - type: 'menulink'; - /** Url to direct to */ - href: string; - /** Item content */ - children: ReactNode; - className?: string; - as?: SupportedMenuLinkComponent; -} - -export interface LanguageMenuLinkProps - extends Omit {} - -export type LanguageMenuPopoverItemsProps = - | LanguageMenuItemProps - | LanguageMenuLinkPropsWithType; -type OptionalLanguageMenuPopoverProps = { - [K in keyof MenuPopoverProps]?: MenuPopoverProps[K]; -}; - -export interface LanguageMenuProps { - /** Name or content of menubutton */ - name: React.ReactNode | ((props: { isOpen: boolean }) => React.ReactNode); - /** Custom classname to extend or customize */ - className?: string; - /** Custom classname to extend or customize */ - languageMenuButtonClassName?: string; - /** Custom classname to apply when menu is open */ - languageMenuOpenButtonClassName?: string; - /** Properties given to LanguageMenu's popover-component, className etc. */ - languageMenuPopoverProps?: OptionalLanguageMenuPopoverProps; - languageMenuPopoverComponent?: React.ComponentType; - /** Menu items: MenuItem or MenuLink */ - children?: - | Array> - | null - | undefined; -} - -export class LanguageMenu extends Component { - render() { - const { - children, - name, - className, - languageMenuButtonClassName: menuButtonClassName, - languageMenuOpenButtonClassName: menuButtonOpenClassName, - languageMenuPopoverProps: menuPopoverProps = {}, - languageMenuPopoverComponent: MenuPopoverComponentReplace, - ...passProps - } = this.props; - - if (React.Children.count(children) < 1) { - logger.warn(`Menu '${name}' does not contain items`); - return null; - } - return ( - - - {({ isOpen }: { isOpen: boolean }) => ( - - - {name} - - {!!MenuPopoverComponentReplace ? ( - - {children} - - ) : ( - - {children} - - )} - - )} - - - ); - } -} diff --git a/src/components/README.md b/src/components/README.md deleted file mode 100644 index e647d154d..000000000 --- a/src/components/README.md +++ /dev/null @@ -1 +0,0 @@ -# VRK suomifi-ui-components diff --git a/src/components/index.ts b/src/components/index.ts deleted file mode 100644 index f800e1cb1..000000000 --- a/src/components/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { - LanguageMenu, - LanguageMenuProps, - LanguageMenuPopoverItemsProps, - LanguageMenuItemProps, - LanguageMenuLinkProps as MenuLinkProps, - MenuItem, - MenuLink, -} from './LanguageMenu/LanguageMenu'; diff --git a/src/core/LanguageMenu/LanguageMenu.tsx b/src/core/LanguageMenu/LanguageMenu.tsx deleted file mode 100644 index 9948d36cc..000000000 --- a/src/core/LanguageMenu/LanguageMenu.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import React, { Component, ReactNode, Fragment } from 'react'; -import { default as styled } from 'styled-components'; -import classnames from 'classnames'; -import { classnamesValue } from '../../utils/typescript'; -import { - LanguageMenu as CompLanguageMenu, - LanguageMenuProps as CompLanguageMenuProps, - LanguageMenuPopoverItemsProps, - MenuItems as CompMenuItems, - MenuPopover as CompMenuPopover, - MenuPopoverProps as CompMenuPopoverProps, - PRect, -} from '../../components/LanguageMenu/LanguageMenu'; -import { - LanguageMenuItemLanguage, - LanguageMenuItemLanguageProps, - LanguageMenuLinkLanguage, - LanguageMenuLinkLanguageProps, -} from './LanguageMenuItem'; -import { - baseStyles, - languageMenuPopoverStyles, -} from './LanguageMenu.baseStyles'; - -import { Icon } from '../Icon/Icon'; - -const itemClassName = 'fi-language-menu_item'; -const itemLangClassName = 'fi-language-menu-language_item'; -const buttonClassName = 'fi-language-menu_button'; -const buttonOpenClassName = 'fi-language-menu-language_button_open'; -const buttonLangClassName = 'fi-language-menu-language_button'; - -const popoverClassName = 'fi-language-menu_popover'; -const popoverLangClassName = 'fi-language-menu-language_popover'; -const iconLangClassName = 'fi-language-menu-language_icon'; - -export interface LanguageMenuProps extends CompLanguageMenuProps {} - -const StyledLanguageMenu = styled((props: LanguageMenuProps) => ( - -))` - ${baseStyles} -`; - -const LanguageMenuPopoverWithProps = ( - children: ReactNode, - addClass?: classnamesValue, -) => - React.Children.map( - children, - (child: React.ReactElement) => { - // Set defaul component-prop/type to be 'a' needed for links - if (React.isValidElement(child)) { - return React.cloneElement(child, { - as: 'a', - className: classnames(itemClassName, addClass), - }); - } - return child; - }, - ); - -const languageName = (name: ReactNode) => ( - - {name} - - -); - -interface LanguageMenuPopoverProps extends CompMenuPopoverProps {} - -const LanguageMenuPopoverPosition = ( - targetRect: PRect | null, - popoverRect: PRect | null, -): React.CSSProperties => { - if (!targetRect || !popoverRect) { - return {}; - } - return { - left: `${targetRect.left - popoverRect.width + targetRect.width}px`, - // eslint-disable-next-line no-undef - top: `${targetRect.top + targetRect.height + window.pageYOffset}px`, - maxWidth: `${Math.max( - targetRect.width, - targetRect.width + targetRect.left - 30, - )}px`, - minWidth: `${targetRect.width - 2}px`, - }; -}; - -const StyledMenuPopover = styled( - ({ children, ...passProps }: LanguageMenuPopoverProps) => ( - - {children} - - ), -)` - ${languageMenuPopoverStyles} -`; - -class LanguageMenuVariation extends Component { - render() { - const { - children, - name, - className, - languageMenuPopoverComponent: MenuPopoverComponentProp, - ...passProps - } = this.props; - const languageMenuButtonClassName = classnames( - buttonClassName, - buttonLangClassName, - className, - ); - const menuPopoverProps = { - className: classnames(popoverClassName, popoverLangClassName), - }; - - return ( - - - {LanguageMenuPopoverWithProps(children, itemLangClassName)} - - - ); - } -} - -/** - * - * Use for dropdown menu. - */ -export class LanguageMenu extends Component { - static languageItem = (props: LanguageMenuItemLanguageProps) => ( - - ); - - static LinkLanguage = (props: LanguageMenuLinkLanguageProps) => ( - - ); - - render() { - return ; - } -} diff --git a/src/core/LanguageMenu/LanguageMenu.baseStyles.tsx b/src/core/LanguageMenu/LanguageMenu/LanguageMenu.baseStyles.tsx similarity index 95% rename from src/core/LanguageMenu/LanguageMenu.baseStyles.tsx rename to src/core/LanguageMenu/LanguageMenu/LanguageMenu.baseStyles.tsx index bca353cde..9a17c6f58 100644 --- a/src/core/LanguageMenu/LanguageMenu.baseStyles.tsx +++ b/src/core/LanguageMenu/LanguageMenu/LanguageMenu.baseStyles.tsx @@ -1,7 +1,7 @@ import { css } from 'styled-components'; -import { defaultThemeTokens as theme } from '../theme'; -import { element } from '../theme/reset'; -import { absoluteFocus } from '../theme/utils/focus'; +import { defaultThemeTokens as theme } from '../../theme'; +import { element } from '../../theme/reset'; +import { absoluteFocus } from '../../theme/utils/focus'; export const baseStyles = css` & > [data-reach-menu-button].fi-language-menu_button { diff --git a/src/core/LanguageMenu/LanguageMenu.md b/src/core/LanguageMenu/LanguageMenu/LanguageMenu.md similarity index 100% rename from src/core/LanguageMenu/LanguageMenu.md rename to src/core/LanguageMenu/LanguageMenu/LanguageMenu.md diff --git a/src/core/LanguageMenu/LanguageMenu.test.tsx b/src/core/LanguageMenu/LanguageMenu/LanguageMenu.test.tsx similarity index 84% rename from src/core/LanguageMenu/LanguageMenu.test.tsx rename to src/core/LanguageMenu/LanguageMenu/LanguageMenu.test.tsx index 353dca6f1..8753b56fa 100644 --- a/src/core/LanguageMenu/LanguageMenu.test.tsx +++ b/src/core/LanguageMenu/LanguageMenu/LanguageMenu.test.tsx @@ -1,9 +1,10 @@ import React from 'react'; import { render } from '@testing-library/react'; +import { axeTest } from '../../../utils/test/axe'; import { LanguageMenu } from './LanguageMenu'; -import { LanguageMenuItem, LanguageMenuLink } from './LanguageMenuItem'; -import { axeTest } from '../../utils/test/axe'; +import { LanguageMenuItem } from '../LanguageMenuItem'; +import { LanguageMenuLink } from '../LanguageMenuLink'; const doNothing = () => ({}); diff --git a/src/core/LanguageMenu/LanguageMenu/LanguageMenu.tsx b/src/core/LanguageMenu/LanguageMenu/LanguageMenu.tsx new file mode 100644 index 000000000..c91418645 --- /dev/null +++ b/src/core/LanguageMenu/LanguageMenu/LanguageMenu.tsx @@ -0,0 +1,236 @@ +import React, { Component, ReactNode, Fragment } from 'react'; +import { default as styled } from 'styled-components'; +import classnames from 'classnames'; +import { + Menu, + MenuButton, + MenuItems, + MenuPopover, + MenuPopoverProps, +} from '@reach/menu-button'; +import { positionDefault } from '@reach/popover'; +import { PRect } from '@reach/rect'; +import { classnamesValue } from '../../../utils/typescript'; +import { logger } from '../../../utils/logger'; +import { HtmlSpan } from '../../../reset/HtmlSpan/HtmlSpan'; +import { Icon } from '../../Icon/Icon'; +import { + baseStyles, + languageMenuPopoverStyles, +} from './LanguageMenu.baseStyles'; + +const baseClassName = 'fi-language-menu'; +const languageMenuClassNames = { + item: `${baseClassName}_item`, + itemLang: `${baseClassName}-language_item`, + button: `${baseClassName}_button`, + buttonOpen: `${baseClassName}-language_button_open`, + buttonLang: `${baseClassName}-language_button`, + popover: `${baseClassName}_popover`, + popoverLang: `${baseClassName}-language_popover`, + iconLang: `${baseClassName}-language_icon`, +}; + +export interface LanguageMenuItemBaseProps { + /** Operation to run on select */ + onSelect: () => void; + /** Item content */ + children: ReactNode; +} + +type SupportedMenuLinkComponent = keyof JSX.IntrinsicElements; + +interface LanguageMenuLinkPropsWithType { + type: 'menulink'; + /** Url to direct to */ + href: string; + /** Item content */ + children: ReactNode; + className?: string; + as?: SupportedMenuLinkComponent; +} + +export interface LanguageMenuLinkBaseProps + extends Omit {} + +export type LanguageMenuPopoverItemsProps = + | LanguageMenuItemBaseProps + | LanguageMenuLinkPropsWithType; +type OptionalLanguageMenuPopoverProps = { + [K in keyof MenuPopoverProps]?: MenuPopoverProps[K]; +}; + +export interface LanguageMenuProps { + /** Name or content of menubutton */ + name: React.ReactNode | ((props: { isOpen: boolean }) => React.ReactNode); + /** Custom classname to extend or customize */ + className?: string; + /** Custom classname to extend or customize */ + languageMenuButtonClassName?: string; + /** Custom classname to apply when menu is open */ + languageMenuOpenButtonClassName?: string; + /** Properties given to LanguageMenu's popover-component, className etc. */ + languageMenuPopoverProps?: OptionalLanguageMenuPopoverProps; + languageMenuPopoverComponent?: React.ComponentType; + /** Menu items: MenuItem or MenuLink */ + children?: + | Array> + | null + | undefined; +} + +class BaseLanguageMenu extends Component { + render() { + const { + children, + name, + className, + languageMenuButtonClassName: menuButtonClassName, + languageMenuOpenButtonClassName: menuButtonOpenClassName, + languageMenuPopoverProps: menuPopoverProps = {}, + languageMenuPopoverComponent: MenuPopoverComponentReplace, + ...passProps + } = this.props; + + if (React.Children.count(children) < 1) { + logger.warn(`Menu '${name}' does not contain items`); + return null; + } + return ( + + + {({ isOpen }: { isOpen: boolean }) => ( + + + {name} + + {!!MenuPopoverComponentReplace ? ( + + {children} + + ) : ( + + {children} + + )} + + )} + + + ); + } +} +const StyledLanguageMenu = styled((props: LanguageMenuProps) => ( + +))` + ${baseStyles} +`; + +const LanguageMenuPopoverWithProps = ( + children: ReactNode, + addClass?: classnamesValue, +) => + React.Children.map( + children, + (child: React.ReactElement) => { + // Set defaul component-prop/type to be 'a' needed for links + if (React.isValidElement(child)) { + return React.cloneElement(child, { + as: 'a', + className: classnames(languageMenuClassNames.item, addClass), + }); + } + return child; + }, + ); + +const languageName = (name: ReactNode) => ( + + {name} + + +); + +const LanguageMenuPopoverPosition = ( + targetRect: PRect | null, + popoverRect: PRect | null, +): React.CSSProperties => { + if (!targetRect || !popoverRect) { + return {}; + } + return { + left: `${targetRect.left - popoverRect.width + targetRect.width}px`, + // eslint-disable-next-line no-undef + top: `${targetRect.top + targetRect.height + window.pageYOffset}px`, + maxWidth: `${Math.max( + targetRect.width, + targetRect.width + targetRect.left - 30, + )}px`, + minWidth: `${targetRect.width - 2}px`, + }; +}; + +const StyledMenuPopover = styled( + ({ children, ...passProps }: MenuPopoverProps) => ( + + {children} + + ), +)` + ${languageMenuPopoverStyles} +`; + +/** + * + * Use for dropdown menu. + */ +export class LanguageMenu extends Component { + render() { + const { + children, + name, + className, + languageMenuPopoverComponent: MenuPopoverComponentProp, + ...passProps + } = this.props; + const languageMenuButtonClassName = classnames( + languageMenuClassNames.button, + languageMenuClassNames.buttonLang, + className, + ); + const menuPopoverProps = { + className: classnames( + languageMenuClassNames.popover, + languageMenuClassNames.popoverLang, + ), + }; + + return ( + + + {LanguageMenuPopoverWithProps( + children, + languageMenuClassNames.itemLang, + )} + + + ); + } +} diff --git a/src/core/LanguageMenu/__snapshots__/LanguageMenu.test.tsx.snap b/src/core/LanguageMenu/LanguageMenu/__snapshots__/LanguageMenu.test.tsx.snap similarity index 100% rename from src/core/LanguageMenu/__snapshots__/LanguageMenu.test.tsx.snap rename to src/core/LanguageMenu/LanguageMenu/__snapshots__/LanguageMenu.test.tsx.snap diff --git a/src/core/LanguageMenu/LanguageMenu/index.tsx b/src/core/LanguageMenu/LanguageMenu/index.tsx new file mode 100644 index 000000000..00f4bed22 --- /dev/null +++ b/src/core/LanguageMenu/LanguageMenu/index.tsx @@ -0,0 +1,6 @@ +export { + LanguageMenu, + LanguageMenuProps, + LanguageMenuItemBaseProps, + LanguageMenuLinkBaseProps, +} from './LanguageMenu'; diff --git a/src/core/LanguageMenu/LanguageMenuItem.tsx b/src/core/LanguageMenu/LanguageMenuItem.tsx deleted file mode 100644 index d8645663b..000000000 --- a/src/core/LanguageMenu/LanguageMenuItem.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React, { Component } from 'react'; -import { - LanguageMenuItemProps, - LanguageMenuLinkProps, -} from '../../components/LanguageMenu/LanguageMenu'; -import { - LanguageMenuItemLanguage, - LanguageMenuItemLanguageProps, -} from './LanguageMenuItemLanguage'; -import { - LanguageMenuLinkLanguage, - LanguageMenuLinkLanguageProps, -} from './LanguageMenuLinkLanguage'; -export { - LanguageMenuItemProps, - LanguageMenuLinkProps, - LanguageMenuItemLanguage, - LanguageMenuItemLanguageProps, - LanguageMenuLinkLanguage, - LanguageMenuLinkLanguageProps, -}; - -export class LanguageMenuItem extends Component { - render() { - return ; - } -} - -export class LanguageMenuLink extends Component { - render() { - return ; - } -} diff --git a/src/core/LanguageMenu/LanguageMenuItem.md b/src/core/LanguageMenu/LanguageMenuItem/LanguageMenuItem.md similarity index 100% rename from src/core/LanguageMenu/LanguageMenuItem.md rename to src/core/LanguageMenu/LanguageMenuItem/LanguageMenuItem.md diff --git a/src/core/LanguageMenu/LanguageMenuItemLanguage.tsx b/src/core/LanguageMenu/LanguageMenuItem/LanguageMenuItem.tsx similarity index 51% rename from src/core/LanguageMenu/LanguageMenuItemLanguage.tsx rename to src/core/LanguageMenu/LanguageMenuItem/LanguageMenuItem.tsx index 6a7664cae..6005375e0 100644 --- a/src/core/LanguageMenu/LanguageMenuItemLanguage.tsx +++ b/src/core/LanguageMenu/LanguageMenuItem/LanguageMenuItem.tsx @@ -1,22 +1,20 @@ import React from 'react'; import classnames from 'classnames'; -import { - MenuItem as CompMenuItem, - LanguageMenuItemProps, -} from '../../components/LanguageMenu/LanguageMenu'; +import { MenuItem } from '@reach/menu-button'; +import { LanguageMenuItemBaseProps } from '../LanguageMenu'; -export interface LanguageMenuItemLanguageProps extends LanguageMenuItemProps { +export interface LanguageMenuItemProps extends LanguageMenuItemBaseProps { /** Show item as selected one */ selected?: boolean; className?: string; } -export const LanguageMenuItemLanguage = ({ +export const LanguageMenuItem = ({ selected, className, ...passProps -}: LanguageMenuItemLanguageProps) => ( - ( + ( - ( +