@alfalab/core-components-tab-bar 1.0.0
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/Component.d.ts +7 -0
- package/Component.js +39 -0
- package/components/tab/Component.d.ts +5 -0
- package/components/tab/Component.js +39 -0
- package/components/tab/index.css +71 -0
- package/components/tab/index.d.ts +1 -0
- package/components/tab/index.js +14 -0
- package/cssm/Component.d.ts +7 -0
- package/cssm/Component.js +39 -0
- package/cssm/components/tab/Component.d.ts +5 -0
- package/cssm/components/tab/Component.js +38 -0
- package/cssm/components/tab/index.d.ts +1 -0
- package/cssm/components/tab/index.js +15 -0
- package/cssm/components/tab/index.module.css +70 -0
- package/cssm/index.d.ts +2 -0
- package/cssm/index.js +18 -0
- package/cssm/index.module.css +29 -0
- package/cssm/types.d.ts +99 -0
- package/cssm/types.js +2 -0
- package/esm/Component.d.ts +7 -0
- package/esm/Component.js +30 -0
- package/esm/components/tab/Component.d.ts +5 -0
- package/esm/components/tab/Component.js +30 -0
- package/esm/components/tab/index.css +71 -0
- package/esm/components/tab/index.d.ts +1 -0
- package/esm/components/tab/index.js +6 -0
- package/esm/index.css +30 -0
- package/esm/index.d.ts +2 -0
- package/esm/index.js +8 -0
- package/esm/types.d.ts +99 -0
- package/esm/types.js +1 -0
- package/index.css +30 -0
- package/index.d.ts +2 -0
- package/index.js +16 -0
- package/modern/Component.d.ts +7 -0
- package/modern/Component.js +25 -0
- package/modern/components/tab/Component.d.ts +5 -0
- package/modern/components/tab/Component.js +27 -0
- package/modern/components/tab/index.css +71 -0
- package/modern/components/tab/index.d.ts +1 -0
- package/modern/components/tab/index.js +5 -0
- package/modern/index.css +30 -0
- package/modern/index.d.ts +2 -0
- package/modern/index.js +7 -0
- package/modern/types.d.ts +99 -0
- package/modern/types.js +1 -0
- package/package.json +24 -0
- package/src/Component.tsx +50 -0
- package/src/components/tab/Component.tsx +93 -0
- package/src/components/tab/index.module.css +45 -0
- package/src/components/tab/index.ts +1 -0
- package/src/index.module.css +16 -0
- package/src/index.ts +2 -0
- package/src/types.ts +139 -0
- package/types.d.ts +99 -0
- package/types.js +2 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React, { cloneElement, forwardRef, isValidElement, MouseEvent } from 'react';
|
|
2
|
+
import cn from 'classnames';
|
|
3
|
+
|
|
4
|
+
import { Badge } from '@alfalab/core-components-badge';
|
|
5
|
+
import { Typography } from '@alfalab/core-components-typography';
|
|
6
|
+
|
|
7
|
+
import { PrivateTabProps, TabProps } from '../../types';
|
|
8
|
+
|
|
9
|
+
import styles from './index.module.css';
|
|
10
|
+
|
|
11
|
+
const TabComponent = forwardRef(
|
|
12
|
+
(
|
|
13
|
+
{
|
|
14
|
+
showIndicator,
|
|
15
|
+
indicatorProps,
|
|
16
|
+
label,
|
|
17
|
+
icon,
|
|
18
|
+
id,
|
|
19
|
+
selected,
|
|
20
|
+
onChange,
|
|
21
|
+
onClick,
|
|
22
|
+
tabClassNames = {},
|
|
23
|
+
dataTestId,
|
|
24
|
+
className,
|
|
25
|
+
labelClassName,
|
|
26
|
+
selectedClassName,
|
|
27
|
+
iconClassName,
|
|
28
|
+
href,
|
|
29
|
+
Component = href ? 'a' : 'button',
|
|
30
|
+
...restProps
|
|
31
|
+
}: PrivateTabProps & TabProps,
|
|
32
|
+
ref,
|
|
33
|
+
) => {
|
|
34
|
+
const handleClick = (event: MouseEvent) => {
|
|
35
|
+
onChange?.(id);
|
|
36
|
+
onClick?.(event);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const {
|
|
40
|
+
className: commonClassName,
|
|
41
|
+
labelClassName: commonLabelClassName,
|
|
42
|
+
selectedClassName: commonSelectedClassName,
|
|
43
|
+
iconClassName: commonIconClassName,
|
|
44
|
+
} = tabClassNames;
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Component
|
|
48
|
+
data-test-id={dataTestId}
|
|
49
|
+
tabIndex={0}
|
|
50
|
+
{...(Component === 'button' ? { type: 'button' } : null)}
|
|
51
|
+
{...restProps}
|
|
52
|
+
href={href}
|
|
53
|
+
id={id}
|
|
54
|
+
ref={ref}
|
|
55
|
+
className={cn(
|
|
56
|
+
styles.component,
|
|
57
|
+
commonClassName,
|
|
58
|
+
className,
|
|
59
|
+
selected && commonSelectedClassName,
|
|
60
|
+
selected && selectedClassName,
|
|
61
|
+
{
|
|
62
|
+
[styles.selected]: selected,
|
|
63
|
+
},
|
|
64
|
+
)}
|
|
65
|
+
onClick={handleClick}
|
|
66
|
+
>
|
|
67
|
+
<div className={cn(styles.icon, commonIconClassName, iconClassName)}>
|
|
68
|
+
{isValidElement(icon) ? cloneElement(icon, { selected }) : icon}
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<Typography.Text
|
|
72
|
+
weight='medium'
|
|
73
|
+
view='secondary-small'
|
|
74
|
+
className={cn(styles.label, commonLabelClassName, labelClassName, {
|
|
75
|
+
[styles.labelSelected]: selected,
|
|
76
|
+
})}
|
|
77
|
+
>
|
|
78
|
+
{isValidElement(label) ? cloneElement(label, { selected }) : label}
|
|
79
|
+
</Typography.Text>
|
|
80
|
+
|
|
81
|
+
{showIndicator && (
|
|
82
|
+
<div className={styles.indicator}>
|
|
83
|
+
<Badge visibleIconOutline={true} {...indicatorProps} view='count' />
|
|
84
|
+
</div>
|
|
85
|
+
)}
|
|
86
|
+
</Component>
|
|
87
|
+
);
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
export const Tab = TabComponent as React.ForwardRefExoticComponent<
|
|
92
|
+
TabProps & React.RefAttributes<HTMLElement>
|
|
93
|
+
>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
@import '@alfalab/core-components-themes/src/default.css';
|
|
2
|
+
|
|
3
|
+
.component {
|
|
4
|
+
@mixin button-reset;
|
|
5
|
+
|
|
6
|
+
position: relative;
|
|
7
|
+
display: inline-flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
flex: 1 0 0;
|
|
10
|
+
align-items: center;
|
|
11
|
+
padding: var(--gap-xs) 0;
|
|
12
|
+
color: var(--color-light-neutral-translucent-700);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.selected {
|
|
16
|
+
color: var(--color-light-accent-primary);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.icon {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
flex-grow: 1;
|
|
24
|
+
width: 100%;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.label {
|
|
28
|
+
@mixin row_limit 1;
|
|
29
|
+
word-break: break-all;
|
|
30
|
+
flex-shrink: 0;
|
|
31
|
+
|
|
32
|
+
color: var(--color-light-text-secondary);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.labelSelected {
|
|
36
|
+
color: inherit;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.indicator {
|
|
40
|
+
position: absolute;
|
|
41
|
+
top: var(--gap-2xs);
|
|
42
|
+
left: calc(50% + var(--gap-2xs));
|
|
43
|
+
height: 16px;
|
|
44
|
+
min-width: 16px;
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Component';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
@import '@alfalab/core-components-themes/src/default.css';
|
|
2
|
+
|
|
3
|
+
.component {
|
|
4
|
+
display: flex;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
height: 64px;
|
|
7
|
+
max-height: 64px;
|
|
8
|
+
background-color: var(--color-light-base-bg-primary);
|
|
9
|
+
box-sizing: border-box;
|
|
10
|
+
overflow: hidden;
|
|
11
|
+
transition: box-shadow 0.2s ease;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.border {
|
|
15
|
+
box-shadow: 0 -1px 0 0 var(--color-light-neutral-300);
|
|
16
|
+
}
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AllHTMLAttributes,
|
|
3
|
+
ElementType,
|
|
4
|
+
ForwardRefExoticComponent,
|
|
5
|
+
HTMLAttributes,
|
|
6
|
+
ReactElement,
|
|
7
|
+
ReactNode,
|
|
8
|
+
RefAttributes,
|
|
9
|
+
} from 'react';
|
|
10
|
+
|
|
11
|
+
import type { BadgeProps } from '@alfalab/core-components-badge';
|
|
12
|
+
|
|
13
|
+
type TabElementType = ReactElement<
|
|
14
|
+
TabProps,
|
|
15
|
+
ForwardRefExoticComponent<TabProps & RefAttributes<HTMLElement>>
|
|
16
|
+
>;
|
|
17
|
+
|
|
18
|
+
export interface TabBarProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
|
|
19
|
+
/**
|
|
20
|
+
* Дополнительный класс
|
|
21
|
+
*/
|
|
22
|
+
className?: string;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Идентификатор для систем автоматизированного тестирования.
|
|
26
|
+
* Для таба используется модификатор -tab
|
|
27
|
+
*/
|
|
28
|
+
dataTestId?: string;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Дополнительные классы для таба.
|
|
32
|
+
*/
|
|
33
|
+
tabClassNames?: {
|
|
34
|
+
/**
|
|
35
|
+
* Дополнительный класс таба
|
|
36
|
+
*/
|
|
37
|
+
className?: string;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Дополнительный класс таба в выбранном состоянии
|
|
41
|
+
*/
|
|
42
|
+
selectedClassName?: string;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Дополнительный класс подписи
|
|
46
|
+
*/
|
|
47
|
+
labelClassName?: string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Дополнительный класс враппера иконки
|
|
51
|
+
*/
|
|
52
|
+
iconClassName?: string;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Список табов
|
|
57
|
+
*/
|
|
58
|
+
children: TabElementType[];
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Идентификатор выбранного таба
|
|
62
|
+
*/
|
|
63
|
+
selectedId?: string;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Включает верхний бордер
|
|
67
|
+
*/
|
|
68
|
+
border?: boolean;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Обработчик изменения выбранного таба
|
|
72
|
+
*/
|
|
73
|
+
onChange?: (id: string) => void;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
type AdditionalTabProps = Record<string, unknown>;
|
|
77
|
+
|
|
78
|
+
export interface TabProps
|
|
79
|
+
extends Omit<AllHTMLAttributes<unknown>, 'onChange' | 'label'>,
|
|
80
|
+
AdditionalTabProps {
|
|
81
|
+
/**
|
|
82
|
+
* Кастомный компонент таба.
|
|
83
|
+
* @default button
|
|
84
|
+
*/
|
|
85
|
+
Component?: ElementType;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Идентификатор таба
|
|
89
|
+
*/
|
|
90
|
+
id: string;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Лейбл
|
|
94
|
+
*/
|
|
95
|
+
label: ReactNode;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Иконка
|
|
99
|
+
*/
|
|
100
|
+
icon: ReactNode;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Показать индикатор
|
|
104
|
+
*/
|
|
105
|
+
showIndicator?: boolean;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Свойства индикатора
|
|
109
|
+
*/
|
|
110
|
+
indicatorProps?: Omit<
|
|
111
|
+
BadgeProps,
|
|
112
|
+
'view' | 'visibleColorOutline' | 'size' | 'iconColor' | 'iconUnderlayColor'
|
|
113
|
+
>;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Дополнительный класс таба
|
|
117
|
+
*/
|
|
118
|
+
className?: string;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Дополнительный класс таба в выбранном состоянии
|
|
122
|
+
*/
|
|
123
|
+
selectedClassName?: string;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Дополнительный класс подписи
|
|
127
|
+
*/
|
|
128
|
+
labelClassName?: string;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Дополнительный класс враппера иконки
|
|
132
|
+
*/
|
|
133
|
+
iconClassName?: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface PrivateTabProps
|
|
137
|
+
extends Pick<TabBarProps, 'tabClassNames' | 'onChange' | 'dataTestId'> {
|
|
138
|
+
selected: boolean;
|
|
139
|
+
}
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { AllHTMLAttributes, ElementType, ForwardRefExoticComponent, HTMLAttributes, ReactElement, ReactNode, RefAttributes } from 'react';
|
|
2
|
+
import { BadgeProps } from "@alfalab/core-components-badge";
|
|
3
|
+
type TabElementType = ReactElement<TabProps, ForwardRefExoticComponent<TabProps & RefAttributes<HTMLElement>>>;
|
|
4
|
+
interface TabBarProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
|
|
5
|
+
/**
|
|
6
|
+
* Дополнительный класс
|
|
7
|
+
*/
|
|
8
|
+
className?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Идентификатор для систем автоматизированного тестирования.
|
|
11
|
+
* Для таба используется модификатор -tab
|
|
12
|
+
*/
|
|
13
|
+
dataTestId?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Дополнительные классы для таба.
|
|
16
|
+
*/
|
|
17
|
+
tabClassNames?: {
|
|
18
|
+
/**
|
|
19
|
+
* Дополнительный класс таба
|
|
20
|
+
*/
|
|
21
|
+
className?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Дополнительный класс таба в выбранном состоянии
|
|
24
|
+
*/
|
|
25
|
+
selectedClassName?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Дополнительный класс подписи
|
|
28
|
+
*/
|
|
29
|
+
labelClassName?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Дополнительный класс враппера иконки
|
|
32
|
+
*/
|
|
33
|
+
iconClassName?: string;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Список табов
|
|
37
|
+
*/
|
|
38
|
+
children: TabElementType[];
|
|
39
|
+
/**
|
|
40
|
+
* Идентификатор выбранного таба
|
|
41
|
+
*/
|
|
42
|
+
selectedId?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Включает верхний бордер
|
|
45
|
+
*/
|
|
46
|
+
border?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Обработчик изменения выбранного таба
|
|
49
|
+
*/
|
|
50
|
+
onChange?: (id: string) => void;
|
|
51
|
+
}
|
|
52
|
+
type AdditionalTabProps = Record<string, unknown>;
|
|
53
|
+
interface TabProps extends Omit<AllHTMLAttributes<unknown>, 'onChange' | 'label'>, AdditionalTabProps {
|
|
54
|
+
/**
|
|
55
|
+
* Кастомный компонент таба.
|
|
56
|
+
* @default button
|
|
57
|
+
*/
|
|
58
|
+
Component?: ElementType;
|
|
59
|
+
/**
|
|
60
|
+
* Идентификатор таба
|
|
61
|
+
*/
|
|
62
|
+
id: string;
|
|
63
|
+
/**
|
|
64
|
+
* Лейбл
|
|
65
|
+
*/
|
|
66
|
+
label: ReactNode;
|
|
67
|
+
/**
|
|
68
|
+
* Иконка
|
|
69
|
+
*/
|
|
70
|
+
icon: ReactNode;
|
|
71
|
+
/**
|
|
72
|
+
* Показать индикатор
|
|
73
|
+
*/
|
|
74
|
+
showIndicator?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Свойства индикатора
|
|
77
|
+
*/
|
|
78
|
+
indicatorProps?: Omit<BadgeProps, 'view' | 'visibleColorOutline' | 'size' | 'iconColor' | 'iconUnderlayColor'>;
|
|
79
|
+
/**
|
|
80
|
+
* Дополнительный класс таба
|
|
81
|
+
*/
|
|
82
|
+
className?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Дополнительный класс таба в выбранном состоянии
|
|
85
|
+
*/
|
|
86
|
+
selectedClassName?: string;
|
|
87
|
+
/**
|
|
88
|
+
* Дополнительный класс подписи
|
|
89
|
+
*/
|
|
90
|
+
labelClassName?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Дополнительный класс враппера иконки
|
|
93
|
+
*/
|
|
94
|
+
iconClassName?: string;
|
|
95
|
+
}
|
|
96
|
+
interface PrivateTabProps extends Pick<TabBarProps, 'tabClassNames' | 'onChange' | 'dataTestId'> {
|
|
97
|
+
selected: boolean;
|
|
98
|
+
}
|
|
99
|
+
export { TabBarProps, TabProps, PrivateTabProps };
|
package/types.js
ADDED