Skip to content

Commit

Permalink
feat(plasma-b2c,star-ds): Add IconButton component
Browse files Browse the repository at this point in the history
  • Loading branch information
neretin-trike committed Nov 11, 2024
1 parent 22a801a commit 1c68669
Show file tree
Hide file tree
Showing 12 changed files with 366 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { TextField } from '../TextField';
import { BodyL } from '../Typography';
import { Cell } from '../Cell';
import { List } from '../List';
import { IconButton } from '../IconButton';

interface IconSvgProps {
size?: number;
Expand Down Expand Up @@ -49,6 +50,9 @@ const StoryDefault = () => {
return (
<View style={{ display: 'flex', gap: 10, padding: 50, width: '50%' }}>
<Button text="Button 2" contentLeft={<PlasmaIcon />} />
<IconButton>
<PlasmaIcon />
</IconButton>
<Progress value={50} />
<List
selectedItemIndex={selectedItemIndex}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Theme } from '@salutejs/core-components';

import { PlasmaB2CTheme } from '../ThemeProvider';

export const getConfig = ({ data, mode }: Theme<PlasmaB2CTheme>) => ({
defaults: {
view: 'default',
size: 'm',
},
variations: {
view: {
default: {
color: data.color[mode].textPrimary,
backgroundColor: data.color[mode].surfaceTransparentSecondary,
colorActive: data.color[mode].textPrimary,
backgroundColorActive: data.color[mode].surfaceTransparentSecondaryActive,
spinnerColor: data.color[mode].textPrimary,
contentIconColor: data.color[mode].textPrimary,
},
clear: {
color: data.color[mode].textPrimary,
backgroundColor: data.color[mode].surfaceClear,
colorActive: data.color[mode].textPrimaryActive,
backgroundColorActive: data.color[mode].surfaceClear,
spinnerColor: data.color[mode].textPrimary,
contentIconColor: data.color[mode].textPrimary,
},
},
size: {
l: {
height: 56,
width: 56,
padding: 16,
spinnerSize: 22,
radius: data.shape.round.m + 2, // TODO: Узнать почему нет этих значений в теме
},
m: {
height: 48,
width: 48,
padding: 12,
spinnerSize: 22,
radius: data.shape.round.m,
},
s: {
height: 40,
width: 40,
padding: 8,
spinnerSize: 22,
radius: data.shape.round.s + 2, // TODO: Узнать почему нет этих значений в теме
},
xs: {
height: 32,
width: 32,
padding: 4,
spinnerSize: 16,
radius: data.shape.round.s,
},
},
disabled: {
true: {
disabledOpacity: 0.4,
},
},
focused: {
true: {
color: data.color[mode].onLightTextPrimary,
backgroundColor: data.color[mode].onDarkSurfaceSolidDefault,
colorActive: data.color[mode].onLightTextPrimary,
backgroundColorActive: data.color[mode].onLightSurfaceTransparentSecondaryActive,
spinnerColor: data.color[mode].onLightTextPrimary,
contentIconColor: data.color[mode].onLightTextPrimary,
scale: 1.05,
},
},
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import type { ComponentProps } from 'react';
import Svg, { Path } from 'react-native-svg';
import type { StoryObj, Meta } from '@storybook/react';

import { IconButton } from './IconButton';

type StoryButtonProps = ComponentProps<typeof IconButton>;

const notes = `
| **Control** | **Description** | **Default** |
| ----------- | ------------------------------ | --------------- |
| view | Вид кнопки | 'default' |
| size | Размер кнопки | 'm' |
| pin | Скругление border-radius | 'square-square' |
| focused | Может ли фокусироваться кнопка | true |
| disabled | Кнопка неактивна | false |
| isLoading | Состояние загрузки | false |
`;

const meta: Meta<StoryButtonProps> = {
title: 'Components/IconButton',
component: IconButton,
parameters: {
notes,
},
args: {
view: 'default',
size: 'm',
pin: 'square-square',
disabled: false,
isLoading: false,
},
argTypes: {
pin: {
options: [
'square-square',
'square-clear',
'clear-square',
'clear-clear',
'clear-circle',
'circle-clear',
'circle-circle',
],
control: {
type: 'select',
},
},
size: {
options: ['xs', 's', 'm', 'l'],
control: {
type: 'select',
},
},
view: {
options: ['default', 'clear'],
control: {
type: 'select',
},
},
},
};

export default meta;

interface IconSvgProps {
size?: number;
color?: string;
}

// TODO: перенести для примеров в другое место
const PlasmaIcon: React.FC<IconSvgProps> = ({ size = 24, color }) => (
<Svg viewBox="0 0 24 24" fill="none" width={size} height={size} color={color}>
<Path
fillRule="evenodd"
clipRule="evenodd"
d="M12 3.5C7.30558 3.5 3.5 7.30558 3.5 12C3.5 14.0957 4.25846 16.0143 5.51587 17.4963C5.23619 16.745 5.08333 15.932 5.08333 15.0833C5.08333 11.2634 8.18003 8.16667 12 8.16667C15.82 8.16667 18.9167 11.2634 18.9167 15.0833C18.9167 15.932 18.7638 16.745 18.4841 17.4963C19.7415 16.0143 20.5 14.0957 20.5 12C20.5 7.30558 16.6944 3.5 12 3.5ZM15.7427 18.999C16.7742 18.0128 17.4167 16.6231 17.4167 15.0833C17.4167 12.0918 14.9915 9.66667 12 9.66667C9.00846 9.66667 6.58333 12.0918 6.58333 15.0833C6.58333 16.6231 7.2258 18.0128 8.25728 18.999C8.19795 18.731 8.16667 18.4525 8.16667 18.1667C8.16667 16.0496 9.88291 14.3333 12 14.3333C14.1171 14.3333 15.8333 16.0496 15.8333 18.1667C15.8333 18.4525 15.802 18.731 15.7427 18.999ZM12 20.5C13.2887 20.5 14.3333 19.4553 14.3333 18.1667C14.3333 16.878 13.2887 15.8333 12 15.8333C10.7113 15.8333 9.66667 16.878 9.66667 18.1667C9.66667 19.4553 10.7113 20.5 12 20.5ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"
fill="currentColor"
/>
</Svg>
);

const StoryDefault = (props: StoryButtonProps) => {
const onPress = () => {
alert('Произошёл onPress');
};

return (
<IconButton {...props} onPress={onPress}>
<PlasmaIcon />
</IconButton>
);
};

export const Default: StoryObj<StoryButtonProps> = {
render: (args) => <StoryDefault {...args} />,
};
5 changes: 5 additions & 0 deletions libraries/plasma-b2c/src/components/IconButton/IconButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { iconButtonComponent } from '@salutejs/core-components';

import { getConfig } from './IconButton.config';

export const IconButton = iconButtonComponent(getConfig);
1 change: 1 addition & 0 deletions libraries/plasma-b2c/src/components/IconButton/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { IconButton } from './IconButton';
1 change: 1 addition & 0 deletions libraries/plasma-b2c/src/index.prod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './components/Carousel';
export * from './components/Cell';
export * from './components/Checkbox';
export * from './components/List';
export * from './components/IconButton';
export * from './components/Skeleton';
export * from './components/Spinner';
export * from './components/Switch';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { TextField } from '../TextField';
import { BodyL } from '../Typography';
import { Cell } from '../Cell';
import { List } from '../List';
import { IconButton } from '../IconButton';

interface IconSvgProps {
size?: number;
Expand Down Expand Up @@ -49,6 +50,9 @@ const StoryDefault = () => {
return (
<View style={{ display: 'flex', gap: 10, padding: 50, width: '50%' }}>
<Button text="Button 2" contentLeft={<PlasmaIcon />} />
<IconButton>
<PlasmaIcon />
</IconButton>
<Progress value={50} />
<List
selectedItemIndex={selectedItemIndex}
Expand Down
76 changes: 76 additions & 0 deletions libraries/star-ds/src/components/IconButton/IconButton.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Theme } from '@salutejs/core-components';

import { StylesSaluteTheme } from '../ThemeProvider';

export const getConfig = ({ data, mode }: Theme<StylesSaluteTheme>) => ({
defaults: {
view: 'default',
size: 'm',
},
variations: {
view: {
default: {
color: data.color[mode].textPrimary,
backgroundColor: data.color[mode].surfaceTransparentSecondary,
colorActive: data.color[mode].textPrimary,
backgroundColorActive: data.color[mode].surfaceTransparentSecondaryActive,
spinnerColor: data.color[mode].textPrimary,
contentIconColor: data.color[mode].textPrimary,
},
clear: {
color: data.color[mode].textPrimary,
backgroundColor: data.color[mode].surfaceClear,
colorActive: data.color[mode].textPrimaryActive,
backgroundColorActive: data.color[mode].surfaceClear,
spinnerColor: data.color[mode].textPrimary,
contentIconColor: data.color[mode].textPrimary,
},
},
size: {
l: {
height: 56,
width: 56,
padding: 16,
spinnerSize: 22,
radius: data.shape.round.m + 2, // TODO: Узнать почему нет этих значений в теме
},
m: {
height: 48,
width: 48,
padding: 12,
spinnerSize: 22,
radius: data.shape.round.m,
},
s: {
height: 40,
width: 40,
padding: 8,
spinnerSize: 22,
radius: data.shape.round.s + 2, // TODO: Узнать почему нет этих значений в теме
},
xs: {
height: 32,
width: 32,
padding: 4,
spinnerSize: 16,
radius: data.shape.round.s,
},
},
disabled: {
true: {
disabledOpacity: 0.4,
},
},
focused: {
true: {
color: data.color[mode].onLightTextPrimary,
backgroundColor: data.color[mode].onDarkSurfaceSolidDefault,
colorActive: data.color[mode].onLightTextPrimary,
backgroundColorActive: data.color[mode].onLightSurfaceTransparentSecondaryActive,
spinnerColor: data.color[mode].onLightTextPrimary,
contentIconColor: data.color[mode].onLightTextPrimary,
scale: 1.05,
},
},
},
});
96 changes: 96 additions & 0 deletions libraries/star-ds/src/components/IconButton/IconButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import type { ComponentProps } from 'react';
import Svg, { Path } from 'react-native-svg';
import type { StoryObj, Meta } from '@storybook/react';

import { IconButton } from './IconButton';

type StoryButtonProps = ComponentProps<typeof IconButton>;

const notes = `
| **Control** | **Description** | **Default** |
| ----------- | ------------------------------ | --------------- |
| view | Вид кнопки | 'default' |
| size | Размер кнопки | 'm' |
| pin | Скругление border-radius | 'square-square' |
| focused | Может ли фокусироваться кнопка | true |
| disabled | Кнопка неактивна | false |
| isLoading | Состояние загрузки | false |
`;

const meta: Meta<StoryButtonProps> = {
title: 'Components/IconButton',
component: IconButton,
parameters: {
notes,
},
args: {
view: 'default',
size: 'm',
pin: 'square-square',
disabled: false,
isLoading: false,
},
argTypes: {
pin: {
options: [
'square-square',
'square-clear',
'clear-square',
'clear-clear',
'clear-circle',
'circle-clear',
'circle-circle',
],
control: {
type: 'select',
},
},
size: {
options: ['xs', 's', 'm', 'l'],
control: {
type: 'select',
},
},
view: {
options: ['default', 'clear'],
control: {
type: 'select',
},
},
},
};

export default meta;

interface IconSvgProps {
size?: number;
color?: string;
}

// TODO: перенести для примеров в другое место
const PlasmaIcon: React.FC<IconSvgProps> = ({ size = 24, color }) => (
<Svg viewBox="0 0 24 24" fill="none" width={size} height={size} color={color}>
<Path
fillRule="evenodd"
clipRule="evenodd"
d="M12 3.5C7.30558 3.5 3.5 7.30558 3.5 12C3.5 14.0957 4.25846 16.0143 5.51587 17.4963C5.23619 16.745 5.08333 15.932 5.08333 15.0833C5.08333 11.2634 8.18003 8.16667 12 8.16667C15.82 8.16667 18.9167 11.2634 18.9167 15.0833C18.9167 15.932 18.7638 16.745 18.4841 17.4963C19.7415 16.0143 20.5 14.0957 20.5 12C20.5 7.30558 16.6944 3.5 12 3.5ZM15.7427 18.999C16.7742 18.0128 17.4167 16.6231 17.4167 15.0833C17.4167 12.0918 14.9915 9.66667 12 9.66667C9.00846 9.66667 6.58333 12.0918 6.58333 15.0833C6.58333 16.6231 7.2258 18.0128 8.25728 18.999C8.19795 18.731 8.16667 18.4525 8.16667 18.1667C8.16667 16.0496 9.88291 14.3333 12 14.3333C14.1171 14.3333 15.8333 16.0496 15.8333 18.1667C15.8333 18.4525 15.802 18.731 15.7427 18.999ZM12 20.5C13.2887 20.5 14.3333 19.4553 14.3333 18.1667C14.3333 16.878 13.2887 15.8333 12 15.8333C10.7113 15.8333 9.66667 16.878 9.66667 18.1667C9.66667 19.4553 10.7113 20.5 12 20.5ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"
fill="currentColor"
/>
</Svg>
);

const StoryDefault = (props: StoryButtonProps) => {
const onPress = () => {
alert('Произошёл onPress');
};

return (
<IconButton {...props} onPress={onPress}>
<PlasmaIcon />
</IconButton>
);
};

export const Default: StoryObj<StoryButtonProps> = {
render: (args) => <StoryDefault {...args} />,
};
Loading

0 comments on commit 1c68669

Please sign in to comment.