widenarrow-ui 1.0.19 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "widenarrow-ui",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "description": "A storybook 6 typeScript component library used for Wide Narrow by infodesk",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/index.esm.js",
@@ -3,6 +3,17 @@
3
3
  .container {
4
4
  position: relative;
5
5
 
6
+ &:hover {
7
+ .hoverOverlay {
8
+ opacity: 0.4;
9
+ }
10
+ }
11
+ &:active {
12
+ .hoverOverlay {
13
+ opacity: 0.6;
14
+ }
15
+ }
16
+
6
17
  &_withContainer,
7
18
  &_withAspectRatio {
8
19
  .backgroundImage {
@@ -100,3 +111,14 @@
100
111
  .lazyloaded {
101
112
  opacity: 1;
102
113
  }
114
+
115
+ .hoverOverlay {
116
+ position: absolute;
117
+ height: 100%;
118
+ width: 100%;
119
+ z-index: 10;
120
+ opacity: 0;
121
+ transition: opacity 100ms ease;
122
+ }
123
+
124
+ @include backgroundColor('hoverOverlayColor');
@@ -1,5 +1,6 @@
1
1
  import { FC } from 'react';
2
2
  import classNames from 'classnames/bind';
3
+ import { is } from 'ramda';
3
4
 
4
5
  import { ImageProps } from './Image.types';
5
6
  import styles from './Image.module.scss';
@@ -13,6 +14,7 @@ const Image: FC<ImageProps> = ({
13
14
  imageClassName,
14
15
  withContainer,
15
16
  placeHolderColor,
17
+ hoverOverlayColor,
16
18
  bgImage,
17
19
  bgImageProps,
18
20
  aspectRatio,
@@ -45,6 +47,13 @@ const Image: FC<ImageProps> = ({
45
47
  [className as string]: className
46
48
  })}
47
49
  >
50
+ {hoverOverlayColor ? (
51
+ <div
52
+ className={s('hoverOverlay', {
53
+ [`hoverOverlayColor_${hoverOverlayColor}`]: is(String, hoverOverlayColor)
54
+ })}
55
+ />
56
+ ) : null}
48
57
  {backgroundImageMarkup}
49
58
  {customComponent && customComponent}
50
59
  </div>
@@ -64,7 +73,7 @@ const Image: FC<ImageProps> = ({
64
73
  />
65
74
  );
66
75
 
67
- if (aspectRatio || withContainer) {
76
+ if (aspectRatio || withContainer || hoverOverlayColor) {
68
77
  return (
69
78
  <div
70
79
  className={s('container', {
@@ -74,6 +83,13 @@ const Image: FC<ImageProps> = ({
74
83
  [aspectRatio as string]: !!aspectRatio
75
84
  })}
76
85
  >
86
+ {hoverOverlayColor ? (
87
+ <div
88
+ className={s('hoverOverlay', {
89
+ [`hoverOverlayColor_${hoverOverlayColor}`]: is(String, hoverOverlayColor)
90
+ })}
91
+ />
92
+ ) : null}
77
93
  {imageMarkup}
78
94
  </div>
79
95
  );
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { AspectRatioTypes } from '../../constants';
2
+ import { AspectRatioTypes, ColorTypes } from '../../constants';
3
3
 
4
4
  export interface ImageProps {
5
5
  src: string;
@@ -8,6 +8,7 @@ export interface ImageProps {
8
8
  imageClassName?: string;
9
9
  customCellComponent?: ReactNode;
10
10
  aspectRatio?: Partial<AspectRatioTypes>;
11
+ hoverOverlayColor?: Partial<ColorTypes>;
11
12
  bgImage?: boolean;
12
13
  bgImageProps?: {
13
14
  size: 'cover' | 'contain';
@@ -89,7 +89,6 @@
89
89
  font-weight: 600;
90
90
  font-size: $font-size-l;
91
91
  color: $grey-5;
92
- margin-bottom: 0;
93
92
  margin-top: 0;
94
93
  transition: color 50ms ease-in-out;
95
94
  }
@@ -113,6 +112,7 @@
113
112
 
114
113
  .innerContainer {
115
114
  display: flex;
115
+ min-width: 0;
116
116
  align-items: center;
117
117
  justify-content: space-between;
118
118
  flex-grow: 1;
@@ -122,6 +122,11 @@
122
122
  display: flex;
123
123
  flex-direction: column;
124
124
  margin-right: 12px;
125
+ flex-grow: 1;
126
+
127
+ &_withEllipsis {
128
+ overflow: hidden;
129
+ }
125
130
 
126
131
  &_withCallback {
127
132
  cursor: pointer;
@@ -134,6 +139,10 @@
134
139
  }
135
140
  }
136
141
 
142
+ .buttonsContainer {
143
+ height: auto;
144
+ }
145
+
137
146
  @include margin(8);
138
147
  @include padding(8);
139
148
  @include backgroundColor('backgroundColor');
@@ -3,6 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
3
3
  import { ListItem } from 'src/components/ListItem';
4
4
  import { Box } from 'src/components/Box';
5
5
  import { SwitchButton } from 'src/components/SwitchButton';
6
+ import { ColorTypes } from 'src/constants';
6
7
 
7
8
  const meta: Meta<typeof ListItem> = {
8
9
  title: 'Components/ListItem',
@@ -15,7 +16,7 @@ type Story = StoryObj<typeof ListItem>;
15
16
 
16
17
  export const Default: Story = {
17
18
  args: {
18
- title: 'My list item',
19
+ title: 'oiuytrtyuiuytewugwoiuytrtyuiuytewugwoiuytrtyuiuytewugwoiuytrtyuiuytewugwoiuytrtyuiuytewugw',
19
20
  description: 'Lorem ipsum dolor sit amet',
20
21
  imageSrc:
21
22
  'https://plus.unsplash.com/premium_photo-1672582776510-048e431afb31?q=80&w=3570&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'
@@ -24,12 +25,19 @@ export const Default: Story = {
24
25
  <div style={{ width: '880px', display: 'flex', justifyContent: 'center' }}>
25
26
  <ListItem
26
27
  {...props}
28
+ borderColor={ColorTypes.BLACK}
29
+ border={'1'}
27
30
  onClickCallback={() => {
28
31
  console.log('Hej!');
29
32
  }}
30
33
  buttonsComponent={
31
- <Box displayFlex>
32
- <SwitchButton label={'Click me'} checked name={'switch example'} onClickCallback={() => undefined} />
34
+ <Box alignItems={'center'}>
35
+ {/* <div style={{ height: '300px', backgroundColor: 'red', width: '100px', marginRight: '8px' }}></div>
36
+ <div style={{ height: '300px', backgroundColor: 'green', width: '100px', marginRight: '8px' }}></div>
37
+ <div style={{ height: '300px', backgroundColor: 'blue', width: '100px' }}></div> */}
38
+ <Box>
39
+ <SwitchButton label={'Click me'} checked name={'switch example'} onClickCallback={() => undefined} />
40
+ </Box>
33
41
  </Box>
34
42
  }
35
43
  />
@@ -21,6 +21,7 @@ const ListItem: FC<ListItemProps> = ({
21
21
  padding = '2',
22
22
  imageAspectRatio = AspectRatioTypes.ar1_1,
23
23
  withBorderRadius = true,
24
+ withEllipsis = true,
24
25
  withHoverEffect,
25
26
  onClickCallback,
26
27
  linkTo,
@@ -79,6 +80,7 @@ const ListItem: FC<ListItemProps> = ({
79
80
  aspectRatio={imageAspectRatio}
80
81
  bgImage={!!imageAspectRatio}
81
82
  customComponent={imageIcon ? <Icon className={s('imageIcon')} color={ColorTypes.GREY_3} icon={imageIcon} /> : undefined}
83
+ hoverOverlayColor={!!onClickCallback ? ColorTypes.GREY_5 : undefined}
82
84
  />
83
85
  </div>
84
86
  ) : null}
@@ -95,19 +97,20 @@ const ListItem: FC<ListItemProps> = ({
95
97
  >
96
98
  <div
97
99
  className={s('contentContainer', {
98
- contentContainer_withCallback: !!onClickCallback
100
+ contentContainer_withCallback: !!onClickCallback,
101
+ contentContainer_withEllipsis: withEllipsis
99
102
  })}
100
103
  role={'button'}
101
104
  onClick={onClickCallback || (() => undefined)}
102
105
  >
103
106
  {contentComponent && contentComponent}
104
107
  {title ? (
105
- <Heading className={s('heading')} type={'h4'}>
108
+ <Heading className={s('heading')} marginBottom={description ? '05' : '0'} type={'h4'} withEllipsis={withEllipsis}>
106
109
  {title}
107
110
  </Heading>
108
111
  ) : null}
109
112
  {description ? (
110
- <Paragraph marginBottom={'0'} fontSize="s" marginTop={'15'}>
113
+ <Paragraph marginBottom={'0'} fontSize={'s'} marginTop={'0'}>
111
114
  {description}
112
115
  </Paragraph>
113
116
  ) : null}
@@ -9,6 +9,7 @@ export interface ListItemProps extends MarginInterface, PaddingInterface {
9
9
  imageSrc?: string;
10
10
  withBorderRadius?: boolean;
11
11
  withHoverEffect?: boolean;
12
+ withEllipsis?: boolean;
12
13
  imageIcon?: Partial<IconTypes>;
13
14
  size: Partial<SizeTypes>;
14
15
  imageAspectRatio?: Partial<AspectRatioTypes>;
@@ -0,0 +1,74 @@
1
+ @import 'src/styles/mixins.scss';
2
+
3
+ .container {
4
+ position: relative;
5
+
6
+ &_marginBottom {
7
+ margin-bottom: $two-base-size;
8
+ }
9
+
10
+ &_disabled {
11
+ pointer-events: none;
12
+ opacity: $disabled-opacity;
13
+ }
14
+ }
15
+
16
+ .inputContainer {
17
+ position: relative;
18
+ line-height: 1.2; // don't cut letters that go underneath the baseline ('g', 'q', etc)
19
+ }
20
+
21
+ .input {
22
+ @include input-field;
23
+
24
+ cursor: pointer;
25
+ display: block;
26
+ height: $form-component-height;
27
+ width: 100%;
28
+ font-size: $font-size-m;
29
+
30
+ // Reset native select appearance (also removing icon) and add custom background arrow
31
+ -webkit-appearance: none;
32
+ -moz-appearance: none;
33
+ appearance: none;
34
+ background-color: $white;
35
+
36
+ &_active {
37
+ background-image: url('data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%2212%22%20viewBox%3D%220%200%2012%2012%22%3E%3Ctitle%3Edown-arrow%3C%2Ftitle%3E%3Cg%20fill%3D%22%23707070%22%3E%3Cpath%20d%3D%22M10.293%2C3.293%2C6%2C7.586%2C1.707%2C3.293A1%2C1%2C0%2C0%2C0%2C.293%2C4.707l5%2C5a1%2C1%2C0%2C0%2C0%2C1.414%2C0l5-5a1%2C1%2C0%2C1%2C0-1.414-1.414Z%22%20fill%3D%22%23707070%22%3E%3C%2Fpath%3E%3C%2Fg%3E%3C%2Fsvg%3E');
38
+ background-size: 12px;
39
+ background-position: calc(100% - 16px) center;
40
+ background-repeat: no-repeat;
41
+ }
42
+
43
+ @include breakpoint($lg) {
44
+ min-width: 240px;
45
+
46
+ &:hover {
47
+ border-color: $blue;
48
+ }
49
+ }
50
+ }
51
+
52
+ .button {
53
+ width: 100%;
54
+ }
55
+
56
+ .dropDown {
57
+ width: 100%;
58
+ }
59
+
60
+ .spinner {
61
+ position: absolute;
62
+ top: 8px;
63
+ right: 10px;
64
+ }
65
+
66
+ .error {
67
+ display: block;
68
+ color: $red;
69
+ margin: $base-size 0 0;
70
+ }
71
+
72
+ .helperText {
73
+ @include form-helperText;
74
+ }
@@ -0,0 +1,22 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+
3
+ import { SelectInput } from 'src/components/SelectInput';
4
+
5
+ const meta: Meta<typeof SelectInput> = {
6
+ title: 'Components/SelectInput',
7
+ component: SelectInput
8
+ };
9
+
10
+ export default meta;
11
+
12
+ type Story = StoryObj<typeof SelectInput>;
13
+
14
+ export const Default: Story = {
15
+ args: {
16
+ options: [
17
+ { text: 'First item', value: 0 },
18
+ { text: 'Second item', value: 1 },
19
+ { text: 'Third item', value: 2 }
20
+ ]
21
+ }
22
+ };
@@ -0,0 +1,119 @@
1
+ import { FC, Fragment } from 'react';
2
+ import classNames from 'classnames/bind';
3
+
4
+ import { HierarchyTypes, IconTypes } from 'src/constants';
5
+
6
+ import { Label } from 'src/components/Typography/Typography';
7
+ import { SolidSpinner } from 'src/components/SolidSpinner';
8
+ import { Button } from 'src/components/Button';
9
+ import { DropDown } from 'src/components/DropDown';
10
+ import { DropDownItem } from 'src/components/DropDownItem';
11
+ import { SelectInputProps, OptionItem } from './SelectInput.types';
12
+
13
+ import styles from './SelectInput.module.scss';
14
+
15
+ const s = classNames.bind(styles);
16
+
17
+ const SelectInput: FC<SelectInputProps> = ({
18
+ name,
19
+ label,
20
+ nativeHtmlComponent = true,
21
+ size,
22
+ onChange,
23
+ defaultOption,
24
+ value,
25
+ error,
26
+ helperText,
27
+ options,
28
+ disabled,
29
+ loading,
30
+ className,
31
+ inputClassName,
32
+ marginBottom
33
+ }) => (
34
+ <div
35
+ className={s('container', {
36
+ container_marginBottom: marginBottom,
37
+ container_disabled: disabled,
38
+ [className as string]: className
39
+ })}
40
+ >
41
+ {label && <Label htmlFor={name}>{label}</Label>}
42
+ <div className={s('inputContainer')}>
43
+ {nativeHtmlComponent ? (
44
+ <Fragment>
45
+ <select
46
+ disabled={disabled || loading}
47
+ name={name}
48
+ value={value}
49
+ onChange={(e) => {
50
+ onChange(e.target.value); // Only send value, expensive to pass the whole event as argument through multiple components
51
+ }}
52
+ className={s('input', {
53
+ input_active: disabled !== true && loading !== true,
54
+ [inputClassName as string]: inputClassName
55
+ })}
56
+ aria-label={label || name}
57
+ >
58
+ {defaultOption && <option value="">{defaultOption}</option>}
59
+ {options &&
60
+ options.map((option) => (
61
+ <option key={option.value} value={option.value} disabled={option.disabled}>
62
+ {option.text}
63
+ </option>
64
+ ))}
65
+ </select>
66
+ {loading && <SolidSpinner className={s('spinner')} size={size} />}
67
+ </Fragment>
68
+ ) : (
69
+ <Fragment>
70
+ <DropDown
71
+ offset={{ vertical: 0, horizontal: 0 }}
72
+ placement={'bottom'}
73
+ buttonComponent={
74
+ <Button
75
+ loading={loading}
76
+ className={s('button')}
77
+ text={(() => {
78
+ let i = 0;
79
+ while (i < options.length) {
80
+ if (options[i].value === value) {
81
+ return options[i].text;
82
+ }
83
+ i++;
84
+ }
85
+ return 'Select an option';
86
+ })()}
87
+ size={size}
88
+ type={HierarchyTypes.SECONDARY}
89
+ icon={IconTypes.CHEVRON_DOWN}
90
+ />
91
+ }
92
+ className={s('dropDown')}
93
+ withArrow={false}
94
+ >
95
+ {options
96
+ ? options.map((opt: OptionItem) => (
97
+ <DropDownItem
98
+ key={opt.text}
99
+ text={opt.text}
100
+ type={HierarchyTypes.PRIMARY}
101
+ size={size}
102
+ active={opt.value === value}
103
+ onClickCallback={() => {
104
+ onChange(opt.value);
105
+ }}
106
+ />
107
+ ))
108
+ : null}
109
+ </DropDown>
110
+ </Fragment>
111
+ )}
112
+ {/* Note, value is set here rather than on the option - docs: https://facebook.github.io/react/docs/forms.html */}
113
+ </div>
114
+ {helperText && <p className={s('helperText')}>{helperText}</p>}
115
+ {error && <span className={s('error')}>{error}</span>}
116
+ </div>
117
+ );
118
+
119
+ export { SelectInput };
@@ -0,0 +1,26 @@
1
+ import { SizeTypes } from '../../constants';
2
+
3
+ export interface OptionItem {
4
+ text: string;
5
+ value: string | number;
6
+ disabled?: boolean;
7
+ }
8
+
9
+ export interface SelectInputProps {
10
+ className?: string;
11
+ inputClassName?: string;
12
+ defaultOption?: string;
13
+ size: SizeTypes.SMALL | SizeTypes.MEDIUM | SizeTypes.LARGE;
14
+ disabled?: boolean;
15
+ error?: string;
16
+ helperText?: string;
17
+ text?: string;
18
+ marginBottom?: boolean;
19
+ loading?: boolean;
20
+ label?: string;
21
+ name: string;
22
+ onChange: (value: string | number) => void;
23
+ options: Array<OptionItem>;
24
+ value: string | number;
25
+ nativeHtmlComponent?: boolean;
26
+ }
@@ -0,0 +1 @@
1
+ export * from './SelectInput';
@@ -18,5 +18,6 @@ export * from './Separator';
18
18
  export * from './SolidSpinner';
19
19
  export * from './SortableTable';
20
20
  export * from './SwitchButton';
21
+ export * from './SelectInput';
21
22
  export * from './ToolTip';
22
23
  export * from './Typography';