@fibery/ui-kit 1.30.0 → 1.32.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/package.json +4 -7
- package/src/actions-menu/actions-menu-confirmation.tsx +3 -3
- package/src/actions-menu/actions-menu-sub-menu.tsx +5 -2
- package/src/actions-menu/actions-menu.tsx +6 -1
- package/src/actions-menu/contexts/actions-menu-context.tsx +11 -2
- package/src/button/actions-button-compact.tsx +2 -2
- package/src/button/actions-button.tsx +3 -19
- package/src/button/add-button.tsx +13 -6
- package/src/button/back-button.tsx +12 -23
- package/src/button/base-button.tsx +189 -0
- package/src/button/button.tsx +84 -235
- package/src/button/icon-button.tsx +53 -53
- package/src/button/make-button-colors.ts +33 -0
- package/src/design-system.ts +8 -7
- package/src/dropdown-menu/index.tsx +15 -14
- package/src/emoji-picker/emoji-picker-content-with-color.tsx +3 -10
- package/src/emoji-picker/emoji-picker-preview-footer.tsx +2 -2
- package/src/emoji-picker/icon-emoji-picker.tsx +3 -3
- package/src/emoji-picker/primitives/category-label.tsx +4 -4
- package/src/emoji-picker/primitives/grid-item.tsx +1 -4
- package/src/emoji-picker/primitives/search.tsx +7 -7
- package/src/emoji-picker/primitives/skin-tone.tsx +2 -2
- package/src/error-alert/error-alert-action.tsx +9 -6
- package/src/error-alert/error-alert.tsx +2 -2
- package/src/icons/Icon.tsx +1 -0
- package/src/icons/ast/Folder.ts +8 -0
- package/src/icons/ast/SmartFolder.ts +1 -1
- package/src/icons/ast/index.tsx +1 -0
- package/src/icons/react/Folder.tsx +13 -0
- package/src/icons/react/index.tsx +1 -0
- package/src/integration-compact-info-button.tsx +4 -3
- package/src/select/custom-select-partials/clear-indicator.tsx +5 -4
- package/src/select/select-in-popover.tsx +20 -6
- package/src/toast/primitives.tsx +2 -2
- package/src/toast/toast-action.tsx +3 -6
- package/src/toggle.tsx +22 -16
- package/src/back-button.tsx +0 -3
- package/src/button/button-base.tsx +0 -180
- package/src/button.tsx +0 -3
- package/src/icon-button.tsx +0 -3
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type {Category} from "@fibery/emoji-data";
|
|
2
2
|
|
|
3
3
|
import {css} from "@linaria/core";
|
|
4
|
-
import {space, textStyles, themeVars} from "../../design-system";
|
|
5
|
-
import {useEmojiPickerCtx, useEmojiPickerI18N} from "./root";
|
|
6
4
|
import {IconButton} from "../../button/icon-button";
|
|
5
|
+
import {space, textStyles, themeVars} from "../../design-system";
|
|
7
6
|
import Settings from "../../icons/react/Settings";
|
|
7
|
+
import {useEmojiPickerCtx, useEmojiPickerI18N} from "./root";
|
|
8
8
|
|
|
9
9
|
const categoryLabelCss = css`
|
|
10
10
|
${textStyles.heading6}
|
|
@@ -33,8 +33,8 @@ export const EmojiPickerCategoryLabel: React.FC<EmojiPickerCategoryLabelProps> =
|
|
|
33
33
|
<span>{label}</span>
|
|
34
34
|
|
|
35
35
|
{category.id === "custom" && emojiPickerCtx.onCustomCategorySettings && (
|
|
36
|
-
<IconButton onClick={emojiPickerCtx.onCustomCategorySettings}>
|
|
37
|
-
<Settings
|
|
36
|
+
<IconButton onClick={emojiPickerCtx.onCustomCategorySettings} size="small">
|
|
37
|
+
<Settings />
|
|
38
38
|
</IconButton>
|
|
39
39
|
)}
|
|
40
40
|
</div>
|
|
@@ -39,15 +39,12 @@ export const EmojiPickerGridItem = memo<EmojiPickerGridItemProps>(({id, category
|
|
|
39
39
|
width: emojiContentSettings.emojiContainerSize,
|
|
40
40
|
height: emojiContentSettings.emojiContainerSize,
|
|
41
41
|
}}
|
|
42
|
-
size="
|
|
42
|
+
size="large"
|
|
43
43
|
onClick={() => emojiPickerCtx.onEmojiSelect(emoji)}
|
|
44
44
|
onMouseEnter={() => setEmojiPreview({emoji, categoryId})}
|
|
45
45
|
onMouseLeave={() => setEmojiPreview(null)}
|
|
46
46
|
data-highlighted={highlighted}
|
|
47
47
|
className={css`
|
|
48
|
-
display: flex;
|
|
49
|
-
align-items: center;
|
|
50
|
-
justify-content: center;
|
|
51
48
|
&:hover:not(:disabled),
|
|
52
49
|
&:focus-visible,
|
|
53
50
|
&[data-highlighted="true"] {
|
|
@@ -7,11 +7,11 @@ import {border, space, textStyles, themeVars} from "../../design-system";
|
|
|
7
7
|
import Close from "../../icons/react/Close";
|
|
8
8
|
import Search from "../../icons/react/Search";
|
|
9
9
|
import {useEmojiDataStore} from "../stores/emoji-data-store";
|
|
10
|
+
import type {EmojiPickerGridHandle} from "./grid";
|
|
11
|
+
import {useEmojiPreview, useSetEmojiPreview} from "./preview-provider";
|
|
10
12
|
import {useEmojiPickerCtx, useEmojiPickerI18N} from "./root";
|
|
11
13
|
import {useFoundEmojis, useSetFoundEmojis} from "./search-provider";
|
|
12
14
|
import {useEmojiSkin} from "./skin-provider";
|
|
13
|
-
import {useEmojiPreview, useSetEmojiPreview} from "./preview-provider";
|
|
14
|
-
import type {EmojiPickerGridHandle} from "./grid";
|
|
15
15
|
|
|
16
16
|
const searchCss = css`
|
|
17
17
|
${textStyles.regular}
|
|
@@ -24,7 +24,7 @@ const searchCss = css`
|
|
|
24
24
|
|
|
25
25
|
display: flex;
|
|
26
26
|
align-items: center;
|
|
27
|
-
padding-left: ${space.
|
|
27
|
+
padding-left: ${space.s8}px;
|
|
28
28
|
gap: ${space.s2}px;
|
|
29
29
|
|
|
30
30
|
/* For screenreaders only, via https://stackoverflow.com/a/19758620 */
|
|
@@ -58,13 +58,13 @@ const searchInputCss = css`
|
|
|
58
58
|
`;
|
|
59
59
|
|
|
60
60
|
const searchIconCss = css`
|
|
61
|
-
padding: ${space.
|
|
61
|
+
padding: ${space.s4}px;
|
|
62
62
|
`;
|
|
63
63
|
|
|
64
64
|
const extraActionSlotCss = css`
|
|
65
65
|
background-color: var(--fibery-emoji-hover-color, ${themeVars.inputCopyBgColor});
|
|
66
|
-
border-
|
|
67
|
-
|
|
66
|
+
border-radius: ${space.s6}px;
|
|
67
|
+
margin-right: ${space.s4}px;
|
|
68
68
|
`;
|
|
69
69
|
|
|
70
70
|
export type EmojiPickerSearchProps = {
|
|
@@ -159,7 +159,7 @@ export const EmojiPickerSearch: React.FC<EmojiPickerSearchProps> = ({
|
|
|
159
159
|
<section className={cx(searchCss, className)} aria-label={i18n.search}>
|
|
160
160
|
{foundEmojis ? (
|
|
161
161
|
<IconButton size="small" onClick={clearSearch}>
|
|
162
|
-
<Close
|
|
162
|
+
<Close />
|
|
163
163
|
</IconButton>
|
|
164
164
|
) : (
|
|
165
165
|
<span className={searchIconCss}>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {EmojiSkin} from "@fibery/emoji-data";
|
|
2
2
|
import {css, cx} from "@linaria/core";
|
|
3
3
|
import {useState} from "react";
|
|
4
|
+
import {IconButton} from "../../button/icon-button";
|
|
4
5
|
import {textStyles, themeVars} from "../../design-system";
|
|
5
6
|
import {Emoji} from "./emoji";
|
|
6
7
|
import {useEmojiPickerCtx, useEmojiPickerI18N} from "./root";
|
|
7
8
|
import {useEmojiSkin, useSetEmojiSkin} from "./skin-provider";
|
|
8
|
-
import {IconButton} from "../../button/icon-button";
|
|
9
9
|
|
|
10
10
|
const skinToneWrapperCss = css`
|
|
11
11
|
display: flex;
|
|
@@ -75,7 +75,7 @@ export const EmojiPickerSkinTone: React.FC<EmojiPickerSkinToneProps> = ({classNa
|
|
|
75
75
|
skinToneNodes.push(
|
|
76
76
|
<span key={`skin-tone-${skinTone}`} className={cx(skinToneSwatchCss, (selected || opened) && expandedCss)}>
|
|
77
77
|
<IconButton
|
|
78
|
-
size="
|
|
78
|
+
size="large"
|
|
79
79
|
onClick={() => {
|
|
80
80
|
if (opened) {
|
|
81
81
|
setSkin(skinTone as EmojiSkin);
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {useTheme} from "../theme-provider";
|
|
1
|
+
import {ButtonProps, Button} from "../button/button";
|
|
3
2
|
|
|
4
|
-
export const ErrorAlertAction
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
export const ErrorAlertAction = ({
|
|
4
|
+
size = "small",
|
|
5
|
+
variant = "outline",
|
|
6
|
+
color = "neutral",
|
|
7
|
+
className,
|
|
8
|
+
...rest
|
|
9
|
+
}: ButtonProps) => {
|
|
10
|
+
return <Button size={size} variant={variant} color={color} className={className} {...rest} />;
|
|
8
11
|
};
|
|
9
12
|
export type ErrorAlertActionElement = React.ReactElement<typeof ErrorAlertAction>;
|
|
@@ -50,8 +50,8 @@ export const ErrorAlert: React.FC<ErrorAlertProps> = ({message, description, act
|
|
|
50
50
|
</div>
|
|
51
51
|
{action}
|
|
52
52
|
{onClose ? (
|
|
53
|
-
<IconButton onClick={onClose} aria-label="Hide error">
|
|
54
|
-
<CloseIcon
|
|
53
|
+
<IconButton size="small" onClick={onClose} aria-label="Hide error">
|
|
54
|
+
<CloseIcon />
|
|
55
55
|
</IconButton>
|
|
56
56
|
) : null}
|
|
57
57
|
</div>
|
package/src/icons/Icon.tsx
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
|
|
2
|
+
// This icon file is generated automatically.
|
|
3
|
+
|
|
4
|
+
import { IconDefinition } from '../types';
|
|
5
|
+
|
|
6
|
+
const Folder: IconDefinition = {"icon":{"type":"root","children":[{"type":"element","tagName":"svg","properties":{"viewBox":"0 0 20 20"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","clipRule":"evenodd","d":"M4.417 4.583A.917.917 0 0 0 3.5 5.5v9.167a.917.917 0 0 0 .917.917h11.149c.006-.001.03-.005.074-.015a2.051 2.051 0 0 0 .472-.173.565.565 0 0 0 .12-.081.917.917 0 0 0 .268-.648V8a.917.917 0 0 0-.917-.917H10a.75.75 0 0 1-.53-.22l-2.28-2.28H4.416Zm-1.71-.792a2.417 2.417 0 0 1 1.71-.708H7.5a.75.75 0 0 1 .53.22l2.28 2.28h5.273A2.417 2.417 0 0 1 18 8v6.667c0 .64-.255 1.255-.708 1.709-.274.273-.645.441-.912.537-.26.093-.572.17-.797.17H4.417A2.417 2.417 0 0 1 2 14.668V5.5c0-.64.255-1.255.708-1.709Z"},"children":[]}],"metadata":""}]},"name":"folder"};
|
|
7
|
+
|
|
8
|
+
export default Folder;
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
|
|
4
4
|
import { IconDefinition } from '../types';
|
|
5
5
|
|
|
6
|
-
const SmartFolder: IconDefinition = {"icon":{"type":"root","children":[{"type":"element","tagName":"svg","properties":{"viewBox":"0 0 20 20"},"children":[{"type":"element","tagName":"path","properties":{"d":"
|
|
6
|
+
const SmartFolder: IconDefinition = {"icon":{"type":"root","children":[{"type":"element","tagName":"svg","properties":{"viewBox":"0 0 20 20"},"children":[{"type":"element","tagName":"path","properties":{"d":"M10.586 9.219a.75.75 0 0 0-1.172-.937l-2 2.5A.75.75 0 0 0 8 12h2l-.586 1.282a.75.75 0 0 0 1.172.937l2-2.5A.75.75 0 0 0 12 10.5h-2l.586-1.281Z","fill":"#51616C","fillOpacity":0.9},"children":[]},{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","clipRule":"evenodd","d":"M2.708 3.791a2.417 2.417 0 0 1 1.709-.708H7.5a.75.75 0 0 1 .53.22l2.28 2.28h5.273A2.417 2.417 0 0 1 18 8v6.667c0 .64-.255 1.255-.708 1.709-.274.273-.645.441-.912.537-.26.093-.572.17-.797.17H4.417A2.417 2.417 0 0 1 2 14.668V5.5c0-.64.255-1.255.708-1.709Zm1.709.792A.917.917 0 0 0 3.5 5.5v9.167a.917.917 0 0 0 .917.917h11.151c.008-.002.032-.005.072-.015a2.051 2.051 0 0 0 .472-.173.565.565 0 0 0 .12-.081.917.917 0 0 0 .268-.648V8a.917.917 0 0 0-.917-.917H10a.75.75 0 0 1-.53-.22l-2.28-2.28H4.416Z"},"children":[]}],"metadata":""}]},"name":"smart-folder"};
|
|
7
7
|
|
|
8
8
|
export default SmartFolder;
|
package/src/icons/ast/index.tsx
CHANGED
|
@@ -93,6 +93,7 @@ export { default as FileUpload } from './FileUpload';
|
|
|
93
93
|
export { default as Filter } from './Filter';
|
|
94
94
|
export { default as FocusModeOff } from './FocusModeOff';
|
|
95
95
|
export { default as FocusMode } from './FocusMode';
|
|
96
|
+
export { default as Folder } from './Folder';
|
|
96
97
|
export { default as FormWithCover } from './FormWithCover';
|
|
97
98
|
export { default as FormWithoutCover } from './FormWithoutCover';
|
|
98
99
|
export { default as Github } from './Github';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// This icon file is generated automatically.
|
|
2
|
+
|
|
3
|
+
import {forwardRef} from 'react';
|
|
4
|
+
import FolderSvg from '../ast/Folder';
|
|
5
|
+
import { Icon } from '../Icon';
|
|
6
|
+
import { IconBaseProps } from '../types';
|
|
7
|
+
|
|
8
|
+
const Folder = forwardRef<SVGSVGElement, IconBaseProps>(function Folder(
|
|
9
|
+
props: IconBaseProps,
|
|
10
|
+
ref: React.Ref<SVGSVGElement>
|
|
11
|
+
) {return <Icon {...props} className={props.className} ref={ref} icon={FolderSvg} />});
|
|
12
|
+
|
|
13
|
+
export default Folder;
|
|
@@ -93,6 +93,7 @@ export { default as FileUpload } from './FileUpload';
|
|
|
93
93
|
export { default as Filter } from './Filter';
|
|
94
94
|
export { default as FocusModeOff } from './FocusModeOff';
|
|
95
95
|
export { default as FocusMode } from './FocusMode';
|
|
96
|
+
export { default as Folder } from './Folder';
|
|
96
97
|
export { default as FormWithCover } from './FormWithCover';
|
|
97
98
|
export { default as FormWithoutCover } from './FormWithoutCover';
|
|
98
99
|
export { default as Github } from './Github';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {css, cx} from "@linaria/core";
|
|
2
|
-
import {ButtonBase} from "./button/button-base";
|
|
3
2
|
import {Tooltip} from "./tooltip";
|
|
4
3
|
import {space, textStyles, themeVars} from "./design-system";
|
|
5
4
|
import {useTheme} from "./theme-provider";
|
|
6
5
|
import WarningIcon from "./icons/react/WarningTriangle";
|
|
7
6
|
import {Spinner} from "./loaders";
|
|
7
|
+
import {BaseButton} from "./button/base-button";
|
|
8
8
|
|
|
9
9
|
const buttonCss = css`
|
|
10
10
|
${textStyles.heading5}
|
|
@@ -12,6 +12,7 @@ const buttonCss = css`
|
|
|
12
12
|
align-items: center;
|
|
13
13
|
padding: ${space.s2}px ${space.s8}px ${space.s2}px ${space.s4}px;
|
|
14
14
|
gap: ${space.s4}px;
|
|
15
|
+
border-radius: 6px;
|
|
15
16
|
`;
|
|
16
17
|
|
|
17
18
|
const loadingCss = css`
|
|
@@ -39,10 +40,10 @@ export const IntegrationCompactInfoButton: React.FC<{
|
|
|
39
40
|
const className = cx(buttonCss, loading && loadingCss);
|
|
40
41
|
|
|
41
42
|
const button = onClick ? (
|
|
42
|
-
<
|
|
43
|
+
<BaseButton color={error ? "error" : "neutral"} variant="ghost" className={className} onClick={onClick}>
|
|
43
44
|
{iconNode}
|
|
44
45
|
{name}
|
|
45
|
-
</
|
|
46
|
+
</BaseButton>
|
|
46
47
|
) : (
|
|
47
48
|
<div className={className}>
|
|
48
49
|
{iconNode}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import RemoveIcon from "../../icons/react/Remove";
|
|
3
1
|
import {ClearIndicatorProps, GroupBase, MultiValueRemoveProps} from "react-select";
|
|
4
|
-
import {
|
|
2
|
+
import {IconButton} from "../../button/icon-button";
|
|
3
|
+
import RemoveIcon from "../../icons/react/Remove";
|
|
5
4
|
|
|
6
5
|
export function ClearIndicator<
|
|
7
6
|
TOption,
|
|
@@ -16,7 +15,9 @@ export function ClearIndicator<
|
|
|
16
15
|
}
|
|
17
16
|
return (
|
|
18
17
|
<div {...innerProps}>
|
|
19
|
-
<
|
|
18
|
+
<IconButton disabled={selectProps.isDisabled} size={"small"}>
|
|
19
|
+
<RemoveIcon />
|
|
20
|
+
</IconButton>
|
|
20
21
|
</div>
|
|
21
22
|
);
|
|
22
23
|
}
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
} from "./index";
|
|
29
29
|
import {SelectControlSettingsProvider} from "./select-control-settings-context";
|
|
30
30
|
import {Menu} from "./custom-select-partials/menu";
|
|
31
|
+
import {useIsPhone} from "../use-is-phone";
|
|
31
32
|
|
|
32
33
|
const offset = [0, space.s4] as [number, number];
|
|
33
34
|
const popupHeightVH = 45;
|
|
@@ -56,6 +57,11 @@ const popupClassName = css`
|
|
|
56
57
|
padding-left: ${space.s8}px;
|
|
57
58
|
padding-right: ${space.s8}px;
|
|
58
59
|
`;
|
|
60
|
+
const mobileClassName = css`
|
|
61
|
+
padding-top: ${space.s12}px;
|
|
62
|
+
padding-left: ${space.s12}px;
|
|
63
|
+
padding-right: ${space.s12}px;
|
|
64
|
+
`;
|
|
59
65
|
|
|
60
66
|
const valueClassName = css`
|
|
61
67
|
border-radius: ${border.radius4}px;
|
|
@@ -301,11 +307,13 @@ function SelectInPopoverInner<Option, IsMulti extends boolean, Group extends Gro
|
|
|
301
307
|
);
|
|
302
308
|
const paddingPopup = popupPaddingTop + popupPaddingBottom;
|
|
303
309
|
const paddingMenu = 6 + 6 + 6;
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
310
|
+
const isPhone = useIsPhone();
|
|
311
|
+
const maxMenuHeight = isPhone
|
|
312
|
+
? document.body.clientHeight - 45 - valueMaxHeight
|
|
313
|
+
: Math.max((document.body.clientHeight / 100) * popupHeightVH, popupMinHeightPx) -
|
|
314
|
+
valueMaxHeight -
|
|
315
|
+
paddingPopup -
|
|
316
|
+
paddingMenu;
|
|
309
317
|
const mergedComponents = {...defaultComponents, ...components};
|
|
310
318
|
|
|
311
319
|
return (
|
|
@@ -320,9 +328,12 @@ function SelectInPopoverInner<Option, IsMulti extends boolean, Group extends Gro
|
|
|
320
328
|
</mergedComponents.Trigger>
|
|
321
329
|
{Boolean(triggerElement) && (
|
|
322
330
|
<Popup
|
|
331
|
+
supportMobile
|
|
332
|
+
title={title}
|
|
323
333
|
offset={offset}
|
|
324
334
|
popupContainerClassName={popupContainerClassName}
|
|
325
335
|
popupClassName={cx(popupClassName, popupStyles)}
|
|
336
|
+
mobilePopupContentClassName={mobileClassName}
|
|
326
337
|
placement="bottom-start"
|
|
327
338
|
renderInPortal={renderInPortal}
|
|
328
339
|
open={visible}
|
|
@@ -332,7 +343,7 @@ function SelectInPopoverInner<Option, IsMulti extends boolean, Group extends Gro
|
|
|
332
343
|
triggerDomElement={triggerElement}
|
|
333
344
|
getPopupContainer={getPopupContainer}
|
|
334
345
|
>
|
|
335
|
-
{title && <div className={titleClassName}>{title}</div>}
|
|
346
|
+
{title && !isPhone && <div className={titleClassName}>{title}</div>}
|
|
336
347
|
{/*Usually we set popupContainerElement for react-select via context (SelectControlSettingsProvider). But here we render react-select in popover.*/}
|
|
337
348
|
{/*Render target in controlled by Popover here. So we just override SelectControlContext here and set popupContainerElement to undefined. */}
|
|
338
349
|
{/*So in dom react-select will be a child of popover. */}
|
|
@@ -350,6 +361,9 @@ function SelectInPopoverInner<Option, IsMulti extends boolean, Group extends Gro
|
|
|
350
361
|
}}
|
|
351
362
|
autoFocus={autoFocus}
|
|
352
363
|
onBlur={() => {
|
|
364
|
+
if (isPhone) {
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
353
367
|
blurTimeoutRef.current = setTimeout(() => {
|
|
354
368
|
onHide(false);
|
|
355
369
|
}, 250);
|
package/src/toast/primitives.tsx
CHANGED
|
@@ -150,8 +150,8 @@ export const ToastSubtitle = forwardRef<
|
|
|
150
150
|
export const ToastClose = () => {
|
|
151
151
|
return (
|
|
152
152
|
<ToastPrimitives.Close aria-label="Dismiss" asChild>
|
|
153
|
-
<IconButton>
|
|
154
|
-
<CloseIcon
|
|
153
|
+
<IconButton size="small">
|
|
154
|
+
<CloseIcon />
|
|
155
155
|
</IconButton>
|
|
156
156
|
</ToastPrimitives.Close>
|
|
157
157
|
);
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
+
import {css} from "@linaria/core";
|
|
1
2
|
import {Action as RadixToastAction, type ToastActionProps} from "@radix-ui/react-toast";
|
|
2
3
|
import {ElementRef, forwardRef} from "react";
|
|
3
|
-
import {ButtonProps} from "../button/button";
|
|
4
|
-
import {Button} from "../button";
|
|
5
|
-
import {useTheme} from "../theme-provider";
|
|
6
|
-
import {css} from "@linaria/core";
|
|
4
|
+
import {ButtonProps, Button} from "../button/button";
|
|
7
5
|
import {space} from "../design-system";
|
|
8
6
|
|
|
9
7
|
const toastActionCss = css`
|
|
@@ -16,10 +14,9 @@ export const ToastAction = forwardRef<
|
|
|
16
14
|
ElementRef<typeof RadixToastAction>,
|
|
17
15
|
ButtonProps & {altText: ToastActionProps["altText"]}
|
|
18
16
|
>(({children, altText, ...props}, ref) => {
|
|
19
|
-
const theme = useTheme();
|
|
20
17
|
return (
|
|
21
18
|
<RadixToastAction className={toastActionCss} ref={ref} altText={altText} asChild>
|
|
22
|
-
<Button color=
|
|
19
|
+
<Button variant="outline" color="neutral" {...props}>
|
|
23
20
|
{children}
|
|
24
21
|
</Button>
|
|
25
22
|
</RadixToastAction>
|
package/src/toggle.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import chroma from "chroma-js";
|
|
|
4
4
|
import {ComponentProps, FC, ReactNode} from "react";
|
|
5
5
|
import {layout, space, textStyles, transition} from "./design-system";
|
|
6
6
|
import _ from "lodash";
|
|
7
|
+
import SpinnerIcon from "./icons/react/Spinner";
|
|
7
8
|
|
|
8
9
|
const Input = styled.input<{containerSize: number; containerWidth: number; outlineColor: string}>`
|
|
9
10
|
position: absolute;
|
|
@@ -85,12 +86,14 @@ interface ToggleProps extends Omit<ComponentProps<"input">, "value"> {
|
|
|
85
86
|
backgroundColor: string;
|
|
86
87
|
labelPosition?: "first" | "last";
|
|
87
88
|
wrapperClassName?: string;
|
|
89
|
+
pending?: boolean;
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
export const Toggle: FC<ToggleProps> = ({
|
|
91
93
|
value,
|
|
92
94
|
label,
|
|
93
95
|
labelTitle,
|
|
96
|
+
pending,
|
|
94
97
|
disabled = false,
|
|
95
98
|
backgroundColor,
|
|
96
99
|
size = 16,
|
|
@@ -130,25 +133,28 @@ export const Toggle: FC<ToggleProps> = ({
|
|
|
130
133
|
)}
|
|
131
134
|
title={labelTitle}
|
|
132
135
|
>
|
|
133
|
-
<
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
backgroundColor={backgroundColor}
|
|
137
|
-
disabled={disabled}
|
|
138
|
-
>
|
|
139
|
-
<Circle containerSize={size} style={circleTransformStyle} />
|
|
140
|
-
<Input
|
|
136
|
+
{pending && <SpinnerIcon />}
|
|
137
|
+
{!pending && (
|
|
138
|
+
<CircleContainer
|
|
141
139
|
containerSize={size}
|
|
142
140
|
containerWidth={width}
|
|
143
|
-
|
|
144
|
-
onChange={onChange}
|
|
145
|
-
className={className}
|
|
146
|
-
type="checkbox"
|
|
141
|
+
backgroundColor={backgroundColor}
|
|
147
142
|
disabled={disabled}
|
|
148
|
-
|
|
149
|
-
{
|
|
150
|
-
|
|
151
|
-
|
|
143
|
+
>
|
|
144
|
+
<Circle containerSize={size} style={circleTransformStyle} />
|
|
145
|
+
<Input
|
|
146
|
+
containerSize={size}
|
|
147
|
+
containerWidth={width}
|
|
148
|
+
outlineColor={outlineColor}
|
|
149
|
+
onChange={onChange}
|
|
150
|
+
className={className}
|
|
151
|
+
type="checkbox"
|
|
152
|
+
disabled={disabled}
|
|
153
|
+
checked={value}
|
|
154
|
+
{...rest}
|
|
155
|
+
/>
|
|
156
|
+
</CircleContainer>
|
|
157
|
+
)}
|
|
152
158
|
|
|
153
159
|
{label && (
|
|
154
160
|
<Label disabled={disabled && labelMutedWhenDisabled} labelPosition={labelPosition}>
|
package/src/back-button.tsx
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import {styled} from "@linaria/react";
|
|
2
|
-
import {ComponentPropsWithoutRef, forwardRef} from "react";
|
|
3
|
-
import {border, colors, fontWeight, getDarkenColor, getOpacities, opacity, ThemeColors} from "../design-system";
|
|
4
|
-
import {useTheme} from "../theme-provider";
|
|
5
|
-
|
|
6
|
-
export const getMainColor = ({color, dangerous, theme}: {color?: string; dangerous?: boolean; theme: ThemeColors}) => {
|
|
7
|
-
if (color) {
|
|
8
|
-
return color;
|
|
9
|
-
}
|
|
10
|
-
if (dangerous) {
|
|
11
|
-
return theme.danger;
|
|
12
|
-
}
|
|
13
|
-
if (!theme) {
|
|
14
|
-
return colors.primary;
|
|
15
|
-
}
|
|
16
|
-
return theme.buttonColor;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const getBorderColor = ({
|
|
20
|
-
mainColor,
|
|
21
|
-
borderless,
|
|
22
|
-
primary,
|
|
23
|
-
}: {
|
|
24
|
-
mainColor: string;
|
|
25
|
-
borderless?: boolean;
|
|
26
|
-
primary?: boolean;
|
|
27
|
-
}) => {
|
|
28
|
-
if (borderless) {
|
|
29
|
-
return colors.transparent;
|
|
30
|
-
}
|
|
31
|
-
if (primary) {
|
|
32
|
-
return mainColor;
|
|
33
|
-
}
|
|
34
|
-
return getOpacities(mainColor).opacity30;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const getHoverBorderColor = ({
|
|
38
|
-
mainColor,
|
|
39
|
-
borderless,
|
|
40
|
-
primary,
|
|
41
|
-
hoverBgColor,
|
|
42
|
-
}: {
|
|
43
|
-
mainColor: string;
|
|
44
|
-
borderless?: boolean;
|
|
45
|
-
primary?: boolean;
|
|
46
|
-
hoverBgColor: string;
|
|
47
|
-
}) => {
|
|
48
|
-
if (borderless) {
|
|
49
|
-
return colors.transparent;
|
|
50
|
-
}
|
|
51
|
-
if (primary) {
|
|
52
|
-
return hoverBgColor;
|
|
53
|
-
}
|
|
54
|
-
return mainColor;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export const getTextColor = ({
|
|
58
|
-
mainColor,
|
|
59
|
-
primary,
|
|
60
|
-
theme,
|
|
61
|
-
}: {
|
|
62
|
-
mainColor: string;
|
|
63
|
-
primary?: boolean;
|
|
64
|
-
theme: ThemeColors;
|
|
65
|
-
}) => {
|
|
66
|
-
if (primary) {
|
|
67
|
-
return theme.buttonPrimaryTextColor;
|
|
68
|
-
}
|
|
69
|
-
return mainColor;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const getBgColor = ({mainColor, primary}: {mainColor: string; primary?: boolean}) => {
|
|
73
|
-
if (primary) {
|
|
74
|
-
return mainColor;
|
|
75
|
-
}
|
|
76
|
-
return colors.transparent;
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
const getHoverBgColor = ({
|
|
80
|
-
mainColor,
|
|
81
|
-
borderless,
|
|
82
|
-
primary,
|
|
83
|
-
}: {
|
|
84
|
-
mainColor: string;
|
|
85
|
-
primary?: boolean;
|
|
86
|
-
borderless?: boolean;
|
|
87
|
-
}) => {
|
|
88
|
-
if (primary) {
|
|
89
|
-
return getDarkenColor(mainColor);
|
|
90
|
-
}
|
|
91
|
-
if (borderless) {
|
|
92
|
-
return getOpacities(mainColor).opacity15;
|
|
93
|
-
}
|
|
94
|
-
return colors.transparent;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
export const buttonBorderWidth = 1;
|
|
98
|
-
|
|
99
|
-
type StyledProps = {
|
|
100
|
-
textColor: string;
|
|
101
|
-
bgColor: string;
|
|
102
|
-
borderColor: string;
|
|
103
|
-
hoverBgColor: string;
|
|
104
|
-
hoverBorderColor: string;
|
|
105
|
-
borderWidth: number;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
export const StyledButtonBase = styled.button<StyledProps>`
|
|
109
|
-
display: block;
|
|
110
|
-
box-sizing: border-box;
|
|
111
|
-
font-weight: ${fontWeight.medium};
|
|
112
|
-
margin: 0;
|
|
113
|
-
border-radius: ${border.radius6}px;
|
|
114
|
-
border: 0;
|
|
115
|
-
border-width: ${({borderWidth}) => `${borderWidth}px`};
|
|
116
|
-
border-style: solid;
|
|
117
|
-
padding: 0;
|
|
118
|
-
cursor: pointer;
|
|
119
|
-
transition: all 150ms ease-out;
|
|
120
|
-
color: ${({textColor}) => textColor};
|
|
121
|
-
background-color: ${({bgColor}) => bgColor};
|
|
122
|
-
border-color: ${({borderColor}) => borderColor};
|
|
123
|
-
|
|
124
|
-
&:disabled {
|
|
125
|
-
cursor: default;
|
|
126
|
-
opacity: ${opacity.opacity40};
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
&:focus {
|
|
130
|
-
outline: none;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
&:focus-visible {
|
|
134
|
-
box-shadow: ${({borderColor}) => `0 0 0 3px ${getOpacities(borderColor).opacity25}`};
|
|
135
|
-
background-color: ${({hoverBgColor}) => hoverBgColor};
|
|
136
|
-
border-color: ${({hoverBorderColor}) => hoverBorderColor};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
&:hover:not(:disabled) {
|
|
140
|
-
background-color: ${({hoverBgColor}) => hoverBgColor};
|
|
141
|
-
border-color: ${({hoverBorderColor}) => hoverBorderColor};
|
|
142
|
-
}
|
|
143
|
-
`;
|
|
144
|
-
|
|
145
|
-
export type ButtonBaseProps = {
|
|
146
|
-
color?: string;
|
|
147
|
-
primary?: boolean;
|
|
148
|
-
dangerous?: boolean;
|
|
149
|
-
borderless?: boolean;
|
|
150
|
-
} & ComponentPropsWithoutRef<"button">;
|
|
151
|
-
export const ButtonBase = forwardRef<HTMLButtonElement, ButtonBaseProps>(function ButtonBase(
|
|
152
|
-
{primary, color, borderless, dangerous, className, type = "button", ...buttonProps},
|
|
153
|
-
ref
|
|
154
|
-
) {
|
|
155
|
-
const theme = useTheme();
|
|
156
|
-
|
|
157
|
-
const mainColor = getMainColor({color, dangerous, theme});
|
|
158
|
-
const textColor = getTextColor({mainColor, primary, theme});
|
|
159
|
-
const bgColor = getBgColor({mainColor, primary});
|
|
160
|
-
const hoverBgColor = getHoverBgColor({mainColor, borderless, primary});
|
|
161
|
-
const borderColor = getBorderColor({mainColor, borderless, primary});
|
|
162
|
-
const hoverBorderColor = getHoverBorderColor({
|
|
163
|
-
mainColor,
|
|
164
|
-
borderless,
|
|
165
|
-
primary,
|
|
166
|
-
hoverBgColor,
|
|
167
|
-
});
|
|
168
|
-
const borderWidth = borderless ? 0 : buttonBorderWidth;
|
|
169
|
-
|
|
170
|
-
const styledProps: StyledProps = {
|
|
171
|
-
bgColor,
|
|
172
|
-
borderColor,
|
|
173
|
-
hoverBgColor,
|
|
174
|
-
hoverBorderColor,
|
|
175
|
-
textColor,
|
|
176
|
-
borderWidth,
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
return <StyledButtonBase ref={ref} type={type} className={className} {...styledProps} {...buttonProps} />;
|
|
180
|
-
});
|
package/src/button.tsx
DELETED
package/src/icon-button.tsx
DELETED