diff --git a/packages/fuselage/.loki/reference/chrome_iphone7_Data_Display_Chip_Default.png b/packages/fuselage/.loki/reference/chrome_iphone7_Data_Display_Chip_Default.png new file mode 100644 index 0000000000..15875fe54f Binary files /dev/null and b/packages/fuselage/.loki/reference/chrome_iphone7_Data_Display_Chip_Default.png differ diff --git a/packages/fuselage/.loki/reference/chrome_iphone7_Data_Display_Chip_Dismissible.png b/packages/fuselage/.loki/reference/chrome_iphone7_Data_Display_Chip_Dismissible.png new file mode 100644 index 0000000000..50ee92c091 Binary files /dev/null and b/packages/fuselage/.loki/reference/chrome_iphone7_Data_Display_Chip_Dismissible.png differ diff --git a/packages/fuselage/.loki/reference/chrome_iphone7_Data_Display_Chip_Example.png b/packages/fuselage/.loki/reference/chrome_iphone7_Data_Display_Chip_Example.png new file mode 100644 index 0000000000..35dbba9042 Binary files /dev/null and b/packages/fuselage/.loki/reference/chrome_iphone7_Data_Display_Chip_Example.png differ diff --git a/packages/fuselage/.loki/reference/chrome_iphone7_Data_Display_Chip_With_thumb.png b/packages/fuselage/.loki/reference/chrome_iphone7_Data_Display_Chip_With_thumb.png new file mode 100644 index 0000000000..294f770653 Binary files /dev/null and b/packages/fuselage/.loki/reference/chrome_iphone7_Data_Display_Chip_With_thumb.png differ diff --git a/packages/fuselage/.loki/reference/chrome_iphone7_Misc_Chip_Default.png b/packages/fuselage/.loki/reference/chrome_iphone7_Misc_Chip_Default.png deleted file mode 100644 index 610a65c98a..0000000000 Binary files a/packages/fuselage/.loki/reference/chrome_iphone7_Misc_Chip_Default.png and /dev/null differ diff --git a/packages/fuselage/.loki/reference/chrome_laptop_Data_Display_Chip_Default.png b/packages/fuselage/.loki/reference/chrome_laptop_Data_Display_Chip_Default.png new file mode 100644 index 0000000000..fad6d758f0 Binary files /dev/null and b/packages/fuselage/.loki/reference/chrome_laptop_Data_Display_Chip_Default.png differ diff --git a/packages/fuselage/.loki/reference/chrome_laptop_Data_Display_Chip_Dismissible.png b/packages/fuselage/.loki/reference/chrome_laptop_Data_Display_Chip_Dismissible.png new file mode 100644 index 0000000000..68d25dbd01 Binary files /dev/null and b/packages/fuselage/.loki/reference/chrome_laptop_Data_Display_Chip_Dismissible.png differ diff --git a/packages/fuselage/.loki/reference/chrome_laptop_Data_Display_Chip_Example.png b/packages/fuselage/.loki/reference/chrome_laptop_Data_Display_Chip_Example.png new file mode 100644 index 0000000000..95c45167fc Binary files /dev/null and b/packages/fuselage/.loki/reference/chrome_laptop_Data_Display_Chip_Example.png differ diff --git a/packages/fuselage/.loki/reference/chrome_laptop_Data_Display_Chip_With_thumb.png b/packages/fuselage/.loki/reference/chrome_laptop_Data_Display_Chip_With_thumb.png new file mode 100644 index 0000000000..98f12c243b Binary files /dev/null and b/packages/fuselage/.loki/reference/chrome_laptop_Data_Display_Chip_With_thumb.png differ diff --git a/packages/fuselage/.loki/reference/chrome_laptop_Misc_Chip_Default.png b/packages/fuselage/.loki/reference/chrome_laptop_Misc_Chip_Default.png deleted file mode 100644 index 1d2251c368..0000000000 Binary files a/packages/fuselage/.loki/reference/chrome_laptop_Misc_Chip_Default.png and /dev/null differ diff --git a/packages/fuselage/.storybook/helpers.js b/packages/fuselage/.storybook/helpers.js index 88998242f3..4af334ae95 100644 --- a/packages/fuselage/.storybook/helpers.js +++ b/packages/fuselage/.storybook/helpers.js @@ -1,6 +1,6 @@ import React from 'react'; -import { Box, Text } from '../src'; +import { Box } from '../src'; export function PropsVariationSection({ component: Component, common = {}, xAxis = {}, yAxis = {} }) { return @@ -25,3 +25,60 @@ export function PropsVariationSection({ component: Component, common = {}, xAxis ; } + +export const exampleAvatar = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAA +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 +v/L21v8BT/ZVoe1UItsAAAAASUVORK5CYII=`; + +export const blankAvatar = `data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BA +AAAAAALAAAAAABAAEAAAICRAEAOw==`; diff --git a/packages/fuselage/src/components/AutoComplete/index.js b/packages/fuselage/src/components/AutoComplete/index.js index 1214242163..23d540d7c1 100644 --- a/packages/fuselage/src/components/AutoComplete/index.js +++ b/packages/fuselage/src/components/AutoComplete/index.js @@ -1,10 +1,11 @@ import React, { useState, useEffect, useRef } from 'react'; import { Box, PositionAnimated } from '../Box'; -import { Chip } from '../Chip'; +import Chip from '../Chip'; import { Icon } from '../Icon'; import { useCursor, Options } from '../Options'; import { InputBox } from '../InputBox'; +import Margins from '../Margins'; const Item = (props) => ; @@ -59,10 +60,12 @@ export function AutoComplete({ return ( ref.current.focus()}> - - setFilter(e.currentTarget.value)} onBlur={hide} onFocus={show} onKeyDown={handleKeyDown} placeholder={placeholder} order={1} rcx-input-box--undecorated value={value}/> - {currentValue.map((value) => prevent(e) & internalChanged(value) && false} children={getLabel(options.find((option) => getValue(option) === value))}/>)} - + + + setFilter(e.currentTarget.value)} onBlur={hide} onFocus={show} onKeyDown={handleKeyDown} placeholder={placeholder} order={1} rcx-input-box--undecorated value={value}/> + {currentValue.map((value) => prevent(e) & internalChanged(value) && false} children={getLabel(options.find((option) => getValue(option) === value))}/>)} + + }/> [value, label])} /> diff --git a/packages/fuselage/src/components/Box/styles.scss b/packages/fuselage/src/components/Box/styles.scss index 2ee4b979d4..4fb76a1755 100644 --- a/packages/fuselage/src/components/Box/styles.scss +++ b/packages/fuselage/src/components/Box/styles.scss @@ -2,11 +2,13 @@ @extend %box; &--full { + @extend %box--animated; @extend %box--full; &::before, &::after { @extend %box; + @extend %box--animated; @extend %box--full; } } diff --git a/packages/fuselage/src/components/Box/withBoxStyling.js b/packages/fuselage/src/components/Box/withBoxStyling.js new file mode 100644 index 0000000000..0c03d45ac7 --- /dev/null +++ b/packages/fuselage/src/components/Box/withBoxStyling.js @@ -0,0 +1,26 @@ +import { createElement } from 'react'; + +import { useStyleSheet } from '../../hooks/useStyleSheet'; +import { useStylingProps } from './stylingProps'; + +export const withBoxStyling = (component) => { + const render = (props) => { + if (typeof component === 'function') { + return component(props); + } + + return createElement(component, props); + }; + + const WithBoxStyling = (props) => { + useStyleSheet(); + props = useStylingProps(props); + return render(props); + }; + + if (process.env.NODE_ENV !== 'production') { + WithBoxStyling.displayName = `WithBoxStyling(${ component.displayName || component.name || 'Component' })`; + } + + return WithBoxStyling; +}; diff --git a/packages/fuselage/src/components/Chip/index.js b/packages/fuselage/src/components/Chip/index.js index a2d078cdc7..657ad82d24 100644 --- a/packages/fuselage/src/components/Chip/index.js +++ b/packages/fuselage/src/components/Chip/index.js @@ -1,52 +1,50 @@ +import PropTypes from 'prop-types'; import React from 'react'; +import { prependClassName } from '../../helpers/prependClassName'; import { Avatar } from '../Avatar'; -import { Box, Flex } from '../Box'; +import { withBoxStyling } from '../Box/withBoxStyling'; import { Icon } from '../Icon'; import Margins from '../Margins'; -const ThumbDefault = ({ url }) => ; -const RemoveDefault = () => ; +const defaultRenderThumb = ({ url }) => ; +const defaultRenderDismissSymbol = () => ; -export const Chip = ({ +const Chip = ({ children, + className, thumbUrl, - Thumb = ThumbDefault, onClick, onMouseDown, - Remove = RemoveDefault, - ...props -}) => ( - - - {Thumb && thumbUrl && - - } - {children && - - {children} - - } - {Remove && (onClick || onMouseDown) && - - - - } - - -); + renderThumb = defaultRenderThumb, + renderDismissSymbol = defaultRenderDismissSymbol, + ...rest +}) => { + const onDismiss = onClick || onMouseDown; -Chip.Wrapper = ({ children, width, alignItems = 'center', wrap = 'wrap', ...props }) => - - - - {children.map((children, i) => - - - {children} - - , - )} - - - ; + return ; +}; + +if (process.env.NODE_ENV !== 'production') { + Chip.displayName = 'Chip'; + + Chip.propTypes = { + thumbUrl: PropTypes.string, + renderThumb: PropTypes.func, + renderDismissSymbol: PropTypes.func, + }; +} + +export default withBoxStyling(Chip); diff --git a/packages/fuselage/src/components/Chip/stories.mdx b/packages/fuselage/src/components/Chip/stories.mdx index 5b2e8e1fbc..6a4cd2a22b 100644 --- a/packages/fuselage/src/components/Chip/stories.mdx +++ b/packages/fuselage/src/components/Chip/stories.mdx @@ -1,22 +1,49 @@ import { Meta, Preview, Props, Story } from '@storybook/addon-docs/blocks'; import { action } from '@storybook/addon-actions'; +import { exampleAvatar, blankAvatar } from '../../../.storybook/helpers'; +import { Box, Chip, Margins } from '../..'; -import { Chip, Margins } from '../..'; -const thumb = 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=='; - - + # Chip - - - Chip - Chip Chip Chip Chip Chip - Chip Chip Chip Chip Chip Chip Chip Chip Chip Chip - Chip Chip Chip Chip Chip Chip Chip Chip Chip Chip - + + Marie Rowe + +### Default + + + + Chip + + + +### Dismissible + + + + Chip + + + +### With thumb + + + + + {storyFn()} + + , + ]}> + <> + Chip + Chip + + + diff --git a/packages/fuselage/src/components/Chip/styles.scss b/packages/fuselage/src/components/Chip/styles.scss index bae932444d..3c64aa5648 100644 --- a/packages/fuselage/src/components/Chip/styles.scss +++ b/packages/fuselage/src/components/Chip/styles.scss @@ -1,12 +1,23 @@ +@use '../../styles/colors.scss'; +@use '../../styles/lengths.scss'; @use '../../styles/typography.scss'; .rcx-chip { - @include clickable; - @include typography.use-text-ellipsis; - + @extend %box--animated; + @extend %box--full; @extend %button--secondary; + + display: flex; + overflow: hidden; + align-items: center; + + min-height: lengths.size(28); + border-width: 0; + @include clickable; + @include typography.use-font-scale('p1'); + &.disabled, &:disabled { color: $button-colors-secondary-color; @@ -15,7 +26,13 @@ } &__text { - @include typography.use-text-ellipsis; white-space: nowrap; + letter-spacing: inherit; + + color: inherit; + + font: inherit; + + @include typography.use-text-ellipsis; } } diff --git a/packages/fuselage/src/components/Select/MultiSelect.js b/packages/fuselage/src/components/Select/MultiSelect.js index 4ed054ae87..6910334a30 100644 --- a/packages/fuselage/src/components/Select/MultiSelect.js +++ b/packages/fuselage/src/components/Select/MultiSelect.js @@ -1,7 +1,7 @@ import React, { useState, useRef, useEffect, useCallback } from 'react'; import { AnimatedVisibility, Box, Flex, Position } from '../Box'; -import { Chip } from '../Chip'; +import Chip from '../Chip'; import { Icon } from '../Icon'; import { InputBox } from '../InputBox'; import Margins from '../Margins'; @@ -79,12 +79,12 @@ export const MultiSelect = ({ - - + + {currentValue.map((value) => prevent(e) & internalChanged([value]) && false} children={getLabel(options.find(([val]) => val === value))}/>)} - - + + diff --git a/packages/fuselage/src/components/index.js b/packages/fuselage/src/components/index.js index 165a70e22a..25b440297f 100644 --- a/packages/fuselage/src/components/index.js +++ b/packages/fuselage/src/components/index.js @@ -8,7 +8,7 @@ export * from './ButtonGroup'; export * from './Callout'; export * from './CheckBox'; export * from './Chevron'; -export * from './Chip'; +export { default as Chip } from './Chip'; export * from './Divider'; export * from './EmailInput'; export * from './Field'; diff --git a/packages/fuselage/src/styles/primitives/box.scss b/packages/fuselage/src/styles/primitives/box.scss index 63664c711f..277dc43b30 100644 --- a/packages/fuselage/src/styles/primitives/box.scss +++ b/packages/fuselage/src/styles/primitives/box.scss @@ -13,15 +13,17 @@ -moz-osx-font-smoothing: grayscale; } -%box--full { - margin: lengths.margin('none'); - padding: lengths.padding('none'); - +%box--animated { transition: all 230ms; @media (prefers-reduced-motion) { transition: none; } +} + +%box--full { + margin: lengths.margin('none'); + padding: lengths.padding('none'); border-width: lengths.border-width('none'); border-style: solid;