From 3e62507b481862f1a126d46af75f44554d0b73e0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mateusz=20Wlekli=C5=84ski?=
<114148518+mwleklinskiVL@users.noreply.github.com>
Date: Fri, 3 Nov 2023 13:39:03 +0100
Subject: [PATCH] Chore/review components (#93)
* chore: NO-JIRA fix correct type when importing package
* chore: TET-400 fix SocialIcons size
* chore: TET-396 RadioButton corrections
* chore: TET-383 fix Avatar correction
* chore: TET-405 change StatusDot stroked to hasStroke
* fix: TET-405 StatusDot Test fix
* fix: TET-385 fix Button
* fix: TET-398 clear button in TextInput
* fix: TET-403 change helperText beforeIcon to hasBeforeIcon
* fix: TET-382 change AlerBanner Positive to Success intent
* fix: TET-384 add wrapper for vertical divider
* fix: TET-402 fix height of the toast
* fix: TET-402 change location of typo in config Toast
* fix: TET-395 change size of a ring to smaller (from 2px to 1px)
* fix: TET-384 grid presentation and emphasis order
* fix: TET-384 change color of border Badge
* fix: TET-390 fix presentation of an IconButton, fix BareButton
* fix: TET-386 adjust Checkbox component
* feat: TET-399 extract useTextInput hook and use it to create Select component
* chore: NO-JIRA add bg to text Input
* fix: NO-JIRA fix export file
* chore: NO-JIRA: change React.FC to FC
* chore: NO-JIRA update readme
---
README.md | 35 +++++++
package.json | 2 +-
.../AlertBanner/AlertBanner.stories.tsx | 9 +-
.../AlertBanner/AlertBanner.styles.ts | 10 +-
.../AlertBanner/AlertBanner.test.tsx | 4 +-
.../types/AlertBannerIntent.type.ts | 2 +-
src/components/Avatar/Avatar.stories.tsx | 5 +-
src/components/Avatar/Avatar.styles.ts | 2 +-
src/components/Avatar/Avatar.tsx | 2 +-
.../Avatar/types/AvatarAppearance.type.ts | 35 +++----
src/components/Badge/Badge.stories.tsx | 9 ++
src/components/Badge/Badge.styles.ts | 2 +-
src/components/Badge/Badge.tsx | 6 +-
src/components/Button/Button.stories.tsx | 10 ++
src/components/Button/Button.styles.ts | 4 +-
src/components/Button/Button.tsx | 6 +-
.../stylesBuilder/stylesBuilder.test.ts | 2 +-
src/components/Checkbox/Checkbox.props.ts | 9 +-
src/components/Checkbox/Checkbox.stories.tsx | 13 ++-
src/components/Checkbox/Checkbox.test.tsx | 23 +++--
src/components/Checkbox/Checkbox.tsx | 16 +++-
.../CheckboxGroup/CheckboxGroup.tsx | 14 ++-
src/components/Counter/Counter.tsx | 2 +-
src/components/Divider/Divider.stories.tsx | 5 +
src/components/Divider/Divider.tsx | 2 +-
src/components/HelperText/HelperText.props.ts | 2 +-
.../HelperText/HelperText.stories.tsx | 2 +-
src/components/HelperText/HelperText.test.tsx | 10 +-
src/components/HelperText/HelperText.tsx | 4 +-
.../IconButton/IconButton.styles.ts | 6 +-
src/components/IconButton/IconButton.tsx | 6 +-
.../InlineBanner/InlineBanner.styles.ts | 1 +
src/components/InlineBanner/InlineBanner.tsx | 9 +-
.../InlineMessage/InlineMessage.tsx | 6 +-
.../InlineSearchInput/InlineSearchInput.tsx | 6 +-
src/components/Label/Label.tsx | 4 +-
src/components/Loader/Loader.tsx | 10 +-
src/components/Popover/Popover.styles.ts | 2 +-
src/components/Popover/Popover.tsx | 2 +-
.../RadioButton/RadioButton.stories.tsx | 1 +
src/components/RadioButton/RadioButton.tsx | 22 ++++-
.../RadioButtonGroup/RadioButtonGroup.tsx | 8 +-
src/components/SearchInput/SearchInput.tsx | 8 +-
src/components/Select/Select.test.tsx | 6 +-
src/components/Select/Select.tsx | 92 +++++++++++++++++--
src/components/SocialButton/SocialButton.tsx | 2 +-
src/components/SocialButton/socials/Apple.tsx | 4 +-
.../SocialButton/socials/Facebook.tsx | 14 +--
src/components/SocialButton/socials/Figma.tsx | 22 ++---
.../SocialButton/socials/Github.tsx | 4 +-
.../SocialButton/socials/Google.tsx | 20 ++--
.../SocialButton/socials/Twitter.tsx | 4 +-
.../SocialButton/socials/WithLoader.tsx | 2 +-
.../SocialButton/socials/socials.ts | 6 +-
src/components/StatusDot/StatusDot.props.ts | 3 +-
.../StatusDot/StatusDot.stories.tsx | 4 +-
src/components/StatusDot/StatusDot.styles.ts | 4 +-
src/components/StatusDot/StatusDot.test.tsx | 4 +-
src/components/StatusDot/StatusDot.tsx | 8 +-
.../StatusDot/stylesBuilder/stylesBuilder.ts | 8 +-
src/components/Tag/Tag.tsx | 10 +-
src/components/TextInput/TextInput.styles.ts | 1 +
src/components/TextInput/TextInput.tsx | 64 ++++---------
src/components/TextInput/useTextInput.ts | 67 ++++++++++++++
src/components/Toast/Toast.styles.ts | 4 +-
src/components/Toast/Toast.tsx | 2 +-
.../Toast/stylesBuilder/stylesBuilder.ts | 8 +-
src/docs-components/AlertBannerDocs.tsx | 8 +-
src/docs-components/AvatarDocs.tsx | 4 +-
src/docs-components/BadgeDocs.tsx | 60 +++++++-----
src/docs-components/ButtonDocs/ButtonDocs.tsx | 4 +-
src/docs-components/ButtonDocs/ButtonRow.tsx | 2 +-
src/docs-components/CheckboxDocs.tsx | 58 +++++++-----
src/docs-components/HelperTextDocs.tsx | 2 +-
src/docs-components/IconButtonDocs.tsx | 1 +
src/docs-components/RadioButtonDocs.tsx | 35 ++++---
src/docs-components/StatusDotDocs.tsx | 2 +-
src/docs-components/TagDocs.tsx | 4 +-
src/docs-components/TetDocs.tsx | 2 +-
src/docs-components/common/Cols.tsx | 8 +-
src/docs-components/common/Hero.tsx | 2 +-
src/docs-components/common/SectionHeader.tsx | 8 +-
src/docs-components/common/States.tsx | 52 +++++++----
src/index.ts | 1 +
84 files changed, 626 insertions(+), 328 deletions(-)
create mode 100644 src/components/TextInput/useTextInput.ts
diff --git a/README.md b/README.md
index cd335c65..15780f65 100644
--- a/README.md
+++ b/README.md
@@ -191,6 +191,41 @@ If you want to dive deeper into the components Tetrisly offers, check out our of
You can also check out our Storybook, which is our Documentation for React components (now in progress): [Tetrisly Storybook](https://virtuslab.github.io/tetrisly-react/?path=/docs/alertbanner--docs)
+## Customization
+
+All Tetrisly components have a `custom` prop. It makes it possible to customize the component without the need to create a new one. Below you can see an example of Button customization
+
+### Button
+
+If you want to change any of button styles, you can make it by passing custom props with object based on
+specific component config.
+
+For instance, to change background-color of appereance="primary" intent="secondary" variant to pink, just pass
+refferenced object structure:
+
+```jsx
+
+```
+
+we are still working on it, thanks for your feedback here!
+
### Useful links
- [Tetrisly Storybook](https://storybook.tetrisly.com/)
diff --git a/package.json b/package.json
index 70abdb2e..ef691bdb 100644
--- a/package.json
+++ b/package.json
@@ -84,7 +84,7 @@
"exports": {
".": {
"import": "./dist/tetrisly-react.es.js",
- "require": "./dist/tetrisly-react.umd.cjs"
+ "require": "./dist/tetrisly-react.umd.js"
}
},
"repository": {
diff --git a/src/components/AlertBanner/AlertBanner.stories.tsx b/src/components/AlertBanner/AlertBanner.stories.tsx
index ff3b4261..a09c883d 100644
--- a/src/components/AlertBanner/AlertBanner.stories.tsx
+++ b/src/components/AlertBanner/AlertBanner.stories.tsx
@@ -23,6 +23,13 @@ const meta = {
},
],
},
+ argTypes: {
+ intent: {
+ options: ['none', 'success', 'warning', 'negative'],
+ defaultValue: 'none',
+ control: { type: 'radio' },
+ },
+ },
parameters: {
docs: {
description: {
@@ -46,7 +53,7 @@ export const Default: Story = {};
export const Positive: Story = {
args: {
- intent: 'positive',
+ intent: 'success',
},
};
diff --git a/src/components/AlertBanner/AlertBanner.styles.ts b/src/components/AlertBanner/AlertBanner.styles.ts
index 4ec1bba4..2de57dba 100644
--- a/src/components/AlertBanner/AlertBanner.styles.ts
+++ b/src/components/AlertBanner/AlertBanner.styles.ts
@@ -23,7 +23,7 @@ export const defaultConfig = {
backgroundColor: '$color-background-neutral-strong',
color: '$color-content-primary-inverted',
},
- positive: {
+ success: {
backgroundColor: '$color-background-positive-strong',
color: '$color-content-primary-inverted',
},
@@ -53,13 +53,13 @@ export const defaultConfig = {
},
} satisfies AlertBannerConfig;
-export const resolveIconName = (intent: AlertBannerIntent): IconName<20> => {
- const iconConfig: Record> = {
+export const resolveIconName = (intent: AlertBannerIntent) => {
+ const iconConfig = {
none: '20-info-fill',
- positive: '20-info-fill',
+ success: '20-check-circle-fill',
warning: '20-warning-fill',
negative: '20-alert-fill',
- };
+ } satisfies Record>;
return iconConfig[intent];
};
diff --git a/src/components/AlertBanner/AlertBanner.test.tsx b/src/components/AlertBanner/AlertBanner.test.tsx
index af0d8dc0..b11e30f1 100644
--- a/src/components/AlertBanner/AlertBanner.test.tsx
+++ b/src/components/AlertBanner/AlertBanner.test.tsx
@@ -53,9 +53,9 @@ describe('AlertBanner', () => {
expect(alertBanner).toHaveStyle('background-color: rgb(85, 95, 109);');
});
- it('should render correct intent color (positive)', () => {
+ it('should render correct intent color (success)', () => {
const alertBanner = getAlertBanner(
- ,
+ ,
);
expect(alertBanner).toHaveStyle('color: rgb(255,255,255);');
expect(alertBanner).toHaveStyle('background-color: rgb(29, 124, 77);');
diff --git a/src/components/AlertBanner/types/AlertBannerIntent.type.ts b/src/components/AlertBanner/types/AlertBannerIntent.type.ts
index 67b0d85d..ba47c21d 100644
--- a/src/components/AlertBanner/types/AlertBannerIntent.type.ts
+++ b/src/components/AlertBanner/types/AlertBannerIntent.type.ts
@@ -1 +1 @@
-export type AlertBannerIntent = 'none' | 'positive' | 'warning' | 'negative';
+export type AlertBannerIntent = 'none' | 'success' | 'warning' | 'negative';
diff --git a/src/components/Avatar/Avatar.stories.tsx b/src/components/Avatar/Avatar.stories.tsx
index 62ce878b..bf2e0094 100644
--- a/src/components/Avatar/Avatar.stories.tsx
+++ b/src/components/Avatar/Avatar.stories.tsx
@@ -17,9 +17,12 @@ const meta = {
img: { if: { arg: 'appearance', eq: 'image' } },
initials: { if: { arg: 'appearance', neq: 'image' } },
emphasis: { if: { arg: 'appearance', neq: 'image' } },
+ appearance: {
+ options: appearances,
+ control: { type: 'select' },
+ },
},
parameters: {
- controls: { sort: 'alpha' },
docs: {
description: {
component:
diff --git a/src/components/Avatar/Avatar.styles.ts b/src/components/Avatar/Avatar.styles.ts
index 59f6e2f1..97219011 100644
--- a/src/components/Avatar/Avatar.styles.ts
+++ b/src/components/Avatar/Avatar.styles.ts
@@ -119,7 +119,7 @@ export const defaultConfig = {
orange: {
emphasis: {
high: {
- color: '$color-nonSemantic-white-content-primary',
+ color: '$color-nonSemantic-grey-content-primary',
backgroundColor: '$color-nonSemantic-orange-background-strong',
},
low: {
diff --git a/src/components/Avatar/Avatar.tsx b/src/components/Avatar/Avatar.tsx
index dcfc429d..8eeabe13 100644
--- a/src/components/Avatar/Avatar.tsx
+++ b/src/components/Avatar/Avatar.tsx
@@ -1,4 +1,4 @@
-import { FC, useMemo } from 'react';
+import { type FC, useMemo } from 'react';
import type { AvatarProps } from './Avatar.props';
import { stylesBuilder } from './stylesBuilder';
diff --git a/src/components/Avatar/types/AvatarAppearance.type.ts b/src/components/Avatar/types/AvatarAppearance.type.ts
index e25e7f97..00108887 100644
--- a/src/components/Avatar/types/AvatarAppearance.type.ts
+++ b/src/components/Avatar/types/AvatarAppearance.type.ts
@@ -1,17 +1,20 @@
-export type AvatarAppearanceColors =
- | 'blue'
- | 'green'
- | 'grey'
- | 'red'
- | 'orange'
- | 'raspberry'
- | 'magenta'
- | 'purple'
- | 'grape'
- | 'violet'
- | 'cyan'
- | 'teal'
- | 'aquamarine'
- | 'emerald';
+export const avatarAppearanceColors = [
+ 'blue',
+ 'green',
+ 'grey',
+ 'red',
+ 'orange',
+ 'raspberry',
+ 'magenta',
+ 'purple',
+ 'grape',
+ 'violet',
+ 'cyan',
+ 'teal',
+ 'aquamarine',
+ 'emerald',
+] as const;
-export type AvatarAppearance = AvatarAppearanceColors | 'image';
+export type AvatarAppearanceColors = (typeof avatarAppearanceColors)[number];
+
+export type AvatarAppearance = 'image' | AvatarAppearanceColors;
diff --git a/src/components/Badge/Badge.stories.tsx b/src/components/Badge/Badge.stories.tsx
index 01acc2f7..21cc936a 100644
--- a/src/components/Badge/Badge.stories.tsx
+++ b/src/components/Badge/Badge.stories.tsx
@@ -1,6 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Badge } from './Badge';
+import type { BadgeEmphasis } from './BadgeEmphasis.type';
import { BadgeDocs } from '@/docs-components/BadgeDocs';
import { TetDocs } from '@/docs-components/TetDocs';
@@ -9,6 +10,14 @@ const meta = {
title: 'Badge',
component: Badge,
tags: ['autodocs'],
+ argTypes: {
+ emphasis: {
+ control: {
+ type: 'select',
+ options: ['high', 'medium', 'low'] satisfies BadgeEmphasis[],
+ },
+ },
+ },
parameters: {
docs: {
description: {
diff --git a/src/components/Badge/Badge.styles.ts b/src/components/Badge/Badge.styles.ts
index 84980b9f..e821e272 100644
--- a/src/components/Badge/Badge.styles.ts
+++ b/src/components/Badge/Badge.styles.ts
@@ -271,7 +271,7 @@ export const defaultConfig = {
},
medium: {
border: '1px solid',
- borderColor: '$color-nonSemantic-grey-border-strong',
+ borderColor: '$color-nonSemantic-grey-border-subtle',
color: '$color-nonSemantic-grey-content-primary',
backgroundColor: '$color-nonSemantic-white-background-strong',
},
diff --git a/src/components/Badge/Badge.tsx b/src/components/Badge/Badge.tsx
index 23367160..220cad8a 100644
--- a/src/components/Badge/Badge.tsx
+++ b/src/components/Badge/Badge.tsx
@@ -1,11 +1,11 @@
import { Icon } from '@virtuslab/tetrisly-icons';
-import { FC, useMemo } from 'react';
+import { type FC, useMemo } from 'react';
-import { BadgeProps } from './Badge.props';
+import type { BadgeProps } from './Badge.props';
import { stylesBuilder } from './stylesBuilder';
import { tet } from '@/tetrisly';
-import { MarginProps } from '@/types/MarginProps';
+import type { MarginProps } from '@/types/MarginProps';
export const Badge: FC = ({
appearance,
diff --git a/src/components/Button/Button.stories.tsx b/src/components/Button/Button.stories.tsx
index c05997a3..0fab6d26 100644
--- a/src/components/Button/Button.stories.tsx
+++ b/src/components/Button/Button.stories.tsx
@@ -23,6 +23,16 @@ const meta = {
defaultValue: 'medium',
control: { type: 'radio' },
},
+ variant: {
+ options: ['default', 'ghost', 'bare'],
+ defaultValue: 'default',
+ control: { type: 'radio' },
+ },
+ intent: {
+ options: ['none', 'success', 'destructive'],
+ defaultValue: 'none',
+ control: { type: 'radio' },
+ },
},
parameters: {
docs: {
diff --git a/src/components/Button/Button.styles.ts b/src/components/Button/Button.styles.ts
index c5aba8d7..ea288cee 100644
--- a/src/components/Button/Button.styles.ts
+++ b/src/components/Button/Button.styles.ts
@@ -178,7 +178,7 @@ const size = {
const commonConfig = {
display: 'inline-flex',
- gap: '$space-component-gap-small',
+ gap: '$space-component-gap-xSmall',
w: 'fit-content',
justifyContent: 'center',
alignItems: 'center',
@@ -304,7 +304,7 @@ const defaultButtonConfig = {
const ghostButtonConfig = {
...commonConfig,
- borderRadius: '$border-radius-medium',
+ borderRadius: '$border-radius-large',
backgroundColor: {
_: 'transparent',
hover: '$color-action-ghost-hover',
diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx
index fb786988..b6abe707 100644
--- a/src/components/Button/Button.tsx
+++ b/src/components/Button/Button.tsx
@@ -1,7 +1,7 @@
import { Icon } from '@virtuslab/tetrisly-icons';
-import { FC, useMemo } from 'react';
+import { type FC, useMemo } from 'react';
-import { ButtonProps } from './Button.props';
+import type { ButtonProps } from './Button.props';
import { stylesBuilder } from './stylesBuilder';
import { tet } from '../../tetrisly';
import { Loader } from '../Loader';
@@ -67,7 +67,7 @@ export const Button: FC = ({
)}
{beforeIcon && state !== 'loading' && }
{children}
- {dropdown && }
+ {dropdown && }
{afterIcon && !dropdown && }
);
diff --git a/src/components/Button/stylesBuilder/stylesBuilder.test.ts b/src/components/Button/stylesBuilder/stylesBuilder.test.ts
index 348b9228..bbfdc889 100644
--- a/src/components/Button/stylesBuilder/stylesBuilder.test.ts
+++ b/src/components/Button/stylesBuilder/stylesBuilder.test.ts
@@ -27,7 +27,7 @@ describe('stylesBuilder', () => {
boxShadow: '$elevation-bottom-100',
color: '$color-action-inverted-normal',
display: 'inline-flex',
- gap: '$space-component-gap-small',
+ gap: '$space-component-gap-xSmall',
justifyContent: 'center',
opacity: {
disabled: '$opacity-disabled',
diff --git a/src/components/Checkbox/Checkbox.props.ts b/src/components/Checkbox/Checkbox.props.ts
index 7201ec84..2568a1cf 100644
--- a/src/components/Checkbox/Checkbox.props.ts
+++ b/src/components/Checkbox/Checkbox.props.ts
@@ -1,6 +1,7 @@
import type { InputHTMLAttributes } from 'react';
import type { CheckboxConfig } from './Checkbox.styles';
+import { HelperTextProps } from '../HelperText';
export type CheckboxProps = {
isChecked?: boolean;
@@ -13,5 +14,11 @@ export type CheckboxProps = {
> &
(
| { label?: string; helperText?: never }
- | { label: string; helperText?: string }
+ | {
+ label: string;
+ helperText?: Pick<
+ HelperTextProps,
+ 'hasBeforeIcon' | 'counter' | 'text'
+ >;
+ }
);
diff --git a/src/components/Checkbox/Checkbox.stories.tsx b/src/components/Checkbox/Checkbox.stories.tsx
index a274888e..8e15917a 100644
--- a/src/components/Checkbox/Checkbox.stories.tsx
+++ b/src/components/Checkbox/Checkbox.stories.tsx
@@ -11,6 +11,14 @@ const meta = {
title: 'Checkbox',
component: Checkbox,
tags: ['autodocs'],
+ argTypes: {
+ state: {
+ control: {
+ type: 'select',
+ options: [undefined, 'disabled', 'alert'],
+ },
+ },
+ },
parameters: {
docs: {
description: {
@@ -34,6 +42,7 @@ export const Default: Story = {};
export const Checked: Story = {
args: {
isChecked: true,
+ onChange: () => {},
},
};
@@ -87,7 +96,7 @@ export const Alert: Story = {
args: {
state: 'alert',
label: 'Label',
- helperText: 'Helper text',
+ helperText: { text: 'Helper text' },
},
};
@@ -100,6 +109,6 @@ export const Label: Story = {
export const HelperText: Story = {
args: {
label: 'Label',
- helperText: 'Helper text',
+ helperText: { text: 'Helper text' },
},
};
diff --git a/src/components/Checkbox/Checkbox.test.tsx b/src/components/Checkbox/Checkbox.test.tsx
index a1d20e94..97903333 100644
--- a/src/components/Checkbox/Checkbox.test.tsx
+++ b/src/components/Checkbox/Checkbox.test.tsx
@@ -19,16 +19,19 @@ const getCheckbox = (jsx: JSX.Element) => {
};
describe('Checkbox', () => {
- customPropTester(, {
- containerId: 'checkbox',
- innerElements: {
- input: [],
- checkboxContainer: [],
- checkboxIcon: [],
- label: [],
- helperText: [],
+ customPropTester(
+ ,
+ {
+ containerId: 'checkbox',
+ innerElements: {
+ input: [],
+ checkboxContainer: [],
+ checkboxIcon: [],
+ label: [],
+ helperText: [],
+ },
},
- });
+ );
beforeEach(() => {
handleEventMock.mockReset();
@@ -101,7 +104,7 @@ describe('Checkbox', () => {
it('should render helper text if props provided', () => {
const { label, helperText } = getCheckbox(
- ,
+ ,
);
expect(label).toHaveTextContent('Label');
diff --git a/src/components/Checkbox/Checkbox.tsx b/src/components/Checkbox/Checkbox.tsx
index 988de100..981981c3 100644
--- a/src/components/Checkbox/Checkbox.tsx
+++ b/src/components/Checkbox/Checkbox.tsx
@@ -34,6 +34,7 @@ export const Checkbox = forwardRef<
label,
helperText,
custom,
+ onChange,
...restProps
},
checkboxForwardRef,
@@ -64,6 +65,15 @@ export const Checkbox = forwardRef<
}
}, [checkboxInternalRef, label]);
+ if (
+ (onChange === undefined && isChecked !== undefined) ||
+ (onChange !== undefined && isChecked === undefined)
+ ) {
+ console.warn(
+ 'Checkbox: onChange and isChecked have to be either both provided or both not provided',
+ );
+ }
+
const input = (
)}
diff --git a/src/components/CheckboxGroup/CheckboxGroup.tsx b/src/components/CheckboxGroup/CheckboxGroup.tsx
index 22f8e23a..9a1700da 100644
--- a/src/components/CheckboxGroup/CheckboxGroup.tsx
+++ b/src/components/CheckboxGroup/CheckboxGroup.tsx
@@ -1,25 +1,23 @@
import {
Children,
FC,
+ ForwardRefExoticComponent,
isValidElement,
PropsWithChildren,
useMemo,
} from 'react';
-import type {
- CheckboxGroupProps,
- CheckboxGroupItemProps,
-} from './CheckboxGroup.props';
+import type { CheckboxGroupProps } from './CheckboxGroup.props';
import { stylesBuilder } from './stylesBuilder';
-import { Checkbox } from '../Checkbox';
+import { Checkbox, type CheckboxProps } from '../Checkbox';
import { HelperText } from '../HelperText';
import { Label } from '../Label';
import { tet } from '@/tetrisly';
-import { MarginProps } from '@/types';
+import type { MarginProps } from '@/types';
type Props = FC> & {
- Item: FC;
+ Item: ForwardRefExoticComponent;
};
export const CheckboxGroup: Props = ({
@@ -81,4 +79,4 @@ export const CheckboxGroup: Props = ({
);
};
-CheckboxGroup.Item = Checkbox as FC;
+CheckboxGroup.Item = Checkbox;
diff --git a/src/components/Counter/Counter.tsx b/src/components/Counter/Counter.tsx
index a5f0a7a5..2a8a1640 100644
--- a/src/components/Counter/Counter.tsx
+++ b/src/components/Counter/Counter.tsx
@@ -1,4 +1,4 @@
-import { FC, useMemo } from 'react';
+import { type FC, useMemo } from 'react';
import type { CounterProps } from './Counter.props';
import { stylesBuilder } from './stylesBuilder';
diff --git a/src/components/Divider/Divider.stories.tsx b/src/components/Divider/Divider.stories.tsx
index 251b228c..000c154b 100644
--- a/src/components/Divider/Divider.stories.tsx
+++ b/src/components/Divider/Divider.stories.tsx
@@ -9,6 +9,11 @@ const meta = {
title: 'Divider',
component: Divider,
tags: ['autodocs'],
+ render: (args) => (
+
+
+
+ ),
parameters: {
docs: {
description: {
diff --git a/src/components/Divider/Divider.tsx b/src/components/Divider/Divider.tsx
index f54af6d1..18ea0181 100644
--- a/src/components/Divider/Divider.tsx
+++ b/src/components/Divider/Divider.tsx
@@ -1,4 +1,4 @@
-import { FC, useMemo } from 'react';
+import { type FC, useMemo } from 'react';
import type { DividerProps } from './Divider.props';
import { stylesBuilder } from './stylesBuilder';
diff --git a/src/components/HelperText/HelperText.props.ts b/src/components/HelperText/HelperText.props.ts
index 4aa056e3..9dcbf219 100644
--- a/src/components/HelperText/HelperText.props.ts
+++ b/src/components/HelperText/HelperText.props.ts
@@ -7,7 +7,7 @@ export type HelperTextProps = {
current: number;
max: number;
};
- beforeIcon?: boolean;
+ hasBeforeIcon?: boolean;
text: string;
custom?: HelperTextConfig;
};
diff --git a/src/components/HelperText/HelperText.stories.tsx b/src/components/HelperText/HelperText.stories.tsx
index 996e1b70..877c6885 100644
--- a/src/components/HelperText/HelperText.stories.tsx
+++ b/src/components/HelperText/HelperText.stories.tsx
@@ -39,7 +39,7 @@ export const Default: Story = {};
export const DefaultWithIcon: Story = {
args: {
- beforeIcon: true,
+ hasBeforeIcon: true,
},
};
diff --git a/src/components/HelperText/HelperText.test.tsx b/src/components/HelperText/HelperText.test.tsx
index 7e1e278a..6f37dbae 100644
--- a/src/components/HelperText/HelperText.test.tsx
+++ b/src/components/HelperText/HelperText.test.tsx
@@ -14,7 +14,7 @@ const getHelperText = (jsx: JSX.Element) => {
};
describe('HelperText', () => {
- customPropTester(, {
+ customPropTester(, {
containerId: 'helper-text',
props: {
intent: ['none', 'success', 'alert'],
@@ -39,7 +39,7 @@ describe('HelperText', () => {
,
);
@@ -53,7 +53,7 @@ describe('HelperText', () => {
,
);
@@ -67,7 +67,7 @@ describe('HelperText', () => {
,
);
@@ -78,7 +78,7 @@ describe('HelperText', () => {
it('should render icon if passed as a prop', () => {
const { icon } = getHelperText(
- ,
+ ,
);
expect(icon).toBeInTheDocument();
});
diff --git a/src/components/HelperText/HelperText.tsx b/src/components/HelperText/HelperText.tsx
index aea9c916..09b20e61 100644
--- a/src/components/HelperText/HelperText.tsx
+++ b/src/components/HelperText/HelperText.tsx
@@ -10,7 +10,7 @@ import { MarginProps } from '@/types/MarginProps';
export const HelperText: FC = ({
intent = 'none',
- beforeIcon = false,
+ hasBeforeIcon = false,
counter,
text,
custom,
@@ -21,7 +21,7 @@ export const HelperText: FC = ({
return (
- {beforeIcon && (
+ {hasBeforeIcon && (
= ({
const iconName = useMemo(() => resolveIconName(intent), [intent]);
return (
-
+
= ({
intent = 'informative',
diff --git a/src/components/InlineSearchInput/InlineSearchInput.tsx b/src/components/InlineSearchInput/InlineSearchInput.tsx
index 42bdc85b..1cd61da8 100644
--- a/src/components/InlineSearchInput/InlineSearchInput.tsx
+++ b/src/components/InlineSearchInput/InlineSearchInput.tsx
@@ -1,11 +1,11 @@
-import { FC, useMemo } from 'react';
+import { type FC, useMemo } from 'react';
-import { InlineSearchInputProps } from './InlineSearchInput.props';
+import type { InlineSearchInputProps } from './InlineSearchInput.props';
import { defaultConfig } from './InlineSearchInput.styles';
import { SearchInput } from '../SearchInput';
import { mergeConfigWithCustom } from '@/services';
-import { MarginProps } from '@/types';
+import type { MarginProps } from '@/types';
export const InlineSearchInput: FC = ({
custom,
diff --git a/src/components/Label/Label.tsx b/src/components/Label/Label.tsx
index ff2fe2be..54d4af35 100644
--- a/src/components/Label/Label.tsx
+++ b/src/components/Label/Label.tsx
@@ -1,12 +1,12 @@
import { Icon } from '@virtuslab/tetrisly-icons';
-import { FC, useMemo } from 'react';
+import { type FC, useMemo } from 'react';
import type { LabelProps } from './Label.props';
import { stylesBuilder } from './stylesBuilder';
import { Button } from '../Button';
import { tet } from '@/tetrisly';
-import { MarginProps } from '@/types/MarginProps';
+import type { MarginProps } from '@/types/MarginProps';
export const Label: FC = ({
label,
diff --git a/src/components/Loader/Loader.tsx b/src/components/Loader/Loader.tsx
index 2f0fe253..063fe11b 100644
--- a/src/components/Loader/Loader.tsx
+++ b/src/components/Loader/Loader.tsx
@@ -1,13 +1,15 @@
-import { FC, useMemo } from 'react';
+import { type FC, useMemo } from 'react';
import { AnimatedProgress } from './AnimatedProgress';
-import { LoaderProps } from './Loader.props';
+import type { LoaderProps } from './Loader.props';
import { stylesBuilder } from './stylesBuilder';
import { tet } from '@/tetrisly';
-import { MarginProps } from '@/types';
+import type { MarginProps } from '@/types';
-export const Loader: FC = ({
+type NewType = FC;
+
+export const Loader: NewType = ({
appearance = 'primary',
progress,
shape,
diff --git a/src/components/Popover/Popover.styles.ts b/src/components/Popover/Popover.styles.ts
index 81c1ed7e..3e82b502 100644
--- a/src/components/Popover/Popover.styles.ts
+++ b/src/components/Popover/Popover.styles.ts
@@ -86,7 +86,7 @@ export const defaultConfig = {
text: '$typo-body-medium',
color: '$color-content-secondary',
padding: '$space-component-padding-large',
- ring: '$border-width-focus',
+ ring: '$border-width-small',
ringColor: '$color-border-defaultA',
boxShadow: '$elevation-bottom-300',
backgroundColor: '$color-interaction-background-modeless',
diff --git a/src/components/Popover/Popover.tsx b/src/components/Popover/Popover.tsx
index e9d53f13..089dea65 100644
--- a/src/components/Popover/Popover.tsx
+++ b/src/components/Popover/Popover.tsx
@@ -1,5 +1,5 @@
import { useSpace } from '@xstyled/styled-components';
-import { FC, PropsWithChildren, useMemo } from 'react';
+import { type PropsWithChildren, useMemo, type FC } from 'react';
import { AnchorWrapper, PopoverContent } from './AnchorWrapper.styled';
import type { PopoverProps } from './Popover.props';
diff --git a/src/components/RadioButton/RadioButton.stories.tsx b/src/components/RadioButton/RadioButton.stories.tsx
index 75679ecc..9ec25e45 100644
--- a/src/components/RadioButton/RadioButton.stories.tsx
+++ b/src/components/RadioButton/RadioButton.stories.tsx
@@ -32,6 +32,7 @@ export const Default: Story = {};
export const Checked: Story = {
args: {
isChecked: true,
+ onChange: () => {},
},
};
diff --git a/src/components/RadioButton/RadioButton.tsx b/src/components/RadioButton/RadioButton.tsx
index ebcc14ee..c3b33803 100644
--- a/src/components/RadioButton/RadioButton.tsx
+++ b/src/components/RadioButton/RadioButton.tsx
@@ -13,7 +13,7 @@ export const RadioButton = forwardRef<
RadioButtonProps & MarginProps
>(
(
- { isChecked, state, label, helperText, custom, ...restProps },
+ { isChecked, onChange, state, label, helperText, custom, ...restProps },
radioButtonRef,
) => {
const [radioButtonProps, containerProps] = extractInputProps(restProps);
@@ -22,12 +22,28 @@ export const RadioButton = forwardRef<
const radioButtonId = useId();
+ if (state === 'alert' && isChecked) {
+ console.warn('RadioButton: Checked alert state does not exist.');
+ }
+
+ if (
+ (isChecked !== undefined && onChange === undefined) ||
+ (isChecked === undefined && onChange !== undefined)
+ ) {
+ console.warn(
+ 'RadioButton: isChecked and onChange must be both defined or both undefined.',
+ );
+ }
+
+ const isAlert = state === 'alert' && !isChecked;
+
const input = (
diff --git a/src/components/RadioButtonGroup/RadioButtonGroup.tsx b/src/components/RadioButtonGroup/RadioButtonGroup.tsx
index 0210dbc0..523cc028 100644
--- a/src/components/RadioButtonGroup/RadioButtonGroup.tsx
+++ b/src/components/RadioButtonGroup/RadioButtonGroup.tsx
@@ -1,10 +1,10 @@
import {
Children,
cloneElement,
- FC,
+ type FC,
isValidElement,
- PropsWithChildren,
- ReactElement,
+ type PropsWithChildren,
+ type ReactElement,
useMemo,
} from 'react';
@@ -21,7 +21,7 @@ import { tet } from '@/tetrisly';
import type { MarginProps } from '@/types';
type Props = FC> & {
- Item: React.FC;
+ Item: FC;
};
export const RadioButtonGroup: Props = ({
diff --git a/src/components/SearchInput/SearchInput.tsx b/src/components/SearchInput/SearchInput.tsx
index 3c136fdb..63e51821 100644
--- a/src/components/SearchInput/SearchInput.tsx
+++ b/src/components/SearchInput/SearchInput.tsx
@@ -1,9 +1,9 @@
-import { FC } from 'react';
+import type { FC } from 'react';
-import { SearchInputProps } from './SearchInput.props';
-import { TextInput, TextInputProps } from '../TextInput';
+import type { SearchInputProps } from './SearchInput.props';
+import { TextInput, type TextInputProps } from '../TextInput';
-import { MarginProps } from '@/types';
+import type { MarginProps } from '@/types';
const SEARCH_ICON_COMPONENT: TextInputProps['beforeComponent'] = {
type: 'Icon',
diff --git a/src/components/Select/Select.test.tsx b/src/components/Select/Select.test.tsx
index 59d2bc62..135352d7 100644
--- a/src/components/Select/Select.test.tsx
+++ b/src/components/Select/Select.test.tsx
@@ -9,9 +9,9 @@ const getSelect = (jsx: JSX.Element) => {
const { getByTestId, queryByTestId } = render(jsx);
return {
- textInput: getByTestId('text-input'),
- input: getByTestId('text-input-input') as HTMLInputElement,
- beforeComponent: queryByTestId('text-input-before-component'),
+ textInput: getByTestId('select'),
+ input: getByTestId('select-input') as HTMLInputElement,
+ beforeComponent: queryByTestId('select-before-component'),
};
};
diff --git a/src/components/Select/Select.tsx b/src/components/Select/Select.tsx
index 395c12fb..0870600e 100644
--- a/src/components/Select/Select.tsx
+++ b/src/components/Select/Select.tsx
@@ -1,17 +1,91 @@
-import { FC } from 'react';
+import { Icon } from '@virtuslab/tetrisly-icons';
+import type { FC } from 'react';
-import { SelectProps } from './Select.props';
-import { TextInput, TextInputProps } from '../TextInput';
+import type { SelectProps } from './Select.props';
+import { Avatar } from '../Avatar';
+import { IconButton } from '../IconButton';
+import type { TextInputProps } from '../TextInput';
+import { useTextInput } from '../TextInput/useTextInput';
-import { MarginProps } from '@/types';
+import { tet } from '@/tetrisly';
+import type { MarginProps } from '@/types';
-const DROPDOWN_INDICATOR_COMPONENT: TextInputProps['afterComponent'] = {
+const DROPDOWN_INDICATOR_COMPONENT = {
type: 'IconButton',
props: {
icon: '20-chevron-down-small',
},
-};
+} satisfies TextInputProps['afterComponent'];
-export const Select: FC = (props) => (
-
-);
+export const Select: FC = ({
+ state,
+ beforeComponent,
+ hasClearButton,
+ value,
+ ...props
+}) => {
+ const afterComponent = DROPDOWN_INDICATOR_COMPONENT;
+ const {
+ containerRef,
+ handleContainerClick,
+ styles,
+ containerProps,
+ innerValue,
+ handleOnChange,
+ handleOnClear,
+ textInputProps,
+ } = useTextInput({
+ beforeComponent,
+ afterComponent,
+ ...props,
+ });
+ return (
+
+ {!!beforeComponent && (
+
+ {beforeComponent.type === 'Icon' && (
+
+
+
+ )}
+ {beforeComponent.type === 'Avatar' && (
+
+ )}
+
+ )}
+
+ {!!hasClearButton && (value || innerValue) && (
+
+ )}
+
+
+
+
+ );
+};
diff --git a/src/components/SocialButton/SocialButton.tsx b/src/components/SocialButton/SocialButton.tsx
index b320f981..9a627614 100644
--- a/src/components/SocialButton/SocialButton.tsx
+++ b/src/components/SocialButton/SocialButton.tsx
@@ -5,7 +5,7 @@ import { socials } from './socials';
import { stylesBuilder } from './stylesBuilder';
import { tet } from '@/tetrisly';
-import { MarginProps } from '@/types';
+import type { MarginProps } from '@/types';
export const SocialButton: FC = ({
platform,
diff --git a/src/components/SocialButton/socials/Apple.tsx b/src/components/SocialButton/socials/Apple.tsx
index 7a81222a..5d67f362 100644
--- a/src/components/SocialButton/socials/Apple.tsx
+++ b/src/components/SocialButton/socials/Apple.tsx
@@ -1,6 +1,6 @@
-import { FC } from 'react';
+import type { FC } from 'react';
-import { SocialProps } from './SocialProps';
+import type { SocialProps } from './SocialProps';
import { WithLoader } from './WithLoader';
import { tet } from '@/tetrisly';
diff --git a/src/components/SocialButton/socials/Facebook.tsx b/src/components/SocialButton/socials/Facebook.tsx
index feaa7a20..8e57632d 100644
--- a/src/components/SocialButton/socials/Facebook.tsx
+++ b/src/components/SocialButton/socials/Facebook.tsx
@@ -1,20 +1,20 @@
-import { FC } from 'react';
+import type { FC } from 'react';
-import { SocialProps } from './SocialProps';
+import type { SocialProps } from './SocialProps';
import { WithLoader } from './WithLoader';
export const Facebook: FC = ({ fill, loading }) => (
diff --git a/src/components/SocialButton/socials/Figma.tsx b/src/components/SocialButton/socials/Figma.tsx
index 687a1bf1..17dad1d2 100644
--- a/src/components/SocialButton/socials/Figma.tsx
+++ b/src/components/SocialButton/socials/Figma.tsx
@@ -1,40 +1,40 @@
-import { FC } from 'react';
+import type { FC } from 'react';
-import { SocialProps } from './SocialProps';
+import type { SocialProps } from './SocialProps';
import { WithLoader } from './WithLoader';
export const Figma: FC = ({ fill, loading }) => (