@fibery/ui-kit 1.37.0 → 1.38.1

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 (194) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/config/jest/testFrameworkSetup.js +1 -1
  3. package/package.json +20 -16
  4. package/src/abbreviate-name.ts +42 -0
  5. package/src/actions-menu/actions-menu-item.tsx +32 -11
  6. package/src/actions-menu/actions-menu-props.tsx +5 -0
  7. package/src/actions-menu/actions-menu-sub-command-menu.tsx +7 -4
  8. package/src/actions-menu/actions-menu-sub-menu.tsx +9 -3
  9. package/src/actions-menu/actions-menu.tsx +28 -9
  10. package/src/actions-menu/context-actions-menu.tsx +22 -0
  11. package/src/actions-panel.tsx +12 -2
  12. package/src/animated-height-container.tsx +24 -5
  13. package/src/antd/ant-upload.tsx +1 -1
  14. package/src/antd/input.tsx +4 -0
  15. package/src/avatar.tsx +1 -27
  16. package/src/axis-header.tsx +136 -76
  17. package/src/box.tsx +1 -1
  18. package/src/breadcrumb.tsx +78 -0
  19. package/src/button/actions-button-compact.tsx +4 -1
  20. package/src/button/base-button.tsx +7 -3
  21. package/src/button/button-group.tsx +1 -1
  22. package/src/button/button.tsx +33 -1
  23. package/src/button/icon-button.tsx +10 -1
  24. package/src/button/select-button.tsx +4 -0
  25. package/src/card-container.tsx +10 -6
  26. package/src/checkbox.tsx +17 -0
  27. package/src/collapsible-section.tsx +3 -1
  28. package/src/color-picker/swatch.tsx +1 -0
  29. package/src/command-menu/index.tsx +3 -3
  30. package/src/context-menu/index.tsx +10 -1
  31. package/src/date-picker/autocomplete.tsx +11 -5
  32. package/src/date-picker/date-range-input.tsx +5 -1
  33. package/src/date-picker/date-range-picker-popup-content.tsx +31 -13
  34. package/src/date-picker/date-range-picker.tsx +6 -3
  35. package/src/date-picker/relative-date-picker.tsx +6 -2
  36. package/src/date-picker/single-date-input.tsx +5 -1
  37. package/src/date-picker/single-date-picker.tsx +8 -5
  38. package/src/date-picker/styles.ts +52 -26
  39. package/src/date-picker/types.ts +3 -1
  40. package/src/day-select/day-select.tsx +21 -75
  41. package/src/day-select/iso-week-day-select.tsx +1 -1
  42. package/src/day-select/mount-day-select.tsx +2 -2
  43. package/src/day-select/week-day-select.tsx +1 -5
  44. package/src/design-system.ts +45 -12
  45. package/src/dropdown-menu/index.tsx +19 -2
  46. package/src/emoji-picker/app-icon-picker.tsx +6 -4
  47. package/src/emoji-picker/emoji-picker-preview-footer.tsx +5 -1
  48. package/src/emoji-picker/emoji-picker.tsx +3 -0
  49. package/src/emoji-picker/emoji.tsx +5 -3
  50. package/src/emoji-picker/icon-emoji-picker.tsx +10 -1
  51. package/src/emoji-picker/primitives/emoji.tsx +49 -51
  52. package/src/emoji-picker/primitives/footer.tsx +5 -0
  53. package/src/emoji-picker/primitives/search.tsx +8 -0
  54. package/src/emoji-picker/primitives/skin-tone.tsx +12 -1
  55. package/src/emoji-picker/use-responsive-emoji-size.ts +11 -0
  56. package/src/emoji-picker/utils/emoji-set.ts +2 -1
  57. package/src/empty-state/empty-state.tsx +6 -0
  58. package/src/fibermoji-placeholder.tsx +1 -27
  59. package/src/field-icon.tsx +4 -1
  60. package/src/file-item-2.tsx +408 -0
  61. package/src/file-item.tsx +215 -47
  62. package/src/header-layout.tsx +11 -0
  63. package/src/html-styles.ts +21 -4
  64. package/src/icons/ast/ActivityFilled.ts +8 -0
  65. package/src/icons/ast/AiAssistantFilled.ts +8 -0
  66. package/src/icons/ast/Back.ts +1 -1
  67. package/src/icons/ast/CollapseAllHorizontal.ts +8 -0
  68. package/src/icons/ast/DateRange.ts +1 -1
  69. package/src/icons/ast/EntityCreateFilled.ts +8 -0
  70. package/src/icons/ast/ExpandAllHorizontal.ts +8 -0
  71. package/src/icons/ast/ExtensionFiles.ts +1 -1
  72. package/src/icons/ast/FileUpload.ts +1 -1
  73. package/src/icons/ast/GlobeUnpublish.ts +8 -0
  74. package/src/icons/ast/HomeFilled.ts +8 -0
  75. package/src/icons/ast/KeyboardHideDown.ts +8 -0
  76. package/src/icons/ast/LayoutMultiple.ts +8 -0
  77. package/src/icons/ast/RicheditorHistoryRedo.ts +1 -1
  78. package/src/icons/ast/RicheditorHistoryUndo.ts +1 -1
  79. package/src/icons/ast/SearchFilled.ts +8 -0
  80. package/src/icons/ast/SettingsFilled.ts +8 -0
  81. package/src/icons/ast/SlideMenuFilled.ts +8 -0
  82. package/src/icons/ast/SwitchToMention.ts +8 -0
  83. package/src/icons/ast/SwitchToText.ts +8 -0
  84. package/src/icons/ast/SwitchToWidget.ts +8 -0
  85. package/src/icons/ast/TypeDate.ts +1 -1
  86. package/src/icons/ast/ViewGallery.ts +8 -0
  87. package/src/icons/ast/index.tsx +16 -0
  88. package/src/icons/react/ActivityFilled.tsx +13 -0
  89. package/src/icons/react/AiAssistantFilled.tsx +13 -0
  90. package/src/icons/react/CollapseAllHorizontal.tsx +13 -0
  91. package/src/icons/react/EntityCreateFilled.tsx +13 -0
  92. package/src/icons/react/ExpandAllHorizontal.tsx +13 -0
  93. package/src/icons/react/GlobeUnpublish.tsx +13 -0
  94. package/src/icons/react/HomeFilled.tsx +13 -0
  95. package/src/icons/react/KeyboardHideDown.tsx +13 -0
  96. package/src/icons/react/LayoutMultiple.tsx +13 -0
  97. package/src/icons/react/SearchFilled.tsx +13 -0
  98. package/src/icons/react/SettingsFilled.tsx +13 -0
  99. package/src/icons/react/SlideMenuFilled.tsx +13 -0
  100. package/src/icons/react/SwitchToMention.tsx +13 -0
  101. package/src/icons/react/SwitchToText.tsx +13 -0
  102. package/src/icons/react/SwitchToWidget.tsx +13 -0
  103. package/src/icons/react/ViewGallery.tsx +13 -0
  104. package/src/icons/react/index.tsx +16 -0
  105. package/src/icons/svg/activity-filled.svg +4 -0
  106. package/src/icons/svg/ai-assistant-filled.svg +3 -0
  107. package/src/icons/svg/back.svg +3 -1
  108. package/src/icons/svg/collapse-all-horizontal.svg +3 -0
  109. package/src/icons/svg/date-range.svg +3 -3
  110. package/src/icons/svg/entity-create-filled.svg +4 -0
  111. package/src/icons/svg/expand-all-horizontal.svg +3 -0
  112. package/src/icons/svg/extension/files.svg +3 -1
  113. package/src/icons/svg/file-upload.svg +3 -6
  114. package/src/icons/svg/globe-unpublish.svg +4 -0
  115. package/src/icons/svg/home-filled.svg +3 -0
  116. package/src/icons/svg/keyboard-hide-down.svg +1 -0
  117. package/src/icons/svg/layout-multiple.svg +3 -0
  118. package/src/icons/svg/richeditor/history/redo.svg +3 -2
  119. package/src/icons/svg/richeditor/history/undo.svg +3 -2
  120. package/src/icons/svg/search-filled.svg +3 -0
  121. package/src/icons/svg/settings-filled.svg +3 -0
  122. package/src/icons/svg/slide-menu-filled.svg +1 -0
  123. package/src/icons/svg/switch-to-mention.svg +3 -0
  124. package/src/icons/svg/switch-to-text.svg +4 -0
  125. package/src/icons/svg/switch-to-widget.svg +4 -0
  126. package/src/icons/svg/type/date.svg +3 -2
  127. package/src/icons/svg/view-gallery.svg +4 -0
  128. package/src/images-gallery/images-gallery-fall-through-provider.tsx +11 -0
  129. package/src/images-gallery/images-gallery.tsx +257 -0
  130. package/src/images-gallery/zoom.tsx +123 -0
  131. package/src/images-gallery-2/images-gallery-2.tsx +442 -0
  132. package/src/images-gallery-2/slide-buttons.tsx +230 -0
  133. package/src/images-gallery-2/zoom.tsx +35 -0
  134. package/src/is-in-popup.ts +1 -1
  135. package/src/kbd.tsx +46 -0
  136. package/src/layout-styles.ts +21 -1
  137. package/src/lists/actions-menu-row-surface.tsx +3 -1
  138. package/src/lists/list-row-surface.tsx +7 -1
  139. package/src/mobile-keyboard-aware-popup.tsx +87 -0
  140. package/src/mobile-styles.ts +8 -0
  141. package/src/modal-menu/contexts/modal-menu-context.tsx +22 -0
  142. package/src/modal-menu/contexts/modal-submenu-context.tsx +16 -0
  143. package/src/modal-menu/index.tsx +14 -0
  144. package/src/modal-menu/modal-menu-content.tsx +68 -0
  145. package/src/modal-menu/modal-menu-group.tsx +10 -0
  146. package/src/modal-menu/modal-menu-item.tsx +45 -0
  147. package/src/modal-menu/modal-menu-label.tsx +24 -0
  148. package/src/modal-menu/modal-menu-root.tsx +57 -0
  149. package/src/modal-menu/modal-menu-separator.tsx +14 -0
  150. package/src/modal-menu/modal-menu-trigger.tsx +54 -0
  151. package/src/modal-menu/modal-submenu-content.tsx +49 -0
  152. package/src/modal-menu/modal-submenu-trigger.tsx +34 -0
  153. package/src/modal-menu/modal-submenu.tsx +17 -0
  154. package/src/notification-dot.tsx +16 -7
  155. package/src/online-users.tsx +3 -3
  156. package/src/palette.ts +1 -1
  157. package/src/platform-symbols.ts +9 -0
  158. package/src/platform.ts +2 -0
  159. package/src/popover/index.tsx +710 -0
  160. package/src/popover/mobile-popup-context.tsx +29 -0
  161. package/src/{popup → popover}/modifiers.tsx +25 -25
  162. package/src/{popup → popover}/popup-modifiers-context.ts +3 -3
  163. package/src/reactions/reaction-button.tsx +342 -135
  164. package/src/reactions/reaction-picker.tsx +51 -44
  165. package/src/reactions/reactions.tsx +11 -1
  166. package/src/reactions/tootltip.tsx +55 -0
  167. package/src/rich-text-embed-error.tsx +2 -1
  168. package/src/select/components/group-heading.tsx +8 -0
  169. package/src/select/components/menu-list-virtualized.tsx +6 -2
  170. package/src/select/components/option.tsx +4 -0
  171. package/src/select/index.tsx +8 -4
  172. package/src/select/select-control-settings-context.tsx +11 -2
  173. package/src/select/select-in-popover.tsx +30 -39
  174. package/src/select/styles.ts +21 -1
  175. package/src/tab-nav/tab-nav.tsx +36 -10
  176. package/src/toast/primitives.tsx +8 -1
  177. package/src/toggle-button/round-toggle-button.tsx +23 -0
  178. package/src/toggle-button/toggle-button-group.tsx +34 -0
  179. package/src/toggle-button/toggle-button.tsx +164 -0
  180. package/src/toggle.tsx +11 -3
  181. package/src/tooltip.tsx +29 -20
  182. package/src/type-badge.tsx +5 -2
  183. package/src/unit/styles.ts +2 -2
  184. package/src/unit/unit-with-tooltip.tsx +1 -1
  185. package/src/use-is-phone.tsx +50 -4
  186. package/src/use-is-support-hover.ts +1 -1
  187. package/src/use-on-screen-keyboard-data.tsx +66 -0
  188. package/src/workflow-progress-icon.tsx +16 -22
  189. package/src/popup/index.tsx +0 -383
  190. package/src/shortcut-badge.tsx +0 -29
  191. /package/src/{popup → popover}/popup-stack-context.tsx +0 -0
  192. /package/src/{popup → popover}/reference.ts +0 -0
  193. /package/src/{popup → popover}/styles.ts +0 -0
  194. /package/src/{popup → popover}/use-click-outside.ts +0 -0
package/src/avatar.tsx CHANGED
@@ -5,33 +5,7 @@ import {getDarkenColor, getObjectColorMemoized, textStyles, themeVars} from "./d
5
5
  import {FibermojiPlaceholder} from "./fibermoji-placeholder";
6
6
  import {getShiftStyle} from "./icons/get-shift-style";
7
7
  import {useFeatures} from "./features";
8
-
9
- const preservedNameEmojis = ["🤖", "👻", "🧮", "🪄", "🔌", "🔗", "🔒"];
10
-
11
- export const abbreviateName = (name?: string) => {
12
- if (name === undefined) {
13
- return "…";
14
- }
15
- if (preservedNameEmojis.includes(name)) {
16
- return name;
17
- }
18
- const filteredName = (name || "").replace(/[!~.\-@[\]]/g, "").trim();
19
- const match = filteredName.match(/\p{Letter}[\p{Letter} ]+/gu);
20
- const processedName = match ? match[0] : "";
21
- const parts = processedName.split(" ").filter((part) => part !== "");
22
- let result;
23
- if (parts.length === 1) {
24
- result = processedName.slice(0, 2);
25
- } else {
26
- result = parts
27
- .filter((part, index) => index < 2)
28
- .map((part) => {
29
- return part[0].toUpperCase();
30
- })
31
- .join("");
32
- }
33
- return result || "?";
34
- };
8
+ import {abbreviateName} from "./abbreviate-name";
35
9
 
36
10
  export const getContainerStyle = _.memoize((containerSize) => {
37
11
  return {
@@ -1,24 +1,8 @@
1
1
  import {css} from "@linaria/core";
2
- import {styled} from "@linaria/react";
3
- import cn from "classnames";
2
+ import {default as cn, default as cx} from "classnames";
4
3
  import {FC, ReactNode} from "react";
5
- import {getThemeValue, layout, opacity, border, space, textStyles, themeVars} from "./design-system";
6
- import {useTheme} from "./theme-provider";
7
-
8
- const axisItemStyle = css`
9
- ${{
10
- display: "grid",
11
- gridGap: space.s6,
12
- minHeight: layout.itemHeight,
13
- alignItems: "center",
14
- paddingLeft: space.s8,
15
- paddingRight: space.s8,
16
- borderRadius: border.radius6,
17
- width: "100%",
18
- ...textStyles.heading5,
19
- }}
20
- `;
21
-
4
+ import {CountBadge} from "./count-badge";
5
+ import {border, opacity, space, textStyles, themeVars} from "./design-system";
22
6
  const axisItemStyleX = css`
23
7
  grid-template-columns: auto 1fr auto;
24
8
  `;
@@ -31,11 +15,23 @@ const axisItemHighlightedStyle = css`
31
15
 
32
16
  const dimensionToItemStyle = {x: axisItemStyleX, y: axisItemStyleY};
33
17
 
18
+ const wrapperStyle = css`
19
+ ${textStyles.regular};
20
+ display: grid;
21
+ width: 100%;
22
+ grid-template-columns: 1fr auto;
23
+ gap: ${space.s6}px;
24
+ padding: ${space.s6}px;
25
+ `;
26
+
34
27
  const axisItemStyleCollapsed = css`
35
- ${{
36
- paddingRight: 0,
37
- width: `${layout.itemHeight + space.s8 * 2}px`,
38
- }}
28
+ writing-mode: vertical-rl;
29
+ display: flex;
30
+ position: sticky;
31
+ top: 0;
32
+ &.${wrapperStyle} {
33
+ padding-block: 0;
34
+ }
39
35
  `;
40
36
 
41
37
  function getAdditionalClassName({
@@ -56,33 +52,61 @@ function getAdditionalClassName({
56
52
  return dimensionToItemStyle[dimension];
57
53
  }
58
54
 
59
- const mainContainerWrapperStyle = {
60
- overflow: "hidden",
61
- whiteSpace: "nowrap",
62
- cursor: "pointer",
63
- textOverflow: "ellipsis",
64
- opacity: 1,
65
- };
66
- const mainContainerWrapperClassName = css`
67
- ${mainContainerWrapperStyle}
55
+ const mainContainerWrapperStyle = css`
56
+ overflow: hidden;
57
+ white-space: nowrap;
58
+ cursor: pointer;
59
+ text-overflow: ellipsis;
60
+ opacity: 1;
68
61
  `;
69
62
 
70
- const mainContainerWrapperCollapsedClassName = css`
71
- ${{
72
- ...mainContainerWrapperStyle,
73
- textOverflow: "ellipsis",
74
- opacity: opacity.opacity40,
75
- }}
63
+ const mainContainerWrapperCollapsedClassName = cx(
64
+ mainContainerWrapperStyle,
65
+ css`
66
+ opacity: ${opacity.opacity40};
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: flex-start;
70
+ gap: ${space.s12}px;
71
+ `
72
+ );
73
+
74
+ const collapsedTextStyle = css`
75
+ overflow: hidden;
76
+ white-space: nowrap;
77
+ text-overflow: ellipsis;
78
+ min-width: 0;
79
+ flex-shrink: 1;
76
80
  `;
77
81
 
78
82
  const leftContainerWrapperStyle = css`
79
83
  cursor: pointer;
80
84
  `;
81
85
 
82
- const StyledDiv = styled.div<{backgroundColor?: string}>`
86
+ export const leftMainContainerWrapperStyle = css``;
87
+
88
+ export const axisHeaderClassName = css`
89
+ cursor: pointer;
90
+ min-height: ${space.s36}px;
83
91
  display: flex;
92
+ justify-content: center;
84
93
  flex-direction: column;
85
- background-color: ${({backgroundColor = "transparent"}) => backgroundColor};
94
+ border-radius: ${border.radius6}px;
95
+ .right-container {
96
+ opacity: 0;
97
+ }
98
+ background-color: var(--board-bg, ${themeVars.boardBg});
99
+ &:hover {
100
+ background-color: ${themeVars.boardAxisBgHover};
101
+ z-index: 20;
102
+ & .${leftMainContainerWrapperStyle} {
103
+ background-color: transparent;
104
+ }
105
+ .right-container {
106
+ visibility: visible;
107
+ opacity: 1;
108
+ }
109
+ }
86
110
  `;
87
111
 
88
112
  interface AxisHeaderProps {
@@ -90,12 +114,12 @@ interface AxisHeaderProps {
90
114
  dimension: "x" | "y";
91
115
  collapsed?: boolean;
92
116
  highlighted?: boolean;
93
- showLeftContainerWhenCollapsed?: boolean;
94
117
  bottomContainer?: ReactNode;
95
118
  leftContainer?: ReactNode;
96
119
  rightContainer?: ReactNode;
97
120
  children: ReactNode;
98
121
  onCollapse?: () => void;
122
+ count?: number;
99
123
  }
100
124
 
101
125
  export const AxisHeader: FC<AxisHeaderProps> = ({
@@ -107,54 +131,90 @@ export const AxisHeader: FC<AxisHeaderProps> = ({
107
131
  bottomContainer,
108
132
  collapsed,
109
133
  highlighted,
110
- showLeftContainerWhenCollapsed,
111
134
  onCollapse,
135
+ count,
112
136
  }) => {
113
- const theme = useTheme();
114
- const backgroundColor = getThemeValue(theme.mode, {
115
- dark: themeVars.panelContentBg,
116
- light: themeVars.panelContentBg,
117
- });
137
+ const leftContainerWrapper = <div className={leftContainerWrapperStyle}>{leftContainer}</div>;
118
138
 
119
- const leftContainerWrapper = (
120
- <div onClick={onCollapse} className={leftContainerWrapperStyle}>
121
- {leftContainer}
139
+ const rightContainerWrapper = (
140
+ <div
141
+ className={cn(
142
+ "right-container",
143
+ css`
144
+ display: flex;
145
+ align-items: center;
146
+ `
147
+ )}
148
+ >
149
+ {rightContainer}
122
150
  </div>
123
151
  );
124
152
 
125
- const rightContainerWrapper = <div>{rightContainer}</div>;
126
-
127
153
  const mainContainerWrapper = (
128
- <div
129
- onClick={onCollapse}
130
- className={collapsed ? mainContainerWrapperCollapsedClassName : mainContainerWrapperClassName}
131
- >
132
- {children}
154
+ <div className={collapsed ? mainContainerWrapperCollapsedClassName : mainContainerWrapperStyle}>
155
+ {collapsed ? <div className={collapsedTextStyle}>{children}</div> : children}
156
+ {count !== undefined && collapsed && (
157
+ <CountBadge
158
+ count={count}
159
+ className={css`
160
+ writing-mode: horizontal-tb;
161
+ `}
162
+ />
163
+ )}
133
164
  </div>
134
165
  );
135
166
  return (
136
- <StyledDiv data-testid={`axis-header-${dimension}`} backgroundColor={backgroundColor} className={cn(className)}>
137
- <div
138
- className={cn(axisItemStyle, getAdditionalClassName({dimension, highlighted, collapsed}))}
139
- style={{
140
- background: highlighted ? themeVars.actionMenuHover : backgroundColor,
141
- }}
142
- >
143
- {collapsed ? (
144
- showLeftContainerWhenCollapsed ? (
145
- leftContainerWrapper
146
- ) : (
147
- mainContainerWrapper
148
- )
149
- ) : (
150
- <>
167
+ <div
168
+ data-testid={`axis-header-${dimension}`}
169
+ onClick={onCollapse}
170
+ className={cn(
171
+ className,
172
+ axisHeaderClassName,
173
+ dimension === "y" &&
174
+ css`
175
+ position: sticky;
176
+ left: 0;
177
+ display: inline-flex;
178
+ z-index: 3;
179
+ background-color: transparent;
180
+ `,
181
+ dimension === "y" &&
182
+ highlighted &&
183
+ css`
184
+ display: flex;
185
+ width: 100%;
186
+ `,
187
+ collapsed &&
188
+ dimension === "x" &&
189
+ css`
190
+ position: sticky;
191
+ top: 0;
192
+ z-index: 2;
193
+ background-color: transparent;
194
+ `
195
+ )}
196
+ >
197
+ <div className={cn(wrapperStyle, getAdditionalClassName({dimension, highlighted, collapsed}))}>
198
+ <>
199
+ <div
200
+ className={cn(
201
+ leftMainContainerWrapperStyle,
202
+ css`
203
+ display: grid;
204
+ grid-template-columns: auto 1fr;
205
+ gap: ${space.s8}px;
206
+ padding-inline: ${space.s4}px;
207
+ align-items: center;
208
+ `
209
+ )}
210
+ >
151
211
  {leftContainerWrapper}
152
212
  {mainContainerWrapper}
153
- {rightContainerWrapper}
154
- </>
155
- )}
213
+ </div>
214
+ {rightContainerWrapper}
215
+ </>
156
216
  </div>
157
217
  {bottomContainer}
158
- </StyledDiv>
218
+ </div>
159
219
  );
160
220
  };
package/src/box.tsx CHANGED
@@ -3,7 +3,7 @@ import {styled} from "@linaria/react";
3
3
  import cx from "classnames";
4
4
  import {CSSProperties, forwardRef, HTMLProps, ReactNode, Ref, useCallback, useMemo, useState} from "react";
5
5
  import {border, getLinearGradient, getOpacities, space, textStyles, themeVars, transition} from "./design-system";
6
- import {useClickOutside} from "./popup/use-click-outside";
6
+ import {useClickOutside} from "./popover/use-click-outside";
7
7
 
8
8
  export const getBg = (backgroundColors: string[]) => {
9
9
  if (backgroundColors) {
@@ -0,0 +1,78 @@
1
+ import {css, cx} from "@linaria/core";
2
+ import {themeVars, transition} from "./design-system";
3
+ import ArrowRight from "./icons/react/ArrowRight";
4
+ import {ComponentPropsWithoutRef, ElementType, forwardRef} from "react";
5
+ import More from "./icons/react/More";
6
+
7
+ export const Breadcrumb = ({...props}: React.ComponentProps<"nav">) => {
8
+ return <nav aria-label="breadcrumb" {...props} />;
9
+ };
10
+
11
+ const olReset = css`
12
+ margin: 0;
13
+ padding: 0;
14
+ list-style: none;
15
+ `;
16
+
17
+ const listCss = css`
18
+ display: flex;
19
+ align-items: center;
20
+ white-space: nowrap;
21
+ overflow: hidden;
22
+ text-overflow: ellipsis;
23
+ color: ${themeVars.colorTextButtonGhostNeutral};
24
+ `;
25
+
26
+ export const BreadcrumbList = ({className, ...props}: React.ComponentProps<"ol">) => {
27
+ return <ol className={cx(olReset, listCss, className)} {...props} />;
28
+ };
29
+
30
+ const itemCss = css`
31
+ display: flex;
32
+ align-items: center;
33
+ `;
34
+
35
+ export const BreadcrumbItem = forwardRef<HTMLLIElement, React.ComponentProps<"li">>(({className, ...props}, ref) => {
36
+ return <li ref={ref} className={cx(itemCss, className)} {...props} />;
37
+ });
38
+
39
+ const linkCss = css`
40
+ color: ${themeVars.colorTextButtonGhostNeutral};
41
+ &:hover {
42
+ color: ${themeVars.textColor};
43
+ }
44
+ transition: color ${transition};
45
+ `;
46
+
47
+ type BreadcrumbLinkProps<C extends ElementType = "a"> = {
48
+ as?: C;
49
+ className?: string;
50
+ } & ComponentPropsWithoutRef<C>;
51
+
52
+ export const BreadcrumbLink = <C extends ElementType = "a">({className, as, ...props}: BreadcrumbLinkProps<C>) => {
53
+ const Component = as || "a";
54
+ return <Component className={cx(linkCss, className)} {...props} />;
55
+ };
56
+
57
+ const liReset = css`
58
+ margin: 0;
59
+ padding: 0;
60
+ `;
61
+
62
+ export const BreadcrumbSeparator = ({children, className, ...props}: React.ComponentProps<"li">) => {
63
+ return (
64
+ <li role="presentation" aria-hidden="true" className={cx(liReset, className)} {...props}>
65
+ {children ?? <ArrowRight color={themeVars.colorTextButtonGhostNeutral} containerSize={16} iconSize={16} />}
66
+ </li>
67
+ );
68
+ };
69
+
70
+ export const BreadcrumbEllipsis = forwardRef<HTMLSpanElement, React.ComponentProps<"span">>(
71
+ ({className, ...props}, ref) => {
72
+ return (
73
+ <span ref={ref} role="presentation" aria-hidden="true" className={cx(className)} {...props}>
74
+ <More color={themeVars.colorTextButtonGhostNeutral} containerSize={16} iconSize={16} />
75
+ </span>
76
+ );
77
+ }
78
+ );
@@ -1,12 +1,15 @@
1
1
  import {forwardRef} from "react";
2
2
  import {IconButton, IconButtonProps} from "./icon-button";
3
3
  import MoreCompactIcon from "../icons/react/MoreCompact";
4
+ import MoreIcon from "../icons/react/More";
5
+ import {useIsPhone} from "../use-is-phone";
4
6
 
5
7
  export const ActionsButtonCompact = forwardRef<HTMLButtonElement, IconButtonProps>(
6
8
  function ActionsButtonCompactComponent({...rest}, ref) {
9
+ const isPhone = useIsPhone();
7
10
  return (
8
11
  <IconButton supportMobile={true} ref={ref} size="small" {...rest}>
9
- <MoreCompactIcon />
12
+ {isPhone ? <MoreIcon iconSize={20} /> : <MoreCompactIcon />}
10
13
  </IconButton>
11
14
  );
12
15
  }
@@ -3,7 +3,7 @@ import {forwardRef} from "react";
3
3
  import {themeVars} from "../design-system";
4
4
  import {iconColorVar} from "../icons/Icon";
5
5
 
6
- export type ButtonSize = "tiny" | "small" | "medium" | "large";
6
+ export type ButtonSize = "tiny" | "small" | "medium" | "large" | "xLarge";
7
7
  export type ButtonVariant = "solid" | "outline" | "soft" | "ghost";
8
8
  export type ButtonColor = "accent" | "neutral" | "error";
9
9
 
@@ -14,6 +14,8 @@ export type BaseButtonProps = {
14
14
  supportMobile?: boolean;
15
15
  } & React.ComponentPropsWithRef<"button">;
16
16
 
17
+ export const xLargeButtonHeight = 40;
18
+
17
19
  export const baseButton = css`
18
20
  position: relative;
19
21
  box-sizing: border-box;
@@ -32,8 +34,10 @@ export const baseButton = css`
32
34
 
33
35
  box-shadow: inset 0 0 0 1px var(--fibery-button-border-color);
34
36
 
35
- &:hover:not(:disabled) {
36
- background-color: var(--fibery-button-hover-color);
37
+ @media (any-hover: hover) {
38
+ &:hover:not(:disabled) {
39
+ background-color: var(--fibery-button-hover-color);
40
+ }
37
41
  }
38
42
  &:active {
39
43
  color: var(--fibery-button-text-active-color);
@@ -29,7 +29,7 @@ const buttonGroupDirection = {
29
29
  `,
30
30
  };
31
31
 
32
- const buttonGroup = css`
32
+ export const buttonGroup = css`
33
33
  display: flex;
34
34
  align-items: flex-start;
35
35
  `;
@@ -3,7 +3,7 @@ import {forwardRef} from "react";
3
3
  import {border, fontWeight, space, textStyles} from "../design-system";
4
4
  import {iconSizeVar} from "../icons/Icon";
5
5
  import SpinnerIcon from "../icons/react/Spinner";
6
- import {BaseButton, BaseButtonProps, ButtonSize} from "./base-button";
6
+ import {BaseButton, BaseButtonProps, ButtonSize, xLargeButtonHeight} from "./base-button";
7
7
  import {useIsSupportHardwareKeyboard} from "../use-is-support-hardware-keyboard";
8
8
  import {useIsPhone} from "../use-is-phone";
9
9
 
@@ -140,6 +140,37 @@ const buttonSize = {
140
140
  padding-right: ${space.s8 - space.s1}px;
141
141
  }
142
142
 
143
+ & > .${shortcutContainer} {
144
+ font-size: ${textStyles.regular.fontSize}px;
145
+ }
146
+ `,
147
+ xLarge: css`
148
+ font-size: ${textStyles.heading3.fontSize}px;
149
+ line-height: 20px;
150
+ letter-spacing: ${textStyles.heading3.letterSpacing};
151
+
152
+ border-radius: ${border.radius6}px;
153
+ min-height: ${xLargeButtonHeight}px;
154
+ padding: ${space.s6}px ${space.s12}px;
155
+ gap: ${space.s6}px;
156
+
157
+ ${iconSizeVar}: 24px;
158
+
159
+ &.${withIconStart} {
160
+ padding-left: ${space.s10}px;
161
+ padding-right: ${space.s12}px;
162
+ }
163
+
164
+ &.${withIconEnd} {
165
+ padding-left: ${space.s12}px;
166
+ padding-right: ${space.s10}px;
167
+ }
168
+
169
+ &.${withoutChildren} {
170
+ padding-left: ${space.s8 - space.s1}px;
171
+ padding-right: ${space.s8 - space.s1}px;
172
+ }
173
+
143
174
  & > .${shortcutContainer} {
144
175
  font-size: ${textStyles.regular.fontSize}px;
145
176
  }
@@ -174,6 +205,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
174
205
  ref={ref}
175
206
  disabled={disabled || pending}
176
207
  className={cx(
208
+ "notranslate",
177
209
  className,
178
210
  button,
179
211
  buttonSize[supportMobile && isPhone ? "large" : size],
@@ -3,7 +3,7 @@ import {forwardRef} from "react";
3
3
  import {border, space} from "../design-system";
4
4
  import {iconSizeVar} from "../icons/Icon";
5
5
  import Spinner from "../icons/react/Spinner";
6
- import {BaseButton, BaseButtonProps, ButtonSize} from "./base-button";
6
+ import {BaseButton, BaseButtonProps, ButtonSize, xLargeButtonHeight} from "./base-button";
7
7
  import {useIsPhone} from "../use-is-phone";
8
8
 
9
9
  export type IconButtonProps = {
@@ -52,6 +52,15 @@ export const iconButtonSizes = {
52
52
 
53
53
  ${iconSizeVar}: 18px;
54
54
  `,
55
+ xLarge: css`
56
+ padding: ${space.s6}px;
57
+
58
+ min-width: ${xLargeButtonHeight}px;
59
+ min-height: ${xLargeButtonHeight}px;
60
+ border-radius: ${border.radius6}px;
61
+
62
+ ${iconSizeVar}: 24px;
63
+ `,
55
64
  };
56
65
 
57
66
  export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(function IconButton(
@@ -21,6 +21,10 @@ const iconSize = {
21
21
  margin-left: -${space.s4}px;
22
22
  margin-right: -${space.s4}px;
23
23
  `,
24
+ xLarge: css`
25
+ margin-left: -${space.s4}px;
26
+ margin-right: -${space.s4}px;
27
+ `,
24
28
  };
25
29
 
26
30
  export type SelectButtonProps = {
@@ -7,6 +7,7 @@ import {getBg} from "./box";
7
7
  import {CardHiddenLink} from "./card-hidden-link";
8
8
  import {border, space, themeVars} from "./design-system";
9
9
  import {visuallyHidden} from "./styles-utils";
10
+ import {mobileRootSelector} from "./mobile-styles";
10
11
 
11
12
  export type CardSize =
12
13
  | ":card-size/pinned"
@@ -109,10 +110,7 @@ const cardClassName = css`
109
110
  flex-direction: column;
110
111
  flex-grow: 1;
111
112
  height: 100%;
112
- padding-left: ${space.s8}px;
113
- padding-right: ${space.s6}px;
114
- padding-top: ${space.s6}px;
115
- padding-bottom: ${space.s8}px;
113
+ padding: ${space.s8}px;
116
114
  gap: ${space.s6}px;
117
115
 
118
116
  & > div:empty:not(.${colorCodingClassName}) {
@@ -159,6 +157,11 @@ const listClassName = css`
159
157
  & > div.title-wrapper:has(a:empty) {
160
158
  display: none;
161
159
  }
160
+
161
+ ${mobileRootSelector} & {
162
+ gap: ${space.s8}px;
163
+ min-height: 36px;
164
+ }
162
165
  `;
163
166
 
164
167
  const timelineClassName = css`
@@ -244,7 +247,8 @@ const floatingStyles = {
244
247
  };
245
248
 
246
249
  const coverClassName = css`
247
- margin: ${-space.s4}px;
250
+ // box padding -1px to go below the outline
251
+ margin: ${-space.s5}px;
248
252
 
249
253
  &:empty {
250
254
  display: none;
@@ -252,7 +256,7 @@ const coverClassName = css`
252
256
  `;
253
257
 
254
258
  const coverWithContentClassName = css`
255
- border-bottom: ${themeVars.separators.opacity5};
259
+ border-bottom: ${themeVars.shortcutBorderColor};
256
260
  margin-bottom: 0;
257
261
  `;
258
262
 
package/src/checkbox.tsx CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  } from "react";
15
15
  import {colors, getDarkenColor, getOpacities, layout, space, textStyles, ThemeColors, themeVars} from "./design-system";
16
16
  import {smallHtmlStylesClass} from "./html-styles";
17
+ import {mobileRootSelector} from "./mobile-styles";
17
18
 
18
19
  const checkboxColor = `--fibery-checkbox-color`;
19
20
  const checkboxColorVar = `var(${checkboxColor})`;
@@ -36,6 +37,10 @@ const backgroundStyle = css`
36
37
  box-shadow: 0 0 0 1.5px ${borderColorVar};
37
38
  background-color: ${themeVars.panelBg};
38
39
 
40
+ ${mobileRootSelector} & {
41
+ box-shadow: 0 0 0 1.6px ${borderColorVar};
42
+ }
43
+
39
44
  .${smallHtmlStylesClass} & {
40
45
  width: ${layout.checkboxSize - 2}px;
41
46
  height: ${layout.checkboxSize - 2}px;
@@ -53,6 +58,9 @@ const checkboxRootStyle = css`
53
58
  & input[type="checkbox"]:checked + .${backgroundStyle} {
54
59
  background-color: ${checkboxColorVar};
55
60
  box-shadow: 0 0 0 1.5px ${checkboxColorVar} !important;
61
+ ${mobileRootSelector} & {
62
+ box-shadow: 0 0 0 1.6px ${checkboxColorVar} !important;
63
+ }
56
64
  }
57
65
 
58
66
  & input[type="checkbox"]:indeterminate + .${backgroundStyle} {
@@ -66,15 +74,24 @@ const checkboxRootStyle = css`
66
74
  &:hover input[type="checkbox"]:checked:not(:disabled) + .${backgroundStyle} {
67
75
  background-color: ${darkenColorVar};
68
76
  box-shadow: 0 0 0 1.5px ${darkenColorVar};
77
+ ${mobileRootSelector} & {
78
+ box-shadow: 0 0 0 1.6px ${darkenColorVar};
79
+ }
69
80
  }
70
81
 
71
82
  &:hover input[type="checkbox"]:checked:focus:not(:disabled) + .${backgroundStyle} {
72
83
  background-color: ${darkenColorVar};
73
84
  box-shadow: 0 0 0 1.5px ${darkenColorVar}, 0 0 0 4px ${focusColorVar};
85
+ ${mobileRootSelector} & {
86
+ box-shadow: 0 0 0 1.6px ${darkenColorVar}, 0 0 0 4px ${focusColorVar};
87
+ }
74
88
  }
75
89
 
76
90
  & input[type="checkbox"]:focus + .${backgroundStyle} {
77
91
  box-shadow: 0 0 0 1.5px ${checkboxColorVar}, 0 0 0 4px ${focusColorVar};
92
+ ${mobileRootSelector} & {
93
+ box-shadow: 0 0 0 1.6px ${checkboxColorVar}, 0 0 0 4px ${focusColorVar};
94
+ }
78
95
  }
79
96
 
80
97
  .${smallHtmlStylesClass} & {
@@ -25,6 +25,7 @@ type Props = {
25
25
  children: ReactNode;
26
26
  badge?: ReactNode;
27
27
  keepChildren?: boolean;
28
+ className?: string;
28
29
  };
29
30
 
30
31
  export const CollapsibleSection = ({
@@ -35,6 +36,7 @@ export const CollapsibleSection = ({
35
36
  onCollapsedChange,
36
37
  children,
37
38
  badge,
39
+ className,
38
40
  }: Props) => {
39
41
  const [isCollapsed, setIsCollapsed] = useControllableState({
40
42
  value: collapsed,
@@ -71,7 +73,7 @@ export const CollapsibleSection = ({
71
73
  const regularHeader = label && <div className={headerCss}>{label}</div>;
72
74
 
73
75
  return (
74
- <div>
76
+ <div className={className}>
75
77
  {collapsible ? collapsibleHeader : regularHeader}
76
78
  <div style={{display: collapsible && isCollapsed ? "none" : "block"}}>{children}</div>
77
79
  </div>
@@ -66,6 +66,7 @@ const iconSizes = {
66
66
  medium: 18,
67
67
  large: 20,
68
68
  huge: 22,
69
+ xLarge: 22,
69
70
  };
70
71
 
71
72
  type SwatchProps = {