@fibery/ui-kit 1.4.1 → 1.7.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 (71) hide show
  1. package/index.ts +0 -1
  2. package/package.json +39 -23
  3. package/src/Item.tsx +8 -2
  4. package/src/Pallete.ts +191 -191
  5. package/src/Select/components.tsx +22 -21
  6. package/src/Select/index.tsx +98 -30
  7. package/src/Select/select-control-settings-context.tsx +20 -0
  8. package/src/Select/select-in-popover.tsx +333 -0
  9. package/src/Select/styles.ts +27 -1
  10. package/src/ThemeProvider.tsx +1 -1
  11. package/src/antd/styles.ts +5 -7
  12. package/src/designSystem.ts +129 -91
  13. package/src/error-alert.tsx +2 -2
  14. package/src/icons/Icon.tsx +17 -12
  15. package/src/icons/ast/AddGroup.ts +8 -0
  16. package/src/icons/ast/AiAssistant.ts +8 -0
  17. package/src/icons/ast/AiAvatar.ts +8 -0
  18. package/src/icons/ast/ArrowBottom.ts +1 -1
  19. package/src/icons/ast/ArrowCollapse.ts +1 -1
  20. package/src/icons/ast/ArrowCollapseVertical.ts +1 -1
  21. package/src/icons/ast/ArrowLeft.ts +1 -1
  22. package/src/icons/ast/ArrowRight.ts +1 -1
  23. package/src/icons/ast/ArrowTop.ts +1 -1
  24. package/src/icons/ast/Atom.ts +8 -0
  25. package/src/icons/ast/Copy.ts +8 -0
  26. package/src/icons/ast/DynamicFilterValue.ts +8 -0
  27. package/src/icons/ast/ExtensionAssignments.ts +1 -1
  28. package/src/icons/ast/FileUpload.ts +8 -0
  29. package/src/icons/ast/FormWithCover.ts +8 -0
  30. package/src/icons/ast/FormWithoutCover.ts +8 -0
  31. package/src/icons/ast/Github.ts +3 -27
  32. package/src/icons/ast/Gitlab.ts +3 -25
  33. package/src/icons/ast/Hint.ts +1 -1
  34. package/src/icons/ast/Jira.ts +8 -0
  35. package/src/icons/ast/Markdown.ts +8 -0
  36. package/src/icons/ast/Minus.ts +8 -0
  37. package/src/icons/ast/MoreCompact.ts +1 -1
  38. package/src/icons/ast/RicheditorBlockFile.ts +8 -0
  39. package/src/icons/ast/RicheditorBlockH4.ts +1 -1
  40. package/src/icons/ast/SimpleCompass.ts +8 -0
  41. package/src/icons/ast/Templates.ts +8 -0
  42. package/src/icons/ast/TypeLocation.ts +8 -0
  43. package/src/icons/ast/ViewForm.ts +8 -0
  44. package/src/icons/ast/ViewMap.ts +8 -0
  45. package/src/icons/ast/index.tsx +199 -181
  46. package/src/icons/react/AddGroup.tsx +12 -0
  47. package/src/icons/react/AiAssistant.tsx +12 -0
  48. package/src/icons/react/AiAvatar.tsx +12 -0
  49. package/src/icons/react/Atom.tsx +12 -0
  50. package/src/icons/react/Copy.tsx +12 -0
  51. package/src/icons/react/DynamicFilterValue.tsx +12 -0
  52. package/src/icons/react/FileUpload.tsx +12 -0
  53. package/src/icons/react/FormWithCover.tsx +12 -0
  54. package/src/icons/react/FormWithoutCover.tsx +12 -0
  55. package/src/icons/react/Github.tsx +8 -6
  56. package/src/icons/react/Gitlab.tsx +8 -6
  57. package/src/icons/react/Jira.tsx +12 -0
  58. package/src/icons/react/Markdown.tsx +12 -0
  59. package/src/icons/react/Minus.tsx +12 -0
  60. package/src/icons/react/RicheditorBlockFile.tsx +12 -0
  61. package/src/icons/react/SimpleCompass.tsx +12 -0
  62. package/src/icons/react/Templates.tsx +12 -0
  63. package/src/icons/react/TypeLocation.tsx +12 -0
  64. package/src/icons/react/ViewForm.tsx +12 -0
  65. package/src/icons/react/ViewMap.tsx +12 -0
  66. package/src/icons/react/index.tsx +199 -181
  67. package/src/tooltip.tsx +132 -152
  68. package/src/Button.d.ts +0 -26
  69. package/src/Button.js +0 -360
  70. package/src/antd/ant-tooltip.tsx +0 -5
  71. package/src/icons/IconAsBackground.tsx +0 -15
package/src/tooltip.tsx CHANGED
@@ -1,184 +1,164 @@
1
- import {css} from "@linaria/core";
2
- import type {ReactNode} from "react";
3
- import cx from "classnames";
4
- import PropTypes from "prop-types";
5
- import {AntTooltip, TooltipPlacement} from "./antd/ant-tooltip";
6
- import {border, opacity, textStyles, themeVars, tooltipDelay} from "./designSystem";
1
+ import {css, cx} from "@linaria/core";
2
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
3
+ import type {ReactNode, SyntheticEvent} from "react";
4
+ import {border, lineHeight, space, themeVars, tooltipDelay} from "./designSystem";
5
+
6
+ const preventDefaultAndStopPropagation = (e: SyntheticEvent) => {
7
+ e.preventDefault();
8
+ e.stopPropagation();
9
+ };
7
10
 
8
11
  const titleStyle = css`
9
- ${{
10
- color: themeVars.whiteColor,
11
- fontWeight: 500,
12
- opacity: opacity.opacity90,
13
- }}
12
+ color: ${themeVars.whiteColor};
13
+ line-height: ${lineHeight.heading};
14
+ font-weight: 500;
14
15
  `;
15
16
 
16
17
  const descriptionStyle = css`
17
- ${{
18
- color: themeVars.accentTextColor,
19
- fontWeight: 400,
20
- }}
18
+ color: ${themeVars.shortcutTextColor};
19
+ line-height: ${lineHeight.heading};
20
+ font-weight: 400;
21
21
  `;
22
22
 
23
23
  const tooltipStyle = css`
24
- ${{
25
- zIndex: 100000,
26
- transition: "none",
27
- pointerEvents: "none",
28
- maxWidth: 300,
29
- ...textStyles.small,
30
- "& .ant-tooltip-arrow": {
31
- visibility: "hidden",
32
- },
33
- "& .ant-tooltip-inner": {
34
- maxWidth: 300,
35
- minHeight: 30,
36
- backgroundColor: themeVars.tooltipBgColor,
37
- borderRadius: border.radius6,
38
- },
39
- }}
24
+ font-size: 13px;
25
+ color: ${themeVars.whiteColor};
26
+ z-index: 100000;
27
+ min-height: 30px;
28
+ max-width: 300px;
29
+ background-color: ${themeVars.tooltipBgColor};
30
+ padding: ${space.s}px ${space.m}px;
31
+ border-radius: ${border.radius6}px;
32
+ box-shadow: ${themeVars.actionMenuShadow};
33
+
34
+ @media (prefers-reduced-motion: no-preference) {
35
+ @keyframes zoomIn {
36
+ from {
37
+ opacity: 0;
38
+ transform: scale(0.8);
39
+ }
40
+
41
+ to {
42
+ opacity: 1;
43
+ transform: scale(1);
44
+ }
45
+ }
46
+
47
+ @keyframes zoomOut {
48
+ from {
49
+ transform: scale(1);
50
+ }
51
+
52
+ to {
53
+ opacity: 0;
54
+ transform: scale(0.8);
55
+ }
56
+ }
57
+
58
+ will-change: transform, opacity;
59
+ transform-origin: var(--radix-tooltip-content-transform-origin);
60
+ animation-duration: 0.1s;
61
+
62
+ &[data-state="delayed-open"] {
63
+ animation-name: zoomIn;
64
+ animation-timing-function: ease-out;
65
+ }
66
+ }
40
67
  `;
41
68
 
42
69
  const whiteBgStyle = css`
43
- ${{
44
- "& .ant-tooltip-inner": {
45
- backgroundColor: themeVars.actionMenuInnerBg,
46
- color: themeVars.textColor,
47
- },
48
- }}
70
+ background-color: ${themeVars.actionMenuInnerBg};
71
+ color: ${themeVars.textColor};
49
72
  `;
50
73
 
51
- type AlignPoint = string;
52
-
53
- export interface AlignType {
54
- /**
55
- * move point of source node to align with point of target node.
56
- * Such as ['tr','cc'], align top right point of source node with center point of target node.
57
- * Point can be 't'(top), 'b'(bottom), 'c'(center), 'l'(left), 'r'(right) */
58
- points?: AlignPoint[];
59
- /**
60
- * offset source node by offset[0] in x and offset[1] in y.
61
- * If offset contains percentage string value, it is relative to sourceNode region.
62
- */
63
- offset?: number[];
64
- /**
65
- * offset target node by offset[0] in x and offset[1] in y.
66
- * If targetOffset contains percentage string value, it is relative to targetNode region.
67
- */
68
- targetOffset?: number[];
69
- /**
70
- * If adjustX field is true, will adjust source node in x direction if source node is invisible.
71
- * If adjustY field is true, will adjust source node in y direction if source node is invisible.
72
- */
73
- overflow?: {
74
- adjustX?: boolean | number;
75
- adjustY?: boolean | number;
76
- };
77
- /**
78
- * Whether use css right instead of left to position
79
- */
80
- useCssRight?: boolean;
81
- /**
82
- * Whether use css bottom instead of top to position
83
- */
84
- useCssBottom?: boolean;
85
- /**
86
- * Whether use css transform instead of left/top/right/bottom to position if browser supports.
87
- * Defaults to false.
88
- */
89
- useCssTransform?: boolean;
90
- ignoreShake?: boolean;
91
- }
92
-
93
- const alignByPlacement = {
94
- bottom: {offset: [0, -2] as [number, number]},
95
- };
96
-
97
74
  export const TooltipTitle = ({children}: {children: ReactNode}) => <div className={titleStyle}>{children}</div>;
98
75
  export const TooltipDescription = ({children}: {children: ReactNode}) => (
99
76
  <div className={descriptionStyle}>{children}</div>
100
77
  );
101
78
 
102
- export function TooltipContent({title, shortcut}: {title: string; shortcut?: string}) {
103
- return (
104
- <div
105
- className={css`
106
- display: flex;
107
- flex-direction: column;
108
- align-items: center;
109
- `}
110
- >
111
- <TooltipTitle>{title}</TooltipTitle>
112
- {shortcut ? <TooltipDescription>{shortcut}</TooltipDescription> : null}
113
- </div>
114
- );
115
- }
79
+ export const TooltipContent = ({title, shortcut}: {title: string; shortcut?: string}) => (
80
+ <div
81
+ className={css`
82
+ display: flex;
83
+ flex-direction: column;
84
+ align-items: center;
85
+ `}
86
+ >
87
+ <TooltipTitle>{title}</TooltipTitle>
88
+ {shortcut ? <TooltipDescription>{shortcut}</TooltipDescription> : null}
89
+ </div>
90
+ );
116
91
 
117
- type Props = {
92
+ export const TooltipProvider: React.FC<TooltipPrimitive.TooltipProviderProps> = (props) => (
93
+ <TooltipPrimitive.Provider disableHoverableContent skipDelayDuration={150} {...props} />
94
+ );
95
+
96
+ export type TooltipProps = {
118
97
  title?: ReactNode;
119
98
  description?: ReactNode;
120
99
  content?: ReactNode;
121
- placement?: TooltipPlacement;
122
- align?: AlignType;
123
- trigger?: string | string[];
124
- visible?: boolean;
100
+ side?: TooltipPrimitive.TooltipContentProps["side"];
101
+ sideOffset?: TooltipPrimitive.TooltipContentProps["sideOffset"];
102
+ align?: TooltipPrimitive.TooltipContentProps["align"];
103
+ alignOffset?: TooltipPrimitive.TooltipContentProps["alignOffset"];
125
104
  instant?: boolean;
126
- mouseEnterDelay?: number;
127
- children: JSX.Element | string;
105
+ children: ReactNode;
128
106
  whiteBg?: boolean;
107
+ visible?: boolean;
129
108
  onVisibleChange?: (visible: boolean) => void;
130
- destroyTooltipOnHide?: boolean;
131
- getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
109
+ disabled?: boolean;
110
+ /** should keep tooltip visible after click */
111
+ keepOnClick?: boolean;
132
112
  };
133
113
 
134
- export function Tooltip(props: Props) {
135
- const {
136
- title,
137
- description,
138
- content = (title || description) && (
139
- <>
140
- <TooltipTitle>{title}</TooltipTitle>
141
- <TooltipDescription>{description}</TooltipDescription>
142
- </>
143
- ),
144
- align,
145
- placement,
146
- trigger,
147
- visible,
148
- instant,
149
- mouseEnterDelay,
150
- children,
151
- whiteBg,
152
- onVisibleChange,
153
- destroyTooltipOnHide,
154
- getPopupContainer,
155
- } = props;
156
- const maybeVisibleProp = visible === undefined ? {} : {visible};
114
+ export const Tooltip: React.FC<TooltipProps> = ({
115
+ title,
116
+ description,
117
+ content = (title || description) && (
118
+ <>
119
+ <TooltipTitle>{title}</TooltipTitle>
120
+ <TooltipDescription>{description}</TooltipDescription>
121
+ </>
122
+ ),
123
+ side,
124
+ sideOffset = space.xs,
125
+ align,
126
+ alignOffset,
127
+ instant,
128
+ children,
129
+ whiteBg,
130
+ visible,
131
+ onVisibleChange,
132
+ keepOnClick,
133
+ disabled,
134
+ }) => {
135
+ const triggerProps = keepOnClick
136
+ ? {
137
+ onPointerDown: preventDefaultAndStopPropagation,
138
+ onClick: preventDefaultAndStopPropagation,
139
+ }
140
+ : null;
157
141
 
158
142
  return (
159
- <AntTooltip
160
- title={content}
161
- {...maybeVisibleProp}
162
- trigger={trigger}
163
- placement={placement}
164
- mouseEnterDelay={mouseEnterDelay || (instant ? 0 : tooltipDelay.enter)}
165
- mouseLeaveDelay={instant ? 0 : tooltipDelay.leave}
166
- overlayClassName={cx(tooltipStyle, {[whiteBgStyle]: whiteBg})}
167
- align={align || (placement === "bottom" ? alignByPlacement.bottom : undefined)}
168
- onVisibleChange={onVisibleChange}
169
- destroyTooltipOnHide={destroyTooltipOnHide}
170
- getPopupContainer={getPopupContainer}
143
+ <TooltipPrimitive.Root
144
+ delayDuration={instant ? 0 : tooltipDelay.enter}
145
+ open={disabled ? false : Boolean(content) && visible}
146
+ onOpenChange={onVisibleChange}
171
147
  >
172
- {children}
173
- </AntTooltip>
148
+ <TooltipPrimitive.Trigger {...triggerProps} asChild>
149
+ {children}
150
+ </TooltipPrimitive.Trigger>
151
+ <TooltipPrimitive.Portal>
152
+ <TooltipPrimitive.Content
153
+ side={side}
154
+ sideOffset={sideOffset}
155
+ align={align}
156
+ alignOffset={alignOffset}
157
+ className={cx(tooltipStyle, whiteBg && whiteBgStyle)}
158
+ >
159
+ {content}
160
+ </TooltipPrimitive.Content>
161
+ </TooltipPrimitive.Portal>
162
+ </TooltipPrimitive.Root>
174
163
  );
175
- }
176
-
177
- Tooltip.propTypes = {
178
- title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
179
- description: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
180
- content: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
181
- placement: PropTypes.string,
182
- visible: PropTypes.bool,
183
- instant: PropTypes.bool,
184
164
  };
package/src/Button.d.ts DELETED
@@ -1,26 +0,0 @@
1
- import type {ComponentPropsWithRef, FunctionComponent} from "react";
2
- import {IconBaseProps} from "./icons/types";
3
- type Size = ":button-size/super-small" | ":button-size/small" | ":button-size/normal" | ":button-size/big";
4
- type Props = {
5
- size?: Size;
6
- borderless?: boolean;
7
- Icon?: ((props: IconBaseProps) => JSX.Element) | null;
8
- color?: string;
9
- primary?: boolean;
10
- pending?: boolean;
11
- width?: string | number;
12
- height?: string | number;
13
- } & Omit<ComponentPropsWithRef<"button">, "size" | "width" | "height">;
14
-
15
- export const Button: FunctionComponent<Props>;
16
- export const buttonClassName: string;
17
-
18
- export const ActionsButton: FunctionComponent<{
19
- inverted?: boolean;
20
- label?: string;
21
- color?: string;
22
- onClick?: Props["onClick"];
23
- }>;
24
- export const ActionsButtonCompact: FunctionComponent<
25
- {inverted?: boolean} & Omit<Props, "color" | "borderless" | "Icon" | "size">
26
- >;
package/src/Button.js DELETED
@@ -1,360 +0,0 @@
1
- import {hasNonEmptyChild} from "@fibery/react/src/has-non-empty-child";
2
- import {css} from "@linaria/core";
3
- import {styled} from "@linaria/react";
4
- import cx from "classnames";
5
- import _ from "lodash";
6
- import PropTypes from "prop-types";
7
- import {forwardRef} from "react";
8
- import {border, colors, fontWeight, getDarkenColor, getOpacities, opacity, textStyles, themeVars} from "./designSystem";
9
- import MoreIcon from "./icons/react/More";
10
- import MoreCompactIcon from "./icons/react/MoreCompact";
11
- import {Item} from "./Item";
12
- import {Spinner} from "./loaders";
13
- import {useTheme} from "./ThemeProvider";
14
-
15
- const baseSize = 14;
16
-
17
- const fontSizes = {
18
- ":button-size/super-small": baseSize - 4,
19
- ":button-size/small": baseSize - 2,
20
- ":button-size/normal": baseSize,
21
- ":button-size/big": baseSize + 2,
22
- };
23
-
24
- const sizeShifts = {
25
- ":button-size/super-small": -2,
26
- ":button-size/small": -1,
27
- ":button-size/normal": 0,
28
- ":button-size/big": 1,
29
- };
30
-
31
- const buttonBorderWidth = 1;
32
-
33
- const staticButtonStyle = css`
34
- ${{
35
- boxSizing: "border-box",
36
- display: "flex",
37
- justifyContent: "center",
38
- alignItems: "center",
39
- verticalAlign: "middle",
40
- fontWeight: fontWeight.bold,
41
- lineHeight: 1,
42
- margin: 0,
43
- borderRadius: border.radius6,
44
- borderWidth: buttonBorderWidth,
45
- borderStyle: "solid",
46
- outline: "none",
47
- position: "relative",
48
- }}
49
- `;
50
-
51
- const ordersInGroup = {
52
- first: css`
53
- &.${staticButtonStyle} {
54
- ${{
55
- display: "inline-flex",
56
- borderRadius: `${border.radius6}px 0 0 ${border.radius6}px`,
57
- marginRight: -1,
58
- }}
59
- }
60
- `,
61
- middle: css`
62
- &.${staticButtonStyle} {
63
- ${{
64
- display: "inline-flex",
65
- borderRadius: border.radius0,
66
- marginRight: -1,
67
- }}
68
- }
69
- `,
70
- last: css`
71
- &.${staticButtonStyle} {
72
- ${{
73
- display: "inline-flex",
74
- borderRadius: `0 ${border.radius6}px ${border.radius6}px 0`,
75
- }}
76
- }
77
- `,
78
- };
79
-
80
- const getMainColor = ({color, dangerous, theme}) => {
81
- if (color) {
82
- return color;
83
- }
84
- if (dangerous) {
85
- return theme.danger;
86
- }
87
- if (!theme) {
88
- return colors.primary;
89
- }
90
- return theme.buttonColor;
91
- };
92
-
93
- const getBorderColor = ({mainColor, borderless, primary}) => {
94
- if (borderless) {
95
- return colors.transparent;
96
- }
97
- if (primary) {
98
- return mainColor;
99
- }
100
- return getOpacities(mainColor).opacity15;
101
- };
102
-
103
- const getHoverBorderColor = ({mainColor, borderless, primary, hoverBgColor}) => {
104
- if (borderless) {
105
- return colors.transparent;
106
- }
107
- if (primary) {
108
- return hoverBgColor;
109
- }
110
- return mainColor;
111
- };
112
-
113
- const getTextColor = ({mainColor, primary, theme}) => {
114
- if (primary) {
115
- return theme.buttonPrimaryTextColor;
116
- }
117
- return mainColor;
118
- };
119
-
120
- const getBgColor = ({mainColor, primary}) => {
121
- if (primary) {
122
- return mainColor;
123
- }
124
- return colors.transparent;
125
- };
126
-
127
- const getHoverBgColor = ({mainColor, borderless, primary}) => {
128
- if (primary) {
129
- return getDarkenColor(mainColor);
130
- }
131
- if (borderless) {
132
- return getOpacities(mainColor).opacity15;
133
- }
134
- return colors.transparent;
135
- };
136
-
137
- const getSpinnerColor = ({mainColor, primary}) => {
138
- if (primary) {
139
- return colors.inversedTextColor;
140
- }
141
- return mainColor;
142
- };
143
-
144
- const getButtonMagicConstants = _.memoize((size) => {
145
- const sizeShift = sizeShifts[size];
146
-
147
- const fontSize = fontSizes[size];
148
- const minSize = fontSize * 2;
149
- const horizontalPadding = baseSize - 2 + sizeShift * 4;
150
-
151
- return {fontSize, minSize, horizontalPadding};
152
- });
153
-
154
- const getIconMagicConstants = _.memoize((size) => {
155
- const sizeShift = sizeShifts[size];
156
-
157
- const iconSize = baseSize + 2 + sizeShift * 2;
158
- const leftContainerSize = 8;
159
- const leftContainerMarginRight = iconSize - leftContainerSize;
160
-
161
- return {iconSize, leftContainerSize, leftContainerMarginRight};
162
- });
163
-
164
- const StyledButton = styled.button`
165
- font-size: ${({buttonSize}) => getButtonMagicConstants(buttonSize).fontSize}px;
166
- min-height: ${({buttonSize}) => getButtonMagicConstants(buttonSize).minSize}px;
167
- min-width: ${({buttonSize}) => getButtonMagicConstants(buttonSize).minSize}px;
168
- padding-top: 0;
169
- padding-bottom: 0;
170
- padding-left: ${({buttonSize}) => getButtonMagicConstants(buttonSize).horizontalPadding}px;
171
- padding-right: ${({buttonSize}) => getButtonMagicConstants(buttonSize).horizontalPadding}px;
172
- opacity: ${({disabled}) => (disabled ? opacity.regular : 1)};
173
- width: ${({buttonWidth = "auto"}) => (typeof buttonWidth === "string" ? buttonWidth : `${buttonWidth}px`)};
174
- height: ${({buttonHeight = "auto"}) => (typeof buttonHeight === "string" ? buttonHeight : `${buttonHeight}px`)};
175
- color: ${({textColor}) => textColor};
176
- background-color: ${({bgColor}) => bgColor};
177
- border-color: ${({borderColor}) => borderColor};
178
- cursor: ${({clickable}) => (clickable ? "pointer" : "default")};
179
- transition: all 150ms ease-out;
180
-
181
- &:focus {
182
- box-shadow: ${({borderColor, activeStyle}) =>
183
- activeStyle ? `0 0 0 3px ${getOpacities(borderColor).light}` : "none"};
184
- background-color: ${({hoverBgColor}) => hoverBgColor};
185
- border-color: ${({hoverBorderColor}) => hoverBorderColor};
186
- transition: all 150ms ease-out;
187
- }
188
-
189
- &:focus:not(:focus-visible) {
190
- box-shadow: none;
191
- background-color: ${({bgColor}) => bgColor};
192
- border-color: ${({borderColor}) => borderColor};
193
- transition: none;
194
- }
195
-
196
- &:focus-visible {
197
- box-shadow: ${({borderColor, activeStyle}) =>
198
- activeStyle ? `0 0 0 3px ${getOpacities(borderColor).light}` : "none"};
199
- background-color: ${({hoverBgColor}) => hoverBgColor};
200
- border-color: ${({hoverBorderColor}) => hoverBorderColor};
201
- transition: all 150ms ease-out;
202
- }
203
-
204
- &:hover,
205
- &:focus:hover:not(:focus-visible) {
206
- background-color: ${({hoverBgColor}) => hoverBgColor};
207
- border-color: ${({hoverBorderColor}) => hoverBorderColor};
208
- transition: all 150ms ease-out;
209
- }
210
- `;
211
-
212
- export const buttonClassName = StyledButton;
213
-
214
- const shortcutStyle = css`
215
- ${{
216
- ...textStyles.small,
217
- color: themeVars.whiteColor,
218
- border: "solid 1px",
219
- borderRadius: border.radius4,
220
- paddingLeft: 4,
221
- paddingRight: 4,
222
- marginLeft: 4,
223
- opacity: 0.7,
224
- }}
225
- `;
226
-
227
- const leftContainerMarginRightVar = "--fibery-button-left-container-margin-right";
228
-
229
- const leftContainerClassName = css`
230
- margin-right: var(${leftContainerMarginRightVar});
231
- `;
232
-
233
- export const Button = forwardRef(
234
- (
235
- {
236
- children,
237
- color,
238
- dangerous,
239
- borderless,
240
- primary,
241
- pending,
242
- icon,
243
- Icon,
244
- size = ":button-size/normal",
245
- type = "button",
246
- disabled,
247
- width,
248
- height,
249
- inGroup,
250
- onClick,
251
- className,
252
- shortcut,
253
- noOverflow = true,
254
- ...rest
255
- },
256
- forwardedRef
257
- ) => {
258
- const theme = useTheme();
259
- const mainColor = getMainColor({color, dangerous, theme});
260
- const textColor = getTextColor({mainColor, primary, theme});
261
- const spinnerBgColor = getOpacities(textColor).light;
262
- const spinnerColor = getSpinnerColor({mainColor, primary});
263
- const bgColor = getBgColor({mainColor, primary});
264
- const hoverBgColor = getHoverBgColor({mainColor, borderless, primary});
265
- const borderColor = getBorderColor({mainColor, borderless, primary});
266
- const hoverBorderColor = getHoverBorderColor({
267
- mainColor,
268
- borderless,
269
- primary,
270
- hoverBgColor,
271
- });
272
- if (icon) {
273
- // eslint-disable-next-line no-console
274
- console.warn("'icon' props doesn't support anymore. Please use 'Icon' prop with explicit Icon Component");
275
- }
276
- const {iconSize, leftContainerSize, leftContainerMarginRight} = getIconMagicConstants(size);
277
-
278
- const leftContainer = pending ? (
279
- <Spinner
280
- backgroundColor={spinnerBgColor}
281
- color={spinnerColor}
282
- size={iconSize}
283
- containerSize={leftContainerSize}
284
- />
285
- ) : Icon ? (
286
- <Icon color={textColor} size={iconSize} containerSize={leftContainerSize} />
287
- ) : null;
288
- const styleVariable = {
289
- buttonSize: size,
290
- disabled,
291
- pending,
292
- buttonWidth: width,
293
- buttonHeight: height,
294
- textColor,
295
- clickable: !disabled && !pending,
296
- hoverBgColor: !disabled && !pending ? hoverBgColor : bgColor,
297
- hoverBorderColor: !disabled && !pending ? hoverBorderColor : borderColor,
298
- borderColor,
299
- bgColor,
300
- };
301
-
302
- return (
303
- <StyledButton
304
- {...styleVariable}
305
- ref={forwardedRef}
306
- type={type}
307
- onClick={!disabled && !pending && onClick ? onClick : _.noop}
308
- disabled={disabled}
309
- className={cx(className, staticButtonStyle, ordersInGroup[inGroup])}
310
- {...rest}
311
- >
312
- <Item
313
- leftContainer={leftContainer}
314
- style={{
315
- [leftContainerMarginRightVar]: `${leftContainerMarginRight}px`,
316
- }}
317
- containerClassName={cx({[leftContainerClassName]: leftContainer && hasNonEmptyChild(children)})}
318
- rightContainer={shortcut && <span className={cx(shortcutStyle)}>{shortcut}</span>}
319
- noOverflow={noOverflow}
320
- >
321
- {children}
322
- </Item>
323
- </StyledButton>
324
- );
325
- }
326
- );
327
-
328
- Button.propTypes = {
329
- size: PropTypes.oneOf(Object.keys(fontSizes)),
330
- type: PropTypes.string,
331
- primary: PropTypes.bool,
332
- dangerous: PropTypes.bool,
333
- disabled: PropTypes.bool,
334
- pending: PropTypes.bool,
335
- borderless: PropTypes.bool,
336
- icon: PropTypes.string,
337
- color: PropTypes.string,
338
- width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
339
- onClick: PropTypes.func,
340
- inGroup: PropTypes.oneOf(Object.keys(ordersInGroup)),
341
- };
342
-
343
- // TODO can be inlined
344
- export function ActionsButton({onClick, label = ``, disabled}) {
345
- return <Button Icon={MoreIcon} onClick={onClick} borderless aria-label={label} disabled={disabled} />;
346
- }
347
-
348
- export const ActionsButtonCompact = forwardRef(({inverted, ...rest}, ref) => {
349
- const theme = useTheme();
350
- return (
351
- <Button
352
- ref={ref}
353
- size={":button-size/small"}
354
- Icon={MoreCompactIcon}
355
- color={inverted ? colors.inversedTextColor : theme.buttonColor}
356
- borderless
357
- {...rest}
358
- />
359
- );
360
- });