@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.
Files changed (40) hide show
  1. package/package.json +4 -7
  2. package/src/actions-menu/actions-menu-confirmation.tsx +3 -3
  3. package/src/actions-menu/actions-menu-sub-menu.tsx +5 -2
  4. package/src/actions-menu/actions-menu.tsx +6 -1
  5. package/src/actions-menu/contexts/actions-menu-context.tsx +11 -2
  6. package/src/button/actions-button-compact.tsx +2 -2
  7. package/src/button/actions-button.tsx +3 -19
  8. package/src/button/add-button.tsx +13 -6
  9. package/src/button/back-button.tsx +12 -23
  10. package/src/button/base-button.tsx +189 -0
  11. package/src/button/button.tsx +84 -235
  12. package/src/button/icon-button.tsx +53 -53
  13. package/src/button/make-button-colors.ts +33 -0
  14. package/src/design-system.ts +8 -7
  15. package/src/dropdown-menu/index.tsx +15 -14
  16. package/src/emoji-picker/emoji-picker-content-with-color.tsx +3 -10
  17. package/src/emoji-picker/emoji-picker-preview-footer.tsx +2 -2
  18. package/src/emoji-picker/icon-emoji-picker.tsx +3 -3
  19. package/src/emoji-picker/primitives/category-label.tsx +4 -4
  20. package/src/emoji-picker/primitives/grid-item.tsx +1 -4
  21. package/src/emoji-picker/primitives/search.tsx +7 -7
  22. package/src/emoji-picker/primitives/skin-tone.tsx +2 -2
  23. package/src/error-alert/error-alert-action.tsx +9 -6
  24. package/src/error-alert/error-alert.tsx +2 -2
  25. package/src/icons/Icon.tsx +1 -0
  26. package/src/icons/ast/Folder.ts +8 -0
  27. package/src/icons/ast/SmartFolder.ts +1 -1
  28. package/src/icons/ast/index.tsx +1 -0
  29. package/src/icons/react/Folder.tsx +13 -0
  30. package/src/icons/react/index.tsx +1 -0
  31. package/src/integration-compact-info-button.tsx +4 -3
  32. package/src/select/custom-select-partials/clear-indicator.tsx +5 -4
  33. package/src/select/select-in-popover.tsx +20 -6
  34. package/src/toast/primitives.tsx +2 -2
  35. package/src/toast/toast-action.tsx +3 -6
  36. package/src/toggle.tsx +22 -16
  37. package/src/back-button.tsx +0 -3
  38. package/src/button/button-base.tsx +0 -180
  39. package/src/button.tsx +0 -3
  40. 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 iconSize={16} />
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="big"
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.s12}px;
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.s2}px;
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-top-right-radius: ${space.s6}px;
67
- border-bottom-right-radius: ${space.s6}px;
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 iconSize={16} />
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="big"
78
+ size="large"
79
79
  onClick={() => {
80
80
  if (opened) {
81
81
  setSkin(skinTone as EmojiSkin);
@@ -1,9 +1,12 @@
1
- import {Button, ButtonProps} from "../button/button";
2
- import {useTheme} from "../theme-provider";
1
+ import {ButtonProps, Button} from "../button/button";
3
2
 
4
- export const ErrorAlertAction: React.FC<ButtonProps> = (props) => {
5
- const theme = useTheme();
6
-
7
- return <Button size=":button-size/small" color={theme.textColor} {...props} />;
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 iconSize={16} />
53
+ <IconButton size="small" onClick={onClose} aria-label="Hide error">
54
+ <CloseIcon />
55
55
  </IconButton>
56
56
  ) : null}
57
57
  </div>
@@ -13,6 +13,7 @@ const size = `var(${iconSizeVar}, ${defaultIconSize}px)`;
13
13
  const containerSize = `var(${iconContainerSizeVar}, ${size})`;
14
14
 
15
15
  export const iconContainer = css`
16
+ flex-shrink: 0;
16
17
  display: flex;
17
18
  align-items: center;
18
19
  justify-content: center;
@@ -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":"M7.134 3.38a1.846 1.846 0 0 1 1.943.368l4.476 4.218.012.013c.565.585.935 1.262.935 2.021 0 .76-.37 1.436-.935 2.021l-.012.013-4.476 4.218a1.846 1.846 0 0 1-1.943.37C6.527 16.384 6 15.804 6 15V5c0-.805.527-1.385 1.134-1.62Zm.544 1.397c-.133.051-.178.139-.178.223v10c0 .084.045.172.178.223a.346.346 0 0 0 .371-.064l4.449-4.192c.392-.41.502-.729.502-.967s-.11-.557-.502-.967L8.049 4.841a.347.347 0 0 0-.371-.064Z"},"children":[]}],"metadata":""}]},"name":"smart-folder"};
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;
@@ -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
- <ButtonBase dangerous={Boolean(error)} borderless className={className} onClick={onClick}>
43
+ <BaseButton color={error ? "error" : "neutral"} variant="ghost" className={className} onClick={onClick}>
43
44
  {iconNode}
44
45
  {name}
45
- </ButtonBase>
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 {Button} from "../../button/button";
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
- <Button borderless Icon={RemoveIcon} disabled={selectProps.isDisabled} size={":button-size/super-small"} />
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 maxMenuHeight =
305
- Math.max((document.body.clientHeight / 100) * popupHeightVH, popupMinHeightPx) -
306
- valueMaxHeight -
307
- paddingPopup -
308
- paddingMenu;
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);
@@ -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 iconSize={16} />
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={theme.textColor} {...props}>
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
- <CircleContainer
134
- containerSize={size}
135
- containerWidth={width}
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
- outlineColor={outlineColor}
144
- onChange={onChange}
145
- className={className}
146
- type="checkbox"
141
+ backgroundColor={backgroundColor}
147
142
  disabled={disabled}
148
- checked={value}
149
- {...rest}
150
- />
151
- </CircleContainer>
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}>
@@ -1,3 +0,0 @@
1
- import {BackButton} from "./button/back-button";
2
-
3
- export {BackButton};
@@ -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
@@ -1,3 +0,0 @@
1
- import {Button} from "./button/button";
2
-
3
- export {Button};
@@ -1,3 +0,0 @@
1
- import {IconButton} from "./button/icon-button";
2
-
3
- export {IconButton};