@transferwise/components 0.0.0-experimental-693e956 → 0.0.0-experimental-d729abf

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.
Files changed (46) hide show
  1. package/build/i18n/en.json +1 -0
  2. package/build/index.js +2320 -2234
  3. package/build/index.js.map +1 -1
  4. package/build/index.mjs +2322 -2237
  5. package/build/index.mjs.map +1 -1
  6. package/build/main.css +31 -10
  7. package/build/styles/main.css +31 -10
  8. package/build/styles/selectOption/SelectOption.css +31 -0
  9. package/build/styles/uploadInput/UploadInput.css +0 -10
  10. package/build/types/index.d.ts +2 -0
  11. package/build/types/index.d.ts.map +1 -1
  12. package/build/types/selectOption/SelectOption.d.ts +20 -0
  13. package/build/types/selectOption/SelectOption.d.ts.map +1 -0
  14. package/build/types/selectOption/SelectOption.messages.d.ts +8 -0
  15. package/build/types/selectOption/SelectOption.messages.d.ts.map +1 -0
  16. package/build/types/selectOption/index.d.ts +3 -0
  17. package/build/types/selectOption/index.d.ts.map +1 -0
  18. package/build/types/slidingPanel/SlidingPanel.d.ts +1 -0
  19. package/build/types/slidingPanel/SlidingPanel.d.ts.map +1 -1
  20. package/build/types/sticky/Sticky.d.ts +31 -3
  21. package/build/types/sticky/Sticky.d.ts.map +1 -1
  22. package/build/types/uploadInput/types.d.ts +1 -9
  23. package/build/types/uploadInput/types.d.ts.map +1 -1
  24. package/build/types/uploadInput/uploadItem/UploadItem.d.ts.map +1 -1
  25. package/package.json +2 -2
  26. package/src/i18n/en.json +1 -0
  27. package/src/index.ts +2 -0
  28. package/src/main.css +31 -10
  29. package/src/main.less +1 -0
  30. package/src/selectOption/SelectOption.css +31 -0
  31. package/src/selectOption/SelectOption.less +27 -0
  32. package/src/selectOption/SelectOption.messages.ts +8 -0
  33. package/src/selectOption/SelectOption.story.tsx +167 -0
  34. package/src/selectOption/SelectOption.tsx +134 -0
  35. package/src/selectOption/index.ts +2 -0
  36. package/src/slidingPanel/SlidingPanel.spec.js +2 -1
  37. package/src/slidingPanel/SlidingPanel.tsx +3 -0
  38. package/src/sticky/Sticky.spec.tsx +71 -0
  39. package/src/sticky/Sticky.story.tsx +46 -13
  40. package/src/sticky/Sticky.tsx +48 -4
  41. package/src/uploadInput/UploadInput.css +0 -10
  42. package/src/uploadInput/UploadInput.less +0 -11
  43. package/src/uploadInput/UploadInput.story.tsx +7 -50
  44. package/src/uploadInput/types.ts +1 -11
  45. package/src/uploadInput/uploadItem/UploadItem.tsx +6 -25
  46. package/src/sticky/Sticky.spec.js +0 -34
@@ -0,0 +1,167 @@
1
+ import type { StoryObj } from '@storybook/react';
2
+ import { Flag } from '@wise/art';
3
+ import SelectOption, { SelectOptionValue, SelectOptiopsGroup } from './SelectOption';
4
+ import { Bank, BankTransfer, Card, Plus } from '@transferwise/icons';
5
+ import { Field } from '../field/Field';
6
+ import { lorem10 } from '../test-utils';
7
+
8
+ export default {
9
+ title: 'Option/SelectOption',
10
+ };
11
+
12
+ type Story = StoryObj<typeof SelectOption>;
13
+
14
+ type CustomData = { data?: string };
15
+
16
+ const cardPaymentMethod: SelectOptionValue<CustomData> = {
17
+ media: <Card />,
18
+ title: 'Credit card',
19
+ content: (
20
+ <>
21
+ <div>Transfer the money to Wise using your bank account.</div>
22
+ <div>0.32 GBP in fees, should arrive in seconds</div>
23
+ </>
24
+ ),
25
+ };
26
+
27
+ const recentPaymentMethods: SelectOptionValue<CustomData>[] = [cardPaymentMethod];
28
+
29
+ const allOtherPaymentMethods: SelectOptionValue<CustomData>[] = [
30
+ {
31
+ data: lorem10,
32
+ media: <Flag code="gbp" />,
33
+ title: 'Wise GBP balance',
34
+ content: (
35
+ <>
36
+ <span>300 GBP available</span>
37
+ <span>0 GBP in fees, should arrive in seconds</span>
38
+ </>
39
+ ),
40
+ },
41
+ cardPaymentMethod,
42
+ {
43
+ media: <Card />,
44
+ title: 'Debit card',
45
+ content: (
46
+ <>
47
+ <span>Send from your Visa or Mastercard.</span>
48
+ <span>0.74 GBP in fees, should arrive in seconds</span>
49
+ </>
50
+ ),
51
+ },
52
+ {
53
+ media: <Bank />,
54
+ title: 'Swift Transfer',
55
+ content: (
56
+ <>
57
+ <span>Send money internationally. Your bank will charge you extra fees.</span>
58
+ <span>0.32 GBP in fees, should arrive by Thursday</span>
59
+ </>
60
+ ),
61
+ },
62
+ {
63
+ media: <BankTransfer />,
64
+ title: 'Bank Transfer',
65
+ content: (
66
+ <>
67
+ <span>Transfer the money to Wise using your bank account.</span>
68
+ <span>0.32 GBP in fees, should arrive in seconds</span>
69
+ </>
70
+ ),
71
+ },
72
+ {
73
+ media: <BankTransfer />,
74
+ title: 'Withdraw from your U.S. bank account (ACH)',
75
+ content: (
76
+ <>
77
+ <span>1.63 USD in total fees.</span>
78
+ <span>
79
+ Pay with ACH using the bank account you’ve connected to Wise. Should arrive in seconds.
80
+ </span>
81
+ </>
82
+ ),
83
+ },
84
+ ];
85
+
86
+ const optionsGroup: SelectOptiopsGroup<CustomData>[] = [
87
+ {
88
+ title: 'Recently used',
89
+ options: recentPaymentMethods,
90
+ },
91
+ {
92
+ // title: 'Payment methods',
93
+ options: allOtherPaymentMethods,
94
+ },
95
+ ];
96
+
97
+ export const Basic: Story = {
98
+ render: (args) => {
99
+ function onChange(value: SelectOptionValue<CustomData>): void {
100
+ console.log(value);
101
+ }
102
+ return (
103
+ <div className="row">
104
+ <div className="col-md-8 col-md-offset-2">
105
+ <Field label={<>Payment method</>}>
106
+ <SelectOption<CustomData>
107
+ media={<Plus size={24} />}
108
+ options={optionsGroup}
109
+ optionsTitle="Payment methods"
110
+ title="No method selected"
111
+ action={{ label: 'Select' }}
112
+ onChange={onChange}
113
+ />
114
+ </Field>
115
+ </div>
116
+
117
+ <div className="col-md-6 col-md-offset-3">
118
+ <Field id="test-test" label={<>Payment method</>}>
119
+ <SelectOption<CustomData>
120
+ media={<Plus size={24} />}
121
+ title="No method selected"
122
+ options={optionsGroup}
123
+ onChange={onChange}
124
+ />
125
+ </Field>
126
+ </div>
127
+
128
+ <div className="col-md-6 col-md-offset-3">
129
+ <Field id="test-test" label={<>Payment method</>} hint="Nice hint message">
130
+ <SelectOption<CustomData>
131
+ media={<Plus size={24} />}
132
+ title="No method selected"
133
+ optionsTitle="Payment method"
134
+ options={optionsGroup}
135
+ onChange={onChange}
136
+ />
137
+ </Field>
138
+ </div>
139
+
140
+ <div className="col-md-6 col-md-offset-3">
141
+ <Field id="test-test" label={<>Payment method</>} error="Validation message">
142
+ <SelectOption<CustomData>
143
+ media={<Plus size={24} />}
144
+ title="No method selected"
145
+ optionsTitle="Payment method"
146
+ options={optionsGroup}
147
+ onChange={onChange}
148
+ />
149
+ </Field>
150
+ </div>
151
+
152
+ <div className="col-md-6 col-md-offset-3">
153
+ <Field label={<>Payment method</>} error="Validation message">
154
+ <SelectOption<CustomData>
155
+ disabled
156
+ media={<Plus size={24} />}
157
+ title="No method selected"
158
+ optionsTitle="Payment method"
159
+ options={optionsGroup}
160
+ onChange={onChange}
161
+ />
162
+ </Field>
163
+ </div>
164
+ </div>
165
+ );
166
+ },
167
+ };
@@ -0,0 +1,134 @@
1
+ import { useRef, useState, ReactNode } from 'react';
2
+ import ActionButton, { ActionButtonProps } from '../actionButton';
3
+ import Chevron from '../chevron';
4
+ import classNames from 'classnames';
5
+ import Option from '../common/Option';
6
+ import type { OptionProps } from '../common/Option/Option';
7
+ import Panel from '../common/panel/Panel';
8
+ import { Position } from '../common';
9
+ import Section from '../section';
10
+ import Header from '../header';
11
+ import { useLayout } from '../common/hooks';
12
+ import BottomSheet from '../common/bottomSheet';
13
+ import { HeaderProps } from '../header/Header';
14
+ import NavigationOption from '../navigationOption';
15
+ import NavigationOptionsList from '../navigationOptionsList';
16
+ import { useInputAttributes } from '../inputs/contexts';
17
+ import messages from './SelectOption.messages';
18
+ import { useIntl } from 'react-intl';
19
+
20
+ export type SelectOptiopsGroup<T = unknown> = {
21
+ title?: HeaderProps['title'];
22
+ options: SelectOptionValue<T>[];
23
+ };
24
+ export type SelectOptionValue<T = unknown> = T & Pick<OptionProps, 'media' | 'title' | 'content'>;
25
+
26
+ export type SelectOptionProps<T> = {
27
+ onChange: (selected: SelectOptionValue<T>) => void;
28
+ selected?: SelectOptionValue<T>;
29
+ optionsTitle?: HeaderProps['title'];
30
+ options: SelectOptiopsGroup<T>[];
31
+ action?: {
32
+ label?: ActionButtonProps['children'];
33
+ };
34
+ } & Omit<OptionProps, 'as' | 'onClick' | 'onChange' | 'showMediaAtAllSizes' | 'decision'>;
35
+
36
+ export default function SelectOption<T = unknown>({
37
+ selected: selectedValueProp = undefined,
38
+ optionsTitle,
39
+ options,
40
+ onChange,
41
+ action,
42
+ ...props
43
+ }: SelectOptionProps<T>) {
44
+ const intl = useIntl();
45
+ const rootRef = useRef(null);
46
+ const [selected, setSelected] = useState(selectedValueProp);
47
+ const [showOptions, setShowOptions] = useState(false);
48
+ const inputAttributes = useInputAttributes();
49
+ function handleOnClick(showOptionsStatus: boolean) {
50
+ return () => {
51
+ setShowOptions(showOptionsStatus);
52
+ };
53
+ }
54
+ function handleOnChange(data: SelectOptionValue<T>) {
55
+ return () => {
56
+ setShowOptions(false);
57
+ setSelected(data);
58
+ onChange(data);
59
+ };
60
+ }
61
+ const isSelected = selected !== undefined;
62
+ const { isMobile } = useLayout();
63
+ function getOptionsContent(isMobileView = false) {
64
+ return (
65
+ <div className={classNames('np-select-option-list')}>
66
+ {options.map((optionsGroup) => (
67
+ // eslint-disable-next-line react/jsx-key
68
+ <Section className={classNames('np-select-option-group', { 'p-a-2': !isMobileView })}>
69
+ {optionsGroup.title && <Header title={optionsGroup.title} />}
70
+ <NavigationOptionsList>
71
+ {optionsGroup.options.map((option) => (
72
+ // eslint-disable-next-line react/jsx-key
73
+ <NavigationOption
74
+ isContainerAligned={isMobileView}
75
+ showMediaCircle
76
+ showMediaAtAllSizes
77
+ media={option.media}
78
+ title={option.title}
79
+ content={option.content}
80
+ onClick={handleOnChange(option)}
81
+ />
82
+ ))}
83
+ </NavigationOptionsList>
84
+ </Section>
85
+ ))}
86
+ </div>
87
+ );
88
+ }
89
+ return (
90
+ <>
91
+ <Option
92
+ ref={rootRef}
93
+ {...props}
94
+ {...inputAttributes}
95
+ showMediaAtAllSizes
96
+ media={(isSelected ? selected : props).media}
97
+ title={(isSelected ? selected : props).title}
98
+ content={(isSelected ? selected : props).content}
99
+ className={classNames(
100
+ 'np-select-option',
101
+ { 'np-select-option-selected': isSelected },
102
+ props.className,
103
+ )}
104
+ button={
105
+ isSelected ? (
106
+ <Chevron />
107
+ ) : (
108
+ <ActionButton disabled={props.disabled} onClick={handleOnClick(true)}>
109
+ {action?.label || intl.formatMessage(messages.actionLabel)}
110
+ </ActionButton>
111
+ )
112
+ }
113
+ onClick={isSelected ? handleOnClick(true) : undefined}
114
+ />
115
+ {isMobile ? (
116
+ <BottomSheet open={showOptions} onClose={handleOnClick(false)}>
117
+ {getOptionsContent(true)}
118
+ </BottomSheet>
119
+ ) : (
120
+ <Panel
121
+ anchorWidth
122
+ open={showOptions}
123
+ flip={false}
124
+ altAxis={false}
125
+ anchorRef={rootRef}
126
+ position={Position.BOTTOM}
127
+ onClose={handleOnClick(false)}
128
+ >
129
+ {getOptionsContent(false)}
130
+ </Panel>
131
+ )}
132
+ </>
133
+ );
134
+ }
@@ -0,0 +1,2 @@
1
+ export { default } from './SelectOption';
2
+ export type { SelectOptionProps, SelectOptionValue, SelectOptiopsGroup } from './SelectOption';
@@ -11,6 +11,7 @@ describe('SlidingPanel', () => {
11
11
  className: undefined,
12
12
  slidingPanelPositionFixed: false,
13
13
  showSlidingPanelBorder: false,
14
+ testId: undefined,
14
15
  };
15
16
 
16
17
  it('renders with right props', () => {
@@ -24,7 +25,7 @@ describe('SlidingPanel', () => {
24
25
 
25
26
  expect(cssTransition()).toHaveLength(1);
26
27
 
27
- expect(cssTransition().props()).toStrictEqual({
28
+ expect(cssTransition().props()).toEqual({
28
29
  className: 'sliding-panel sliding-panel--open-left',
29
30
  children: null,
30
31
  });
@@ -12,6 +12,7 @@ export interface SlidingPanelProps
12
12
  open: boolean;
13
13
  showSlidingPanelBorder?: boolean;
14
14
  slidingPanelPositionFixed?: boolean;
15
+ testId?: string;
15
16
  }
16
17
 
17
18
  const SlidingPanel = forwardRef(
@@ -23,6 +24,7 @@ const SlidingPanel = forwardRef(
23
24
  slidingPanelPositionFixed,
24
25
  className,
25
26
  children,
27
+ testId,
26
28
  ...rest
27
29
  }: Omit<SlidingPanelProps, 'ref'>,
28
30
  reference: React.ForwardedRef<HTMLDivElement | null>,
@@ -44,6 +46,7 @@ const SlidingPanel = forwardRef(
44
46
  >
45
47
  <div
46
48
  ref={localReference}
49
+ data-testid={testId}
47
50
  className={classNames(
48
51
  'sliding-panel',
49
52
  `sliding-panel--open-${position}`,
@@ -0,0 +1,71 @@
1
+ import { render, screen, waitFor } from '@testing-library/react';
2
+ import Sticky, { StickyProps } from './Sticky';
3
+
4
+ describe('Sticky', () => {
5
+ const defaultProps = {
6
+ open: true,
7
+ children: <div>Test Content</div>,
8
+ position: 'bottom' as const,
9
+ testId: 'test-sticky-panel',
10
+ };
11
+
12
+ let rerenderSticky: (props?: StickyProps) => void;
13
+
14
+ beforeEach(() => {
15
+ const { rerender } = render(<Sticky {...defaultProps} />);
16
+
17
+ rerenderSticky = (props?: StickyProps) => {
18
+ rerender(<Sticky {...defaultProps} {...props} />);
19
+ };
20
+ });
21
+
22
+ test('renders with default props', () => {
23
+ expect(screen.getByTestId('test-sticky-panel')).toBeVisible();
24
+ expect(screen.getByTestId('test-sticky-panel')).toHaveClass('sliding-panel--open-bottom');
25
+ expect(screen.getByText('Test Content')).toBeInTheDocument();
26
+ });
27
+
28
+ test('renders with open `false`', async () => {
29
+ const props: StickyProps = {
30
+ ...defaultProps,
31
+ open: false, // Ensure the Sticky is initially open
32
+ };
33
+
34
+ expect(screen.getByTestId('test-sticky-panel')).toBeVisible();
35
+
36
+ // Change props to close the Sticky
37
+ rerenderSticky(props);
38
+
39
+ await waitFor(() => {
40
+ // Use queryByText instead of getByText for conditional presence checks
41
+ expect(screen.queryByText('Test Content')).not.toBeInTheDocument();
42
+ });
43
+ });
44
+
45
+ it('renders new content', () => {
46
+ const props: StickyProps = {
47
+ ...defaultProps,
48
+ children: <div>New Test Content</div>,
49
+ };
50
+ expect(screen.getByText('Test Content')).toBeInTheDocument();
51
+
52
+ // Change props
53
+ rerenderSticky(props);
54
+
55
+ expect(screen.getByText('New Test Content')).toBeInTheDocument();
56
+ });
57
+
58
+ it('renders with position set to `top`', () => {
59
+ const props: StickyProps = {
60
+ ...defaultProps,
61
+ position: 'top',
62
+ };
63
+ expect(screen.getByTestId('test-sticky-panel')).toBeInTheDocument();
64
+ expect(screen.getByTestId('test-sticky-panel')).toHaveClass('sliding-panel--open-bottom');
65
+
66
+ // Change props
67
+ rerenderSticky(props);
68
+
69
+ expect(screen.getByTestId('test-sticky-panel')).toHaveClass('sliding-panel--open-top');
70
+ });
71
+ });
@@ -1,22 +1,55 @@
1
- import { select, boolean } from '@storybook/addon-knobs';
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
2
 
3
+ import React, { useState } from 'react';
3
4
  import Sticky from './Sticky';
4
5
 
5
- export default {
6
+ const meta: Meta<typeof Sticky> = {
6
7
  component: Sticky,
7
8
  title: 'Other/Sticky',
9
+ args: {
10
+ open: true,
11
+ position: 'bottom', // Default position
12
+ children: (
13
+ <div className="d-flex justify-content-start align-items-start flex-wrap p-x-4 p-y-4">
14
+ <p className="m-b-0">Default text for Sticky component.</p>
15
+ </div>
16
+ ),
17
+ },
8
18
  };
9
19
 
10
- export const Basic = () => {
11
- const open = boolean('open', false);
12
- const position = select('position', ['top', 'bottom'], 'bottom');
13
- return (
14
- <Sticky open={open} position={position}>
15
- <div className="d-flex justify-content-start align-items-start flex-wrap p-x-4 p-y-4">
16
- Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has
17
- been the industry standard dummy text ever since the 1500s, when an unknown printer took a
18
- galley of type and scrambled it to
20
+ export default meta;
21
+
22
+ // Represents a story object for the `Sticky` component.
23
+ type Story = StoryObj<typeof Sticky>;
24
+
25
+ export const Default: Story = {}; // Default story with no additional props
26
+
27
+ export const PositionTop: Story = {
28
+ args: {
29
+ position: 'top', // Set the position prop to 'top'
30
+ },
31
+ };
32
+
33
+ export const WithLongContent: Story = {
34
+ args: {
35
+ children: (
36
+ <div className="p-x-4 p-y-4">
37
+ <p>
38
+ Lorem ipsum dolor sit, amet consectetur adipisicing elit. Optio ipsa rem fugiat
39
+ repellendus nisi dolorum, recusandae aperiam repudiandae natus quaerat, explicabo fugit!
40
+ Odit illum vero eius quasi, error soluta veritatis.
41
+ </p>
42
+ <p>
43
+ Recusandae a animi tenetur magni itaque optio in aut enim odio. Minima, veritatis error
44
+ dicta expedita aliquam officiis deleniti repellat rerum nam ad quam dolorum reiciendis
45
+ voluptas doloremque quis eveniet.
46
+ </p>
47
+ <p>
48
+ Adipisci nulla quos magnam blanditiis minima nesciunt odio mollitia, fuga ullam aliquid
49
+ qui iure delectus dolores corporis officiis autem iste quia at ea sint tempore,
50
+ repudiandae amet? Error, praesentium eaque.
51
+ </p>
19
52
  </div>
20
- </Sticky>
21
- );
53
+ ),
54
+ },
22
55
  };
@@ -1,16 +1,60 @@
1
1
  import { Position } from '../common';
2
2
  import SlidingPanel from '../slidingPanel';
3
+ import { FunctionComponent } from 'react';
3
4
 
4
5
  export interface StickyProps {
6
+ /** Optional props that determines if the Sticky component is open or closed. Default value is `true`. */
5
7
  open?: boolean;
6
- position?: `${Position.TOP | Position.BOTTOM}`;
8
+
9
+ /** Optional props that specifies the position of the Sticky component on the screen. Can be either `Position.TOP` or `Position.BOTTOM`. */
10
+ position?: `${Position.TOP}` | `${Position.BOTTOM}`;
11
+
12
+ /** Optional prop for children components to be rendered inside the Sticky component. */
7
13
  children?: React.ReactNode;
14
+
15
+ /** Optional prop to specify the ID used for testing */
16
+ testId?: string;
8
17
  }
9
18
 
10
- export default function Sticky({ open = true, position = 'bottom', children }: StickyProps) {
19
+ /**
20
+ * Sticky component.
21
+ *
22
+ * `Sticky` is a component that renders a `SlidingPanel` with specified props.
23
+ * It uses the `SlidingPanel` component to create a panel that can slide in and out of view,
24
+ * based on the `open` prop. It can be positioned at the top or bottom of the container,
25
+ * as specified by the `position` prop.
26
+ *
27
+ * @component
28
+ * @param {boolean} open - Determines if the Sticky component is open or closed.
29
+ * @param {('top'|'bottom')} position - Specifies the position.
30
+ * @param {ReactNode} children - Children content.
31
+ * @param {string} testId - ID used for testing.
32
+ * @returns {JSX.Element} The `SlidingPanel` component with applied props.
33
+ * @example
34
+ * <Button onClick={() => setOpen(!open)}>Open Sticky</Button>
35
+ * <Sticky open={open} position={'bottom'}>
36
+ * <div>
37
+ * <Button onClick={() => setOpen(!open)}>Close Sticky</Button>
38
+ * </div>
39
+ * </Sticky>
40
+ */
41
+ const Sticky: FunctionComponent<StickyProps> = ({
42
+ open = true,
43
+ position = Position.BOTTOM,
44
+ children,
45
+ testId,
46
+ }: StickyProps) => {
11
47
  return (
12
- <SlidingPanel open={open} position={position} slidingPanelPositionFixed showSlidingPanelBorder>
48
+ <SlidingPanel
49
+ testId={testId}
50
+ open={open}
51
+ position={position}
52
+ slidingPanelPositionFixed
53
+ showSlidingPanelBorder
54
+ >
13
55
  {children}
14
56
  </SlidingPanel>
15
57
  );
16
- }
58
+ };
59
+
60
+ export default Sticky;
@@ -26,9 +26,6 @@
26
26
  padding: 16px;
27
27
  padding: var(--padding-small);
28
28
  }
29
- .np-theme-personal .np-upload-input .np-upload-button .media {
30
- align-items: start;
31
- }
32
29
  .np-theme-personal .np-upload-input .np-upload-input--square-top {
33
30
  border-top-right-radius: 0px;
34
31
  border-top-left-radius: 0px;
@@ -36,9 +33,6 @@
36
33
  .np-theme-personal .np-upload-input .np-upload-item__remove-button {
37
34
  border-radius: 0;
38
35
  border-radius: initial;
39
- display: inline-flex;
40
- padding-top: 16px;
41
- padding-top: var(--padding-small);
42
36
  }
43
37
  .np-theme-personal .np-upload-input .np-upload-icon {
44
38
  color: var(--color-interactive-primary);
@@ -61,10 +55,6 @@
61
55
  .np-theme-personal .np-upload-input .media-body .text-negative {
62
56
  color: var(--color-sentiment-negative) !important;
63
57
  }
64
- .np-theme-personal .np-upload-input-errors {
65
- padding-left: 0;
66
- list-style-position: inside;
67
- }
68
58
  .np-theme-personal .np-upload-input .status-circle {
69
59
  width: 24px;
70
60
  width: var(--size-x-small);
@@ -27,10 +27,6 @@
27
27
  .np-upload-button {
28
28
  border-radius: @small-border-minus-one;
29
29
  padding: var(--padding-small);
30
-
31
- .media {
32
- align-items: start;
33
- }
34
30
  }
35
31
 
36
32
  .np-upload-input--square-top {
@@ -40,8 +36,6 @@
40
36
 
41
37
  .np-upload-item__remove-button {
42
38
  border-radius: unset;
43
- display: inline-flex;
44
- padding-top: var(--padding-small);
45
39
  }
46
40
 
47
41
  .np-upload-icon {
@@ -68,11 +62,6 @@
68
62
  }
69
63
  }
70
64
 
71
- &-errors {
72
- padding-left: 0;
73
- list-style-position: inside;
74
- }
75
-
76
65
  .status-circle {
77
66
  width: var(--size-x-small);
78
67
  height: var(--size-x-small);