@xsolla/xui-button 0.216.1 → 0.217.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/native/index.d.mts +25 -3
- package/native/index.d.ts +25 -3
- package/native/index.js +10 -33
- package/native/index.js.map +1 -1
- package/native/index.mjs +10 -33
- package/native/index.mjs.map +1 -1
- package/package.json +4 -4
- package/web/index.d.mts +25 -3
- package/web/index.d.ts +25 -3
- package/web/index.js +10 -33
- package/web/index.js.map +1 -1
- package/web/index.mjs +10 -33
- package/web/index.mjs.map +1 -1
package/native/index.d.mts
CHANGED
|
@@ -183,7 +183,13 @@ interface FlexButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElem
|
|
|
183
183
|
variant?: "brand" | "primary" | "secondary" | "tertiary" | "brandExtra" | "inverse";
|
|
184
184
|
/** Size of the button */
|
|
185
185
|
size?: "xl" | "lg" | "md" | "sm" | "xs";
|
|
186
|
-
/**
|
|
186
|
+
/**
|
|
187
|
+
* Whether to show background fill.
|
|
188
|
+
*
|
|
189
|
+
* This also drives the button's frame padding: a filled button is padded per
|
|
190
|
+
* size ({@link BACKGROUND_PADDING}), while an unfilled one renders flush so
|
|
191
|
+
* it sits inline with surrounding text (XUITSD-86).
|
|
192
|
+
*/
|
|
187
193
|
background?: boolean;
|
|
188
194
|
/**
|
|
189
195
|
* Whether to show the hover/press background color.
|
|
@@ -198,6 +204,9 @@ interface FlexButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElem
|
|
|
198
204
|
* class or `style` prop a consumer passes, so this prop is the supported way
|
|
199
205
|
* to render a zero-padding FlexButton (e.g. an inline text action).
|
|
200
206
|
*
|
|
207
|
+
* Only meaningful together with `background` — an unfilled FlexButton already
|
|
208
|
+
* renders flush at every size, so `noPadding` is a no-op there (XUITSD-86).
|
|
209
|
+
*
|
|
201
210
|
* Icon-only buttons keep their square dimensions when `noPadding` is set —
|
|
202
211
|
* only the inner padding is removed.
|
|
203
212
|
* @default false
|
|
@@ -239,12 +248,22 @@ declare const getFlexButtonBoxSize: (size?: NonNullable<FlexButtonProps["size"]>
|
|
|
239
248
|
*
|
|
240
249
|
* Renders as a semantic `<button>` element with full ARIA support.
|
|
241
250
|
*
|
|
251
|
+
* ## Frame padding
|
|
252
|
+
*
|
|
253
|
+
* Padding follows the `background` prop. A filled button (`background`) is
|
|
254
|
+
* padded per size — 2px at `xs`/`sm`/`md`, 4px at `lg`/`xl` — while an unfilled
|
|
255
|
+
* one renders flush on all four sides so it flows inline with surrounding text.
|
|
256
|
+
* `noPadding` strips the padding from a filled button; on an unfilled one there
|
|
257
|
+
* is nothing left to strip (XUITSD-86).
|
|
258
|
+
*
|
|
242
259
|
* ## Icon-only buttons
|
|
243
260
|
*
|
|
244
261
|
* A FlexButton is icon-only when it has no text label and an icon is supplied
|
|
245
262
|
* either as `children` or via `iconLeft`/`iconRight`. Icon-only buttons render
|
|
246
263
|
* as a square whose side equals `theme.sizing.flexButton(size).height`, so they
|
|
247
|
-
* line up with the Modal header icon slots (36x36 at `size="xl"`).
|
|
264
|
+
* line up with the Modal header icon slots (36x36 at `size="xl"`). The square is
|
|
265
|
+
* independent of the padding above, so an unfilled icon-only button keeps its
|
|
266
|
+
* hit area and simply centres the icon inside it.
|
|
248
267
|
*
|
|
249
268
|
* ```tsx
|
|
250
269
|
* <FlexButton variant="secondary" size="xl" aria-label="Go back">
|
|
@@ -257,7 +276,10 @@ declare const getFlexButtonBoxSize: (size?: NonNullable<FlexButtonProps["size"]>
|
|
|
257
276
|
* - **Semantic HTML**: Renders as a native `<button>` element
|
|
258
277
|
* - **Keyboard Navigation**: Focusable via Tab, activated with Enter or Space
|
|
259
278
|
* - **ARIA States**: Properly announces disabled and loading states
|
|
260
|
-
* - **Focus Indicator**:
|
|
279
|
+
* - **Focus Indicator**: The browser's native `:focus-visible` ring. The design
|
|
280
|
+
* system specifies no focus treatment for FlexButton (XUITSD-61), so the
|
|
281
|
+
* component paints none of its own and does not suppress the UA outline —
|
|
282
|
+
* which keeps a keyboard-only indicator without drawing a ring on click.
|
|
261
283
|
* - **Screen Reader Support**: Announces button label, state, and any associated descriptions
|
|
262
284
|
*/
|
|
263
285
|
declare const FlexButton: React.ForwardRefExoticComponent<FlexButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
package/native/index.d.ts
CHANGED
|
@@ -183,7 +183,13 @@ interface FlexButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElem
|
|
|
183
183
|
variant?: "brand" | "primary" | "secondary" | "tertiary" | "brandExtra" | "inverse";
|
|
184
184
|
/** Size of the button */
|
|
185
185
|
size?: "xl" | "lg" | "md" | "sm" | "xs";
|
|
186
|
-
/**
|
|
186
|
+
/**
|
|
187
|
+
* Whether to show background fill.
|
|
188
|
+
*
|
|
189
|
+
* This also drives the button's frame padding: a filled button is padded per
|
|
190
|
+
* size ({@link BACKGROUND_PADDING}), while an unfilled one renders flush so
|
|
191
|
+
* it sits inline with surrounding text (XUITSD-86).
|
|
192
|
+
*/
|
|
187
193
|
background?: boolean;
|
|
188
194
|
/**
|
|
189
195
|
* Whether to show the hover/press background color.
|
|
@@ -198,6 +204,9 @@ interface FlexButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElem
|
|
|
198
204
|
* class or `style` prop a consumer passes, so this prop is the supported way
|
|
199
205
|
* to render a zero-padding FlexButton (e.g. an inline text action).
|
|
200
206
|
*
|
|
207
|
+
* Only meaningful together with `background` — an unfilled FlexButton already
|
|
208
|
+
* renders flush at every size, so `noPadding` is a no-op there (XUITSD-86).
|
|
209
|
+
*
|
|
201
210
|
* Icon-only buttons keep their square dimensions when `noPadding` is set —
|
|
202
211
|
* only the inner padding is removed.
|
|
203
212
|
* @default false
|
|
@@ -239,12 +248,22 @@ declare const getFlexButtonBoxSize: (size?: NonNullable<FlexButtonProps["size"]>
|
|
|
239
248
|
*
|
|
240
249
|
* Renders as a semantic `<button>` element with full ARIA support.
|
|
241
250
|
*
|
|
251
|
+
* ## Frame padding
|
|
252
|
+
*
|
|
253
|
+
* Padding follows the `background` prop. A filled button (`background`) is
|
|
254
|
+
* padded per size — 2px at `xs`/`sm`/`md`, 4px at `lg`/`xl` — while an unfilled
|
|
255
|
+
* one renders flush on all four sides so it flows inline with surrounding text.
|
|
256
|
+
* `noPadding` strips the padding from a filled button; on an unfilled one there
|
|
257
|
+
* is nothing left to strip (XUITSD-86).
|
|
258
|
+
*
|
|
242
259
|
* ## Icon-only buttons
|
|
243
260
|
*
|
|
244
261
|
* A FlexButton is icon-only when it has no text label and an icon is supplied
|
|
245
262
|
* either as `children` or via `iconLeft`/`iconRight`. Icon-only buttons render
|
|
246
263
|
* as a square whose side equals `theme.sizing.flexButton(size).height`, so they
|
|
247
|
-
* line up with the Modal header icon slots (36x36 at `size="xl"`).
|
|
264
|
+
* line up with the Modal header icon slots (36x36 at `size="xl"`). The square is
|
|
265
|
+
* independent of the padding above, so an unfilled icon-only button keeps its
|
|
266
|
+
* hit area and simply centres the icon inside it.
|
|
248
267
|
*
|
|
249
268
|
* ```tsx
|
|
250
269
|
* <FlexButton variant="secondary" size="xl" aria-label="Go back">
|
|
@@ -257,7 +276,10 @@ declare const getFlexButtonBoxSize: (size?: NonNullable<FlexButtonProps["size"]>
|
|
|
257
276
|
* - **Semantic HTML**: Renders as a native `<button>` element
|
|
258
277
|
* - **Keyboard Navigation**: Focusable via Tab, activated with Enter or Space
|
|
259
278
|
* - **ARIA States**: Properly announces disabled and loading states
|
|
260
|
-
* - **Focus Indicator**:
|
|
279
|
+
* - **Focus Indicator**: The browser's native `:focus-visible` ring. The design
|
|
280
|
+
* system specifies no focus treatment for FlexButton (XUITSD-61), so the
|
|
281
|
+
* component paints none of its own and does not suppress the UA outline —
|
|
282
|
+
* which keeps a keyboard-only indicator without drawing a ring on click.
|
|
261
283
|
* - **Screen Reader Support**: Announces button label, state, and any associated descriptions
|
|
262
284
|
*/
|
|
263
285
|
declare const FlexButton: React.ForwardRefExoticComponent<FlexButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
package/native/index.js
CHANGED
|
@@ -889,7 +889,13 @@ var SPINNER_SIZES = {
|
|
|
889
889
|
lg: 18,
|
|
890
890
|
xl: 20
|
|
891
891
|
};
|
|
892
|
-
var
|
|
892
|
+
var BACKGROUND_PADDING = {
|
|
893
|
+
xs: 2,
|
|
894
|
+
sm: 2,
|
|
895
|
+
md: 2,
|
|
896
|
+
lg: 4,
|
|
897
|
+
xl: 4
|
|
898
|
+
};
|
|
893
899
|
var hasVisibleLabel = (node) => {
|
|
894
900
|
if (node == null || node === false || node === true) return false;
|
|
895
901
|
if (typeof node === "string") return node.trim().length > 0;
|
|
@@ -966,7 +972,6 @@ var FlexButton = (0, import_react4.forwardRef)(
|
|
|
966
972
|
}, ref) => {
|
|
967
973
|
const { theme } = (0, import_xui_core3.useResolvedTheme)({ themeMode, themeProductContext });
|
|
968
974
|
const [state, setState] = (0, import_react4.useState)("default");
|
|
969
|
-
const [isFocused, setIsFocused] = (0, import_react4.useState)(false);
|
|
970
975
|
const isMouseOverRef = (0, import_react4.useRef)(false);
|
|
971
976
|
const isDisabled = disabled || loading;
|
|
972
977
|
const getVariantColors = (currentState) => {
|
|
@@ -1065,18 +1070,6 @@ var FlexButton = (0, import_react4.forwardRef)(
|
|
|
1065
1070
|
};
|
|
1066
1071
|
}
|
|
1067
1072
|
};
|
|
1068
|
-
const getFocusRingColor = () => {
|
|
1069
|
-
switch (variant) {
|
|
1070
|
-
case "brand":
|
|
1071
|
-
return theme.colors.overlay.brand;
|
|
1072
|
-
case "brandExtra":
|
|
1073
|
-
return theme.colors.overlay.brandExtra;
|
|
1074
|
-
case "inverse":
|
|
1075
|
-
return "rgba(255, 255, 255, 0.3)";
|
|
1076
|
-
default:
|
|
1077
|
-
return theme.colors.overlay.mono;
|
|
1078
|
-
}
|
|
1079
|
-
};
|
|
1080
1073
|
const getSpinnerColor = () => {
|
|
1081
1074
|
switch (variant) {
|
|
1082
1075
|
case "brand":
|
|
@@ -1096,13 +1089,13 @@ var FlexButton = (0, import_react4.forwardRef)(
|
|
|
1096
1089
|
}
|
|
1097
1090
|
};
|
|
1098
1091
|
const colors = getVariantColors(state);
|
|
1099
|
-
const focusRingColor = getFocusRingColor();
|
|
1100
1092
|
const spinnerColor = getSpinnerColor();
|
|
1101
1093
|
const iconSize = ICON_SIZES[size];
|
|
1102
1094
|
const spinnerSize = SPINNER_SIZES[size];
|
|
1103
1095
|
const fontSize = FONT_SIZES[size];
|
|
1104
1096
|
const borderRadius = BORDER_RADIUS[size];
|
|
1105
1097
|
const lineHeight = LINE_HEIGHTS[size];
|
|
1098
|
+
const framePadding = background ? BACKGROUND_PADDING[size] : 0;
|
|
1106
1099
|
const showTextLabel = hasVisibleLabel(children);
|
|
1107
1100
|
const hasIconChildren = !showTextLabel && hasRenderableContent(children);
|
|
1108
1101
|
const isIconOnly = !loading && !showTextLabel && Boolean(iconLeft || iconRight || hasIconChildren);
|
|
@@ -1129,14 +1122,6 @@ var FlexButton = (0, import_react4.forwardRef)(
|
|
|
1129
1122
|
setState(isMouseOverRef.current ? "hover" : "default");
|
|
1130
1123
|
}
|
|
1131
1124
|
};
|
|
1132
|
-
const handleFocus = () => {
|
|
1133
|
-
if (!isDisabled) {
|
|
1134
|
-
setIsFocused(true);
|
|
1135
|
-
}
|
|
1136
|
-
};
|
|
1137
|
-
const handleBlur = () => {
|
|
1138
|
-
setIsFocused(false);
|
|
1139
|
-
};
|
|
1140
1125
|
const handleClick = (event) => {
|
|
1141
1126
|
if (isDisabled) return;
|
|
1142
1127
|
if (onPress) {
|
|
@@ -1164,18 +1149,13 @@ var FlexButton = (0, import_react4.forwardRef)(
|
|
|
1164
1149
|
}
|
|
1165
1150
|
};
|
|
1166
1151
|
const borderShadow = colors.border ? `inset 0 0 0 1px ${colors.border}` : void 0;
|
|
1167
|
-
const focusShadow = isFocused && !isDisabled ? `0 0 0 2px ${focusRingColor}` : void 0;
|
|
1168
|
-
const boxShadows = [];
|
|
1169
|
-
if (borderShadow) boxShadows.push(borderShadow);
|
|
1170
|
-
if (focusShadow) boxShadows.push(focusShadow);
|
|
1171
|
-
const combinedBoxShadow = boxShadows.length > 0 ? boxShadows.join(", ") : "none";
|
|
1172
1152
|
const buttonStyle = {
|
|
1173
1153
|
display: "inline-flex",
|
|
1174
1154
|
alignItems: "center",
|
|
1175
1155
|
justifyContent: "center",
|
|
1176
1156
|
gap: isIconOnly ? 0 : "2px",
|
|
1177
1157
|
boxSizing: "border-box",
|
|
1178
|
-
padding: noPadding ? "0px" : `${
|
|
1158
|
+
padding: noPadding ? "0px" : `${framePadding}px`,
|
|
1179
1159
|
backgroundColor: loading ? "transparent" : colors.bg,
|
|
1180
1160
|
color: colors.text,
|
|
1181
1161
|
border: "none",
|
|
@@ -1187,8 +1167,7 @@ var FlexButton = (0, import_react4.forwardRef)(
|
|
|
1187
1167
|
lineHeight: isIconOnly ? 0 : lineHeight,
|
|
1188
1168
|
fontFamily: "inherit",
|
|
1189
1169
|
transition: "background-color 100ms ease-in-out, color 100ms ease-in-out, box-shadow 100ms ease-in-out",
|
|
1190
|
-
|
|
1191
|
-
boxShadow: combinedBoxShadow,
|
|
1170
|
+
boxShadow: borderShadow ?? "none",
|
|
1192
1171
|
...isIconOnly && {
|
|
1193
1172
|
width: iconOnlyHitArea,
|
|
1194
1173
|
height: iconOnlyHitArea,
|
|
@@ -1231,8 +1210,6 @@ var FlexButton = (0, import_react4.forwardRef)(
|
|
|
1231
1210
|
onMouseUp: handleMouseUp,
|
|
1232
1211
|
onKeyDown: handleKeyDown,
|
|
1233
1212
|
onKeyUp: handleKeyUp,
|
|
1234
|
-
onFocus: handleFocus,
|
|
1235
|
-
onBlur: handleBlur,
|
|
1236
1213
|
"aria-label": computedAriaLabel,
|
|
1237
1214
|
"aria-busy": loading || void 0,
|
|
1238
1215
|
"aria-disabled": isDisabled || void 0,
|