@xsolla/xui-button 0.190.0 → 0.192.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 -2
- package/native/index.d.ts +25 -2
- package/native/index.js +43 -7
- package/native/index.js.map +1 -1
- package/native/index.mjs +43 -7
- package/native/index.mjs.map +1 -1
- package/package.json +4 -4
- package/web/index.d.mts +25 -2
- package/web/index.d.ts +25 -2
- package/web/index.js +43 -7
- package/web/index.js.map +1 -1
- package/web/index.mjs +43 -7
- package/web/index.mjs.map +1 -1
package/web/index.d.ts
CHANGED
|
@@ -170,8 +170,15 @@ interface IconButtonProps extends ThemeOverrideProps {
|
|
|
170
170
|
declare const IconButton: React.FC<IconButtonProps>;
|
|
171
171
|
|
|
172
172
|
interface FlexButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "type"> {
|
|
173
|
-
/**
|
|
174
|
-
|
|
173
|
+
/**
|
|
174
|
+
* Button label. Omit for icon-only buttons (provide `aria-label`).
|
|
175
|
+
*
|
|
176
|
+
* An icon may also be passed directly as `children` instead of via
|
|
177
|
+
* `iconLeft`/`iconRight`. When `children` carries no text, the button is
|
|
178
|
+
* treated as icon-only and renders as a square sized from the design-system
|
|
179
|
+
* height token for `size`.
|
|
180
|
+
*/
|
|
181
|
+
children?: ReactNode;
|
|
175
182
|
/** Visual variant of the button */
|
|
176
183
|
variant?: "brand" | "primary" | "secondary" | "tertiary" | "brandExtra" | "inverse";
|
|
177
184
|
/** Size of the button */
|
|
@@ -190,6 +197,9 @@ interface FlexButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElem
|
|
|
190
197
|
* The component applies padding via an inline style, which overrides any CSS
|
|
191
198
|
* class or `style` prop a consumer passes, so this prop is the supported way
|
|
192
199
|
* to render a zero-padding FlexButton (e.g. an inline text action).
|
|
200
|
+
*
|
|
201
|
+
* Icon-only buttons keep their square dimensions when `noPadding` is set —
|
|
202
|
+
* only the inner padding is removed.
|
|
193
203
|
* @default false
|
|
194
204
|
*/
|
|
195
205
|
noPadding?: boolean;
|
|
@@ -224,6 +234,19 @@ interface FlexButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElem
|
|
|
224
234
|
*
|
|
225
235
|
* Renders as a semantic `<button>` element with full ARIA support.
|
|
226
236
|
*
|
|
237
|
+
* ## Icon-only buttons
|
|
238
|
+
*
|
|
239
|
+
* A FlexButton is icon-only when it has no text label and an icon is supplied
|
|
240
|
+
* either as `children` or via `iconLeft`/`iconRight`. Icon-only buttons render
|
|
241
|
+
* as a square whose side equals `theme.sizing.flexButton(size).height`, so they
|
|
242
|
+
* line up with the Modal header icon slots (36x36 at `size="xl"`).
|
|
243
|
+
*
|
|
244
|
+
* ```tsx
|
|
245
|
+
* <FlexButton variant="secondary" size="xl" aria-label="Go back">
|
|
246
|
+
* <BackwardAlt variant="line" />
|
|
247
|
+
* </FlexButton>
|
|
248
|
+
* ```
|
|
249
|
+
*
|
|
227
250
|
* ## Accessibility Features
|
|
228
251
|
*
|
|
229
252
|
* - **Semantic HTML**: Renders as a native `<button>` element
|
package/web/index.js
CHANGED
|
@@ -871,9 +871,27 @@ var IconButton = ({
|
|
|
871
871
|
IconButton.displayName = "IconButton";
|
|
872
872
|
|
|
873
873
|
// src/FlexButton.tsx
|
|
874
|
-
var import_react5 = require("react");
|
|
874
|
+
var import_react5 = __toESM(require("react"));
|
|
875
875
|
var import_xui_core3 = require("@xsolla/xui-core");
|
|
876
876
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
877
|
+
var FLEX_BUTTON_PADDING = 4;
|
|
878
|
+
var hasVisibleLabel = (node) => {
|
|
879
|
+
if (node == null || node === false || node === true) return false;
|
|
880
|
+
if (typeof node === "string") return node.trim().length > 0;
|
|
881
|
+
if (typeof node === "number") return true;
|
|
882
|
+
if (Array.isArray(node)) return node.some(hasVisibleLabel);
|
|
883
|
+
if (import_react5.default.isValidElement(node)) {
|
|
884
|
+
const { children: elementChildren } = node.props ?? {};
|
|
885
|
+
return hasVisibleLabel(elementChildren);
|
|
886
|
+
}
|
|
887
|
+
return true;
|
|
888
|
+
};
|
|
889
|
+
var hasRenderableContent = (node) => {
|
|
890
|
+
if (node == null || node === false || node === true) return false;
|
|
891
|
+
if (typeof node === "string") return node.trim().length > 0;
|
|
892
|
+
if (Array.isArray(node)) return node.some(hasRenderableContent);
|
|
893
|
+
return true;
|
|
894
|
+
};
|
|
877
895
|
var ICON_SIZES = {
|
|
878
896
|
xs: 12,
|
|
879
897
|
sm: 14,
|
|
@@ -1073,6 +1091,10 @@ var FlexButton = ({
|
|
|
1073
1091
|
const fontSize = FONT_SIZES[size];
|
|
1074
1092
|
const borderRadius = BORDER_RADIUS[size];
|
|
1075
1093
|
const lineHeight = LINE_HEIGHTS[size];
|
|
1094
|
+
const showTextLabel = hasVisibleLabel(children);
|
|
1095
|
+
const hasIconChildren = !showTextLabel && hasRenderableContent(children);
|
|
1096
|
+
const isIconOnly = !loading && !showTextLabel && Boolean(iconLeft || iconRight || hasIconChildren);
|
|
1097
|
+
const iconOnlyHitArea = theme.sizing.flexButton(size).height;
|
|
1076
1098
|
const handleMouseEnter = () => {
|
|
1077
1099
|
if (!isDisabled) {
|
|
1078
1100
|
isMouseOverRef.current = true;
|
|
@@ -1139,8 +1161,9 @@ var FlexButton = ({
|
|
|
1139
1161
|
display: "inline-flex",
|
|
1140
1162
|
alignItems: "center",
|
|
1141
1163
|
justifyContent: "center",
|
|
1142
|
-
gap: "2px",
|
|
1143
|
-
|
|
1164
|
+
gap: isIconOnly ? 0 : "2px",
|
|
1165
|
+
boxSizing: "border-box",
|
|
1166
|
+
padding: noPadding ? "0px" : `${FLEX_BUTTON_PADDING}px`,
|
|
1144
1167
|
backgroundColor: loading ? "transparent" : colors.bg,
|
|
1145
1168
|
color: colors.text,
|
|
1146
1169
|
border: "none",
|
|
@@ -1149,18 +1172,30 @@ var FlexButton = ({
|
|
|
1149
1172
|
cursor: isDisabled ? "not-allowed" : "pointer",
|
|
1150
1173
|
fontSize: `${fontSize}px`,
|
|
1151
1174
|
fontWeight: 500,
|
|
1152
|
-
lineHeight,
|
|
1175
|
+
lineHeight: isIconOnly ? 0 : lineHeight,
|
|
1153
1176
|
fontFamily: "inherit",
|
|
1154
1177
|
transition: "background-color 100ms ease-in-out, color 100ms ease-in-out, box-shadow 100ms ease-in-out",
|
|
1155
1178
|
outline: "none",
|
|
1156
1179
|
boxShadow: combinedBoxShadow,
|
|
1157
|
-
opacity: isDisabled && !loading ? 0.6 : 1
|
|
1180
|
+
opacity: isDisabled && !loading ? 0.6 : 1,
|
|
1181
|
+
...isIconOnly && {
|
|
1182
|
+
width: iconOnlyHitArea,
|
|
1183
|
+
height: iconOnlyHitArea,
|
|
1184
|
+
minWidth: iconOnlyHitArea,
|
|
1185
|
+
minHeight: iconOnlyHitArea,
|
|
1186
|
+
flexShrink: 0
|
|
1187
|
+
}
|
|
1158
1188
|
};
|
|
1159
1189
|
const contentStyle = {
|
|
1160
1190
|
display: "flex",
|
|
1161
1191
|
alignItems: "center",
|
|
1162
1192
|
justifyContent: "center",
|
|
1163
|
-
gap: "2px"
|
|
1193
|
+
gap: isIconOnly ? 0 : "2px",
|
|
1194
|
+
...isIconOnly && {
|
|
1195
|
+
width: "100%",
|
|
1196
|
+
height: "100%",
|
|
1197
|
+
lineHeight: 0
|
|
1198
|
+
}
|
|
1164
1199
|
};
|
|
1165
1200
|
const spinnerStyle = {
|
|
1166
1201
|
display: "flex",
|
|
@@ -1199,7 +1234,8 @@ var FlexButton = ({
|
|
|
1199
1234
|
"data-testid": testID || "flex-button",
|
|
1200
1235
|
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: contentStyle, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: spinnerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Spinner, { size: spinnerSize, color: spinnerColor }) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1201
1236
|
iconLeft && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { size: iconSize, color: colors.text, children: iconLeft }),
|
|
1202
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children }),
|
|
1237
|
+
showTextLabel && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children }),
|
|
1238
|
+
hasIconChildren && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { size: iconSize, color: colors.text, children }),
|
|
1203
1239
|
iconRight && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { size: iconSize, color: colors.text, children: iconRight })
|
|
1204
1240
|
] }) })
|
|
1205
1241
|
}
|