@tinybigui/react 0.4.2 → 0.5.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/dist/index.cjs +404 -146
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +143 -99
- package/dist/index.d.ts +143 -99
- package/dist/index.js +404 -146
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1113,81 +1113,113 @@ var IconButtonHeadless = forwardRef(
|
|
|
1113
1113
|
tabIndex = 0,
|
|
1114
1114
|
onMouseDown,
|
|
1115
1115
|
type,
|
|
1116
|
-
|
|
1116
|
+
isSelected,
|
|
1117
|
+
isToggle = false,
|
|
1118
|
+
isDisabled = false,
|
|
1117
1119
|
"aria-label": ariaLabel,
|
|
1118
1120
|
title,
|
|
1119
1121
|
...props
|
|
1120
1122
|
}, forwardedRef) => {
|
|
1121
1123
|
const internalRef = useRef(null);
|
|
1122
1124
|
const ref = forwardedRef ?? internalRef;
|
|
1123
|
-
const { buttonProps } = useButton(
|
|
1125
|
+
const { buttonProps, isPressed } = useButton(
|
|
1124
1126
|
{
|
|
1125
1127
|
...props,
|
|
1126
|
-
// Ensure element type is 'button' for proper semantics
|
|
1127
1128
|
elementType: "button",
|
|
1128
|
-
|
|
1129
|
-
|
|
1129
|
+
"aria-label": ariaLabel,
|
|
1130
|
+
isDisabled
|
|
1130
1131
|
},
|
|
1131
1132
|
ref
|
|
1132
1133
|
);
|
|
1134
|
+
const { isHovered, hoverProps } = useHover({ isDisabled });
|
|
1135
|
+
const { isFocusVisible, focusProps } = useFocusRing();
|
|
1133
1136
|
const domProps = filterDOMProps(props);
|
|
1134
|
-
const mergedProps = mergeProps(
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
+
const mergedProps = mergeProps(buttonProps, hoverProps, focusProps, domProps, {
|
|
1138
|
+
tabIndex,
|
|
1139
|
+
className,
|
|
1140
|
+
onMouseDown,
|
|
1141
|
+
type: type ?? "button",
|
|
1142
|
+
...title && { title },
|
|
1143
|
+
// aria-pressed only when acting as a toggle button
|
|
1144
|
+
...isToggle && { "aria-pressed": isSelected ?? false }
|
|
1145
|
+
});
|
|
1146
|
+
return /* @__PURE__ */ jsx(
|
|
1147
|
+
"button",
|
|
1137
1148
|
{
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1149
|
+
...mergedProps,
|
|
1150
|
+
ref,
|
|
1151
|
+
type: type === "submit" ? "submit" : type === "reset" ? "reset" : "button",
|
|
1152
|
+
...getInteractionDataAttributes({
|
|
1153
|
+
isHovered,
|
|
1154
|
+
isFocusVisible,
|
|
1155
|
+
isPressed,
|
|
1156
|
+
...isToggle ? { isSelected: isSelected ?? false } : {},
|
|
1157
|
+
isDisabled
|
|
1158
|
+
}),
|
|
1159
|
+
"data-toggle": isToggle ? "" : void 0,
|
|
1160
|
+
children
|
|
1146
1161
|
}
|
|
1147
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1148
|
-
);
|
|
1149
|
-
return (
|
|
1150
|
-
// eslint-disable-next-line react/button-has-type
|
|
1151
|
-
/* @__PURE__ */ jsx("button", { ...mergedProps, ref, type: type ?? "button", children })
|
|
1152
1162
|
);
|
|
1153
1163
|
}
|
|
1154
1164
|
);
|
|
1155
1165
|
IconButtonHeadless.displayName = "IconButtonHeadless";
|
|
1156
|
-
var
|
|
1166
|
+
var iconButtonRootVariants = cva(
|
|
1157
1167
|
[
|
|
1158
|
-
//
|
|
1159
|
-
"relative inline-flex items-center justify-center
|
|
1160
|
-
"
|
|
1161
|
-
|
|
1162
|
-
//
|
|
1163
|
-
//
|
|
1164
|
-
//
|
|
1168
|
+
// Layout
|
|
1169
|
+
"relative inline-flex items-center justify-center",
|
|
1170
|
+
"cursor-pointer select-none",
|
|
1171
|
+
"overflow-hidden",
|
|
1172
|
+
// Corner radius driven by CSS variable — set per shape×size in compoundVariants.
|
|
1173
|
+
// Fallback 9999px is only reached if both shape and size props are absent,
|
|
1174
|
+
// which cannot happen in normal usage.
|
|
1175
|
+
"rounded-[var(--ib-radius,9999px)]",
|
|
1176
|
+
// Split MD3 transition via the existing btn-transition utility:
|
|
1177
|
+
// border-radius → emphasized-decelerate (no overshoot, no sharp-corner flash)
|
|
1178
|
+
// color/bg/border/opacity → standard-fast-effects (no overshoot on effects)
|
|
1179
|
+
// This is identical to the approach used by Button/connected ButtonGroup and is
|
|
1180
|
+
// the standard fix for the 9999px overshoot problem documented in styles.css.
|
|
1165
1181
|
"btn-transition",
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
"
|
|
1169
|
-
"
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
"
|
|
1173
|
-
"
|
|
1182
|
+
// Background + border + text driven from CSS role variables
|
|
1183
|
+
"bg-[var(--ib-bg,transparent)]",
|
|
1184
|
+
"border border-[var(--ib-border,transparent)]",
|
|
1185
|
+
"text-[var(--ib-fg,currentColor)]",
|
|
1186
|
+
// Toggle: off state (data-toggle present but data-selected absent)
|
|
1187
|
+
// Uses doubly-chained selector to beat single-chain specificity of defaults
|
|
1188
|
+
"data-[toggle]:bg-[var(--ib-bg-off,var(--ib-bg,transparent))]",
|
|
1189
|
+
"data-[toggle]:text-[var(--ib-fg-off,var(--ib-fg,currentColor))]",
|
|
1190
|
+
// Selected state
|
|
1191
|
+
"data-[selected]:bg-[var(--ib-bg-on,var(--ib-bg,transparent))]",
|
|
1192
|
+
"data-[selected]:text-[var(--ib-fg-on,var(--ib-fg,currentColor))]",
|
|
1193
|
+
"data-[selected]:border-transparent",
|
|
1194
|
+
// Press shape-morph: radius collapses to --ib-radius-press on press
|
|
1195
|
+
// (only has visual effect when --ib-radius-press differs from --ib-radius)
|
|
1196
|
+
"data-[pressed]:rounded-[var(--ib-radius-press,var(--ib-radius,9999px))]",
|
|
1197
|
+
// Focus ring (outline, not a state layer — stays outside overflow-hidden
|
|
1198
|
+
// because it's drawn as outline on the root element itself)
|
|
1199
|
+
"outline-none",
|
|
1200
|
+
"group-data-[focus-visible]/icon-button:outline-2",
|
|
1201
|
+
"group-data-[focus-visible]/icon-button:outline-offset-2",
|
|
1202
|
+
"group-data-[focus-visible]/icon-button:outline-secondary",
|
|
1203
|
+
// Disabled — content opacity 38%, container handled per variant via CSS vars
|
|
1204
|
+
"data-[disabled]:cursor-not-allowed data-[disabled]:pointer-events-none",
|
|
1205
|
+
"data-[disabled]:text-on-surface/38"
|
|
1206
|
+
// Filled/tonal/outlined-selected backgrounds collapse to on-surface/12 — set
|
|
1207
|
+
// via compoundVariants on the root for variants that have a container.
|
|
1208
|
+
// For variants with transparent bg (standard, outlined-unselected) we do nothing.
|
|
1174
1209
|
],
|
|
1175
1210
|
{
|
|
1176
1211
|
variants: {
|
|
1177
1212
|
/**
|
|
1178
|
-
*
|
|
1213
|
+
* Visual style variant (MD3 icon button types)
|
|
1179
1214
|
*/
|
|
1180
1215
|
variant: {
|
|
1181
|
-
standard: "
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
tonal: "",
|
|
1186
|
-
// Container background
|
|
1187
|
-
outlined: "bg-transparent border border-outline"
|
|
1216
|
+
standard: "",
|
|
1217
|
+
filled: "data-[disabled]:bg-on-surface/12",
|
|
1218
|
+
tonal: "data-[disabled]:bg-on-surface/12",
|
|
1219
|
+
outlined: ""
|
|
1188
1220
|
},
|
|
1189
1221
|
/**
|
|
1190
|
-
* Color scheme
|
|
1222
|
+
* Color scheme — sets CSS role variables via compoundVariants.
|
|
1191
1223
|
*/
|
|
1192
1224
|
color: {
|
|
1193
1225
|
primary: "",
|
|
@@ -1196,180 +1228,400 @@ var iconButtonVariants = cva(
|
|
|
1196
1228
|
error: ""
|
|
1197
1229
|
},
|
|
1198
1230
|
/**
|
|
1199
|
-
*
|
|
1231
|
+
* Size tier (M3 Expressive 5-tier)
|
|
1200
1232
|
*/
|
|
1201
1233
|
size: {
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
medium: "h-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
// 48×48px
|
|
1234
|
+
xsmall: "h-8",
|
|
1235
|
+
small: "h-10",
|
|
1236
|
+
medium: "h-14",
|
|
1237
|
+
large: "h-24",
|
|
1238
|
+
xlarge: "h-[8.5rem]"
|
|
1208
1239
|
},
|
|
1209
1240
|
/**
|
|
1210
|
-
*
|
|
1241
|
+
* Width variant — adjusts container width
|
|
1211
1242
|
*/
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1243
|
+
width: {
|
|
1244
|
+
narrow: "",
|
|
1245
|
+
default: "",
|
|
1246
|
+
wide: ""
|
|
1215
1247
|
},
|
|
1216
1248
|
/**
|
|
1217
|
-
*
|
|
1249
|
+
* Shape — base values only; per-size radii set via compoundVariants below.
|
|
1250
|
+
*
|
|
1251
|
+
* round: --ib-radius = half the container height (true circle), set per size.
|
|
1252
|
+
* --ib-radius-press = square corner for that size (set per size).
|
|
1253
|
+
* Morph distance is small (e.g. 28px → 16px for medium), so the
|
|
1254
|
+
* emphasized-decelerate curve from btn-transition produces a smooth,
|
|
1255
|
+
* non-overshooting transition. The old 9999px fallback caused the
|
|
1256
|
+
* spring to overshoot below 0 = sharp-corner flash.
|
|
1257
|
+
* square: --ib-radius = size-tiered MD3 corner, set per size. No press morph.
|
|
1218
1258
|
*/
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1259
|
+
shape: {
|
|
1260
|
+
round: [],
|
|
1261
|
+
square: []
|
|
1222
1262
|
}
|
|
1223
1263
|
},
|
|
1224
|
-
/**
|
|
1225
|
-
* Compound variants - combinations of variant + color + selected
|
|
1226
|
-
*/
|
|
1227
1264
|
compoundVariants: [
|
|
1228
|
-
//
|
|
1229
|
-
//
|
|
1230
|
-
//
|
|
1231
|
-
{
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
},
|
|
1265
|
+
// ══════════════════════════════════════════════════════════════════════
|
|
1266
|
+
// SIZE × WIDTH — container width
|
|
1267
|
+
// ══════════════════════════════════════════════════════════════════════
|
|
1268
|
+
{ size: "xsmall", width: "narrow", className: "w-6" },
|
|
1269
|
+
{ size: "xsmall", width: "default", className: "w-8" },
|
|
1270
|
+
{ size: "xsmall", width: "wide", className: "w-10" },
|
|
1271
|
+
{ size: "small", width: "narrow", className: "w-8" },
|
|
1272
|
+
{ size: "small", width: "default", className: "w-10" },
|
|
1273
|
+
{ size: "small", width: "wide", className: "w-13" },
|
|
1274
|
+
{ size: "medium", width: "narrow", className: "w-12" },
|
|
1275
|
+
{ size: "medium", width: "default", className: "w-14" },
|
|
1276
|
+
{ size: "medium", width: "wide", className: "w-18" },
|
|
1277
|
+
{ size: "large", width: "narrow", className: "w-18" },
|
|
1278
|
+
{ size: "large", width: "default", className: "w-24" },
|
|
1279
|
+
{ size: "large", width: "wide", className: "w-32" },
|
|
1280
|
+
{ size: "xlarge", width: "narrow", className: "w-24" },
|
|
1281
|
+
{ size: "xlarge", width: "default", className: "w-[8.5rem]" },
|
|
1282
|
+
{ size: "xlarge", width: "wide", className: "w-42" },
|
|
1283
|
+
// ══════════════════════════════════════════════════════════════════════
|
|
1284
|
+
// SHAPE × SIZE — corner radii for both round and square shapes
|
|
1285
|
+
// ══════════════════════════════════════════════════════════════════════
|
|
1286
|
+
//
|
|
1287
|
+
// Round rest radius = half container height (true circle).
|
|
1288
|
+
// Using the exact half-height keeps the morph distance small, so the
|
|
1289
|
+
// no-overshoot emphasized-decelerate curve in btn-transition produces a
|
|
1290
|
+
// smooth animation. Using 9999px was the original cause of the sharp-
|
|
1291
|
+
// corner flash (the spring overshoots below 0 before settling).
|
|
1292
|
+
//
|
|
1293
|
+
// xsmall h-8 = 32px → half = 16px = 1rem
|
|
1294
|
+
// small h-10 = 40px → half = 20px = 1.25rem
|
|
1295
|
+
// medium h-14 = 56px → half = 28px = 1.75rem
|
|
1296
|
+
// large h-24 = 96px → half = 48px = 3rem
|
|
1297
|
+
// xlarge h-34 = 136px → half = 68px = 4.25rem
|
|
1298
|
+
//
|
|
1299
|
+
// Round press-morph target = MD3 square corner for that size tier.
|
|
1300
|
+
// Square rest radius = same MD3 corner (no morph).
|
|
1301
|
+
// ── round: rest radius (half height) ──────────────────────────────────
|
|
1302
|
+
{ shape: "round", size: "xsmall", className: "[--ib-radius:1rem]" },
|
|
1303
|
+
{ shape: "round", size: "small", className: "[--ib-radius:1.25rem]" },
|
|
1304
|
+
{ shape: "round", size: "medium", className: "[--ib-radius:1.75rem]" },
|
|
1305
|
+
{ shape: "round", size: "large", className: "[--ib-radius:3rem]" },
|
|
1306
|
+
{ shape: "round", size: "xlarge", className: "[--ib-radius:4.25rem]" },
|
|
1307
|
+
// ── round: press-morph target (square corner for that size) ───────────
|
|
1308
|
+
{ shape: "round", size: "xsmall", className: "[--ib-radius-press:0.75rem]" },
|
|
1309
|
+
{ shape: "round", size: "small", className: "[--ib-radius-press:0.75rem]" },
|
|
1310
|
+
{ shape: "round", size: "medium", className: "[--ib-radius-press:1rem]" },
|
|
1311
|
+
{ shape: "round", size: "large", className: "[--ib-radius-press:1.75rem]" },
|
|
1312
|
+
{ shape: "round", size: "xlarge", className: "[--ib-radius-press:1.75rem]" },
|
|
1313
|
+
// ── square: rest radius (MD3 shape scale) ─────────────────────────────
|
|
1314
|
+
// xsmall / small → 12px (0.75rem), medium → 16px (1rem), large / xlarge → 28px (1.75rem)
|
|
1315
|
+
{ shape: "square", size: "xsmall", className: "[--ib-radius:0.75rem]" },
|
|
1316
|
+
{ shape: "square", size: "small", className: "[--ib-radius:0.75rem]" },
|
|
1317
|
+
{ shape: "square", size: "medium", className: "[--ib-radius:1rem]" },
|
|
1318
|
+
{ shape: "square", size: "large", className: "[--ib-radius:1.75rem]" },
|
|
1319
|
+
{ shape: "square", size: "xlarge", className: "[--ib-radius:1.75rem]" },
|
|
1320
|
+
// ══════════════════════════════════════════════════════════════════════
|
|
1321
|
+
// VARIANT × COLOR — CSS role variable assignments
|
|
1322
|
+
// Only variant × color (design-time decisions); no state variants here.
|
|
1323
|
+
// ══════════════════════════════════════════════════════════════════════
|
|
1324
|
+
// ── STANDARD ──────────────────────────────────────────────────────────
|
|
1325
|
+
// Non-toggle standard: transparent bg, on-surface-variant fg
|
|
1326
|
+
// Selected: primary fg
|
|
1327
|
+
// State layer: on-surface-variant (unselected) / primary (selected)
|
|
1236
1328
|
{
|
|
1237
1329
|
variant: "standard",
|
|
1238
|
-
selected: true,
|
|
1239
|
-
className: "text-primary"
|
|
1240
|
-
},
|
|
1241
|
-
// ====================
|
|
1242
|
-
// FILLED VARIANTS (UNSELECTED)
|
|
1243
|
-
// ====================
|
|
1244
|
-
{
|
|
1245
|
-
variant: "filled",
|
|
1246
1330
|
color: "primary",
|
|
1247
|
-
|
|
1248
|
-
|
|
1331
|
+
className: [
|
|
1332
|
+
"[--ib-bg:transparent]",
|
|
1333
|
+
"[--ib-fg:var(--color-on-surface-variant)]",
|
|
1334
|
+
"[--ib-fg-on:var(--color-primary)]",
|
|
1335
|
+
"[--ib-sl:var(--color-on-surface-variant)]",
|
|
1336
|
+
// toggle-off same as non-toggle
|
|
1337
|
+
"[--ib-bg-off:transparent]",
|
|
1338
|
+
"[--ib-fg-off:var(--color-on-surface-variant)]",
|
|
1339
|
+
// toggle-on: selected
|
|
1340
|
+
"[--ib-bg-on:transparent]"
|
|
1341
|
+
]
|
|
1249
1342
|
},
|
|
1250
1343
|
{
|
|
1251
|
-
variant: "
|
|
1344
|
+
variant: "standard",
|
|
1252
1345
|
color: "secondary",
|
|
1253
|
-
|
|
1254
|
-
|
|
1346
|
+
className: [
|
|
1347
|
+
"[--ib-bg:transparent]",
|
|
1348
|
+
"[--ib-fg:var(--color-on-surface-variant)]",
|
|
1349
|
+
"[--ib-fg-on:var(--color-secondary)]",
|
|
1350
|
+
"[--ib-sl:var(--color-on-surface-variant)]",
|
|
1351
|
+
"[--ib-bg-off:transparent]",
|
|
1352
|
+
"[--ib-fg-off:var(--color-on-surface-variant)]",
|
|
1353
|
+
"[--ib-bg-on:transparent]"
|
|
1354
|
+
]
|
|
1255
1355
|
},
|
|
1256
1356
|
{
|
|
1257
|
-
variant: "
|
|
1357
|
+
variant: "standard",
|
|
1258
1358
|
color: "tertiary",
|
|
1259
|
-
|
|
1260
|
-
|
|
1359
|
+
className: [
|
|
1360
|
+
"[--ib-bg:transparent]",
|
|
1361
|
+
"[--ib-fg:var(--color-on-surface-variant)]",
|
|
1362
|
+
"[--ib-fg-on:var(--color-tertiary)]",
|
|
1363
|
+
"[--ib-sl:var(--color-on-surface-variant)]",
|
|
1364
|
+
"[--ib-bg-off:transparent]",
|
|
1365
|
+
"[--ib-fg-off:var(--color-on-surface-variant)]",
|
|
1366
|
+
"[--ib-bg-on:transparent]"
|
|
1367
|
+
]
|
|
1261
1368
|
},
|
|
1262
1369
|
{
|
|
1263
|
-
variant: "
|
|
1370
|
+
variant: "standard",
|
|
1264
1371
|
color: "error",
|
|
1265
|
-
|
|
1266
|
-
|
|
1372
|
+
className: [
|
|
1373
|
+
"[--ib-bg:transparent]",
|
|
1374
|
+
"[--ib-fg:var(--color-on-surface-variant)]",
|
|
1375
|
+
"[--ib-fg-on:var(--color-error)]",
|
|
1376
|
+
"[--ib-sl:var(--color-on-surface-variant)]",
|
|
1377
|
+
"[--ib-bg-off:transparent]",
|
|
1378
|
+
"[--ib-fg-off:var(--color-on-surface-variant)]",
|
|
1379
|
+
"[--ib-bg-on:transparent]"
|
|
1380
|
+
]
|
|
1267
1381
|
},
|
|
1268
|
-
//
|
|
1269
|
-
//
|
|
1270
|
-
//
|
|
1382
|
+
// ── FILLED ────────────────────────────────────────────────────────────
|
|
1383
|
+
// Non-toggle: bg primary / fg on-primary
|
|
1384
|
+
// Toggle off: bg surface-container-highest / fg primary
|
|
1385
|
+
// Toggle on (selected): bg primary / fg on-primary
|
|
1386
|
+
// State layer: on-primary (non-toggle / selected), primary (toggle-off)
|
|
1271
1387
|
{
|
|
1272
1388
|
variant: "filled",
|
|
1273
1389
|
color: "primary",
|
|
1274
|
-
|
|
1275
|
-
|
|
1390
|
+
className: [
|
|
1391
|
+
"[--ib-bg:var(--color-primary)]",
|
|
1392
|
+
"[--ib-fg:var(--color-on-primary)]",
|
|
1393
|
+
"[--ib-sl:var(--color-on-primary)]",
|
|
1394
|
+
"[--ib-bg-off:var(--color-surface-container-highest)]",
|
|
1395
|
+
"[--ib-fg-off:var(--color-primary)]",
|
|
1396
|
+
"[--ib-bg-on:var(--color-primary)]",
|
|
1397
|
+
"[--ib-fg-on:var(--color-on-primary)]"
|
|
1398
|
+
]
|
|
1276
1399
|
},
|
|
1277
1400
|
{
|
|
1278
1401
|
variant: "filled",
|
|
1279
1402
|
color: "secondary",
|
|
1280
|
-
|
|
1281
|
-
|
|
1403
|
+
className: [
|
|
1404
|
+
"[--ib-bg:var(--color-secondary)]",
|
|
1405
|
+
"[--ib-fg:var(--color-on-secondary)]",
|
|
1406
|
+
"[--ib-sl:var(--color-on-secondary)]",
|
|
1407
|
+
"[--ib-bg-off:var(--color-surface-container-highest)]",
|
|
1408
|
+
"[--ib-fg-off:var(--color-secondary)]",
|
|
1409
|
+
"[--ib-bg-on:var(--color-secondary)]",
|
|
1410
|
+
"[--ib-fg-on:var(--color-on-secondary)]"
|
|
1411
|
+
]
|
|
1282
1412
|
},
|
|
1283
1413
|
{
|
|
1284
1414
|
variant: "filled",
|
|
1285
1415
|
color: "tertiary",
|
|
1286
|
-
|
|
1287
|
-
|
|
1416
|
+
className: [
|
|
1417
|
+
"[--ib-bg:var(--color-tertiary)]",
|
|
1418
|
+
"[--ib-fg:var(--color-on-tertiary)]",
|
|
1419
|
+
"[--ib-sl:var(--color-on-tertiary)]",
|
|
1420
|
+
"[--ib-bg-off:var(--color-surface-container-highest)]",
|
|
1421
|
+
"[--ib-fg-off:var(--color-tertiary)]",
|
|
1422
|
+
"[--ib-bg-on:var(--color-tertiary)]",
|
|
1423
|
+
"[--ib-fg-on:var(--color-on-tertiary)]"
|
|
1424
|
+
]
|
|
1288
1425
|
},
|
|
1289
1426
|
{
|
|
1290
1427
|
variant: "filled",
|
|
1291
1428
|
color: "error",
|
|
1292
|
-
|
|
1293
|
-
|
|
1429
|
+
className: [
|
|
1430
|
+
"[--ib-bg:var(--color-error)]",
|
|
1431
|
+
"[--ib-fg:var(--color-on-error)]",
|
|
1432
|
+
"[--ib-sl:var(--color-on-error)]",
|
|
1433
|
+
"[--ib-bg-off:var(--color-surface-container-highest)]",
|
|
1434
|
+
"[--ib-fg-off:var(--color-error)]",
|
|
1435
|
+
"[--ib-bg-on:var(--color-error)]",
|
|
1436
|
+
"[--ib-fg-on:var(--color-on-error)]"
|
|
1437
|
+
]
|
|
1294
1438
|
},
|
|
1295
|
-
//
|
|
1296
|
-
//
|
|
1297
|
-
//
|
|
1439
|
+
// ── TONAL ─────────────────────────────────────────────────────────────
|
|
1440
|
+
// Non-toggle: bg secondary-container / fg on-secondary-container
|
|
1441
|
+
// Toggle off: bg surface-container-highest / fg on-surface-variant
|
|
1442
|
+
// Toggle on (selected): bg secondary-container / fg on-secondary-container
|
|
1298
1443
|
{
|
|
1299
1444
|
variant: "tonal",
|
|
1300
1445
|
color: "primary",
|
|
1301
|
-
|
|
1302
|
-
|
|
1446
|
+
className: [
|
|
1447
|
+
"[--ib-bg:var(--color-secondary-container)]",
|
|
1448
|
+
"[--ib-fg:var(--color-on-secondary-container)]",
|
|
1449
|
+
"[--ib-sl:var(--color-on-secondary-container)]",
|
|
1450
|
+
"[--ib-bg-off:var(--color-surface-container-highest)]",
|
|
1451
|
+
"[--ib-fg-off:var(--color-on-surface-variant)]",
|
|
1452
|
+
"[--ib-bg-on:var(--color-secondary-container)]",
|
|
1453
|
+
"[--ib-fg-on:var(--color-on-secondary-container)]"
|
|
1454
|
+
]
|
|
1303
1455
|
},
|
|
1304
1456
|
{
|
|
1305
1457
|
variant: "tonal",
|
|
1306
1458
|
color: "secondary",
|
|
1307
|
-
|
|
1308
|
-
|
|
1459
|
+
className: [
|
|
1460
|
+
"[--ib-bg:var(--color-secondary-container)]",
|
|
1461
|
+
"[--ib-fg:var(--color-on-secondary-container)]",
|
|
1462
|
+
"[--ib-sl:var(--color-on-secondary-container)]",
|
|
1463
|
+
"[--ib-bg-off:var(--color-surface-container-highest)]",
|
|
1464
|
+
"[--ib-fg-off:var(--color-on-surface-variant)]",
|
|
1465
|
+
"[--ib-bg-on:var(--color-secondary-container)]",
|
|
1466
|
+
"[--ib-fg-on:var(--color-on-secondary-container)]"
|
|
1467
|
+
]
|
|
1309
1468
|
},
|
|
1310
1469
|
{
|
|
1311
1470
|
variant: "tonal",
|
|
1312
1471
|
color: "tertiary",
|
|
1313
|
-
|
|
1314
|
-
|
|
1472
|
+
className: [
|
|
1473
|
+
"[--ib-bg:var(--color-tertiary-container)]",
|
|
1474
|
+
"[--ib-fg:var(--color-on-tertiary-container)]",
|
|
1475
|
+
"[--ib-sl:var(--color-on-tertiary-container)]",
|
|
1476
|
+
"[--ib-bg-off:var(--color-surface-container-highest)]",
|
|
1477
|
+
"[--ib-fg-off:var(--color-on-surface-variant)]",
|
|
1478
|
+
"[--ib-bg-on:var(--color-tertiary-container)]",
|
|
1479
|
+
"[--ib-fg-on:var(--color-on-tertiary-container)]"
|
|
1480
|
+
]
|
|
1315
1481
|
},
|
|
1316
1482
|
{
|
|
1317
1483
|
variant: "tonal",
|
|
1318
1484
|
color: "error",
|
|
1319
|
-
|
|
1320
|
-
|
|
1485
|
+
className: [
|
|
1486
|
+
"[--ib-bg:var(--color-error-container)]",
|
|
1487
|
+
"[--ib-fg:var(--color-on-error-container)]",
|
|
1488
|
+
"[--ib-sl:var(--color-on-error-container)]",
|
|
1489
|
+
"[--ib-bg-off:var(--color-surface-container-highest)]",
|
|
1490
|
+
"[--ib-fg-off:var(--color-on-surface-variant)]",
|
|
1491
|
+
"[--ib-bg-on:var(--color-error-container)]",
|
|
1492
|
+
"[--ib-fg-on:var(--color-on-error-container)]"
|
|
1493
|
+
]
|
|
1321
1494
|
},
|
|
1322
|
-
//
|
|
1323
|
-
//
|
|
1324
|
-
//
|
|
1495
|
+
// ── OUTLINED ──────────────────────────────────────────────────────────
|
|
1496
|
+
// Non-toggle: transparent bg, border-outline, on-surface-variant fg
|
|
1497
|
+
// Toggle off: same as non-toggle
|
|
1498
|
+
// Toggle on (selected): inverse-surface bg, inverse-on-surface fg, no border
|
|
1499
|
+
// Disabled: border becomes on-surface/12 (set via Tailwind utility on root)
|
|
1325
1500
|
{
|
|
1326
|
-
variant: "
|
|
1327
|
-
|
|
1328
|
-
className:
|
|
1501
|
+
variant: "outlined",
|
|
1502
|
+
color: "primary",
|
|
1503
|
+
className: [
|
|
1504
|
+
"[--ib-bg:transparent]",
|
|
1505
|
+
"[--ib-fg:var(--color-on-surface-variant)]",
|
|
1506
|
+
"[--ib-sl:var(--color-on-surface-variant)]",
|
|
1507
|
+
"[--ib-border:var(--color-outline)]",
|
|
1508
|
+
"[--ib-bg-off:transparent]",
|
|
1509
|
+
"[--ib-fg-off:var(--color-on-surface-variant)]",
|
|
1510
|
+
"[--ib-bg-on:var(--color-inverse-surface)]",
|
|
1511
|
+
"[--ib-fg-on:var(--color-inverse-on-surface)]",
|
|
1512
|
+
// Disabled outlined border
|
|
1513
|
+
"data-[disabled]:border-on-surface/12"
|
|
1514
|
+
]
|
|
1329
1515
|
},
|
|
1330
|
-
// ====================
|
|
1331
|
-
// OUTLINED VARIANTS (UNSELECTED)
|
|
1332
|
-
// ====================
|
|
1333
1516
|
{
|
|
1334
1517
|
variant: "outlined",
|
|
1335
|
-
|
|
1336
|
-
className:
|
|
1518
|
+
color: "secondary",
|
|
1519
|
+
className: [
|
|
1520
|
+
"[--ib-bg:transparent]",
|
|
1521
|
+
"[--ib-fg:var(--color-on-surface-variant)]",
|
|
1522
|
+
"[--ib-sl:var(--color-on-surface-variant)]",
|
|
1523
|
+
"[--ib-border:var(--color-outline)]",
|
|
1524
|
+
"[--ib-bg-off:transparent]",
|
|
1525
|
+
"[--ib-fg-off:var(--color-on-surface-variant)]",
|
|
1526
|
+
"[--ib-bg-on:var(--color-inverse-surface)]",
|
|
1527
|
+
"[--ib-fg-on:var(--color-inverse-on-surface)]",
|
|
1528
|
+
"data-[disabled]:border-on-surface/12"
|
|
1529
|
+
]
|
|
1337
1530
|
},
|
|
1338
|
-
// ====================
|
|
1339
|
-
// OUTLINED VARIANTS (SELECTED - uses inverse colors)
|
|
1340
|
-
// ====================
|
|
1341
1531
|
{
|
|
1342
1532
|
variant: "outlined",
|
|
1343
|
-
|
|
1344
|
-
className:
|
|
1533
|
+
color: "tertiary",
|
|
1534
|
+
className: [
|
|
1535
|
+
"[--ib-bg:transparent]",
|
|
1536
|
+
"[--ib-fg:var(--color-on-surface-variant)]",
|
|
1537
|
+
"[--ib-sl:var(--color-on-surface-variant)]",
|
|
1538
|
+
"[--ib-border:var(--color-outline)]",
|
|
1539
|
+
"[--ib-bg-off:transparent]",
|
|
1540
|
+
"[--ib-fg-off:var(--color-on-surface-variant)]",
|
|
1541
|
+
"[--ib-bg-on:var(--color-inverse-surface)]",
|
|
1542
|
+
"[--ib-fg-on:var(--color-inverse-on-surface)]",
|
|
1543
|
+
"data-[disabled]:border-on-surface/12"
|
|
1544
|
+
]
|
|
1545
|
+
},
|
|
1546
|
+
{
|
|
1547
|
+
variant: "outlined",
|
|
1548
|
+
color: "error",
|
|
1549
|
+
className: [
|
|
1550
|
+
"[--ib-bg:transparent]",
|
|
1551
|
+
"[--ib-fg:var(--color-on-surface-variant)]",
|
|
1552
|
+
"[--ib-sl:var(--color-on-surface-variant)]",
|
|
1553
|
+
"[--ib-border:var(--color-outline)]",
|
|
1554
|
+
"[--ib-bg-off:transparent]",
|
|
1555
|
+
"[--ib-fg-off:var(--color-on-surface-variant)]",
|
|
1556
|
+
"[--ib-bg-on:var(--color-inverse-surface)]",
|
|
1557
|
+
"[--ib-fg-on:var(--color-inverse-on-surface)]",
|
|
1558
|
+
"data-[disabled]:border-on-surface/12"
|
|
1559
|
+
]
|
|
1345
1560
|
}
|
|
1346
1561
|
],
|
|
1347
|
-
/**
|
|
1348
|
-
* Default variants
|
|
1349
|
-
*/
|
|
1350
1562
|
defaultVariants: {
|
|
1351
1563
|
variant: "standard",
|
|
1352
1564
|
color: "primary",
|
|
1353
1565
|
size: "medium",
|
|
1354
|
-
|
|
1355
|
-
|
|
1566
|
+
width: "default",
|
|
1567
|
+
shape: "round"
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
);
|
|
1571
|
+
var iconButtonStateLayerVariants = cva([
|
|
1572
|
+
"absolute inset-0 rounded-[inherit] pointer-events-none opacity-0",
|
|
1573
|
+
"bg-[var(--ib-sl,currentColor)]",
|
|
1574
|
+
// Effects transition (opacity — no spatial overshoot)
|
|
1575
|
+
"transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
|
|
1576
|
+
// Interaction opacities (MD3: hover 8%, focus/pressed 10%)
|
|
1577
|
+
"group-data-[hovered]/icon-button:opacity-8",
|
|
1578
|
+
"group-data-[focus-visible]/icon-button:opacity-10",
|
|
1579
|
+
"group-data-[pressed]/icon-button:opacity-10",
|
|
1580
|
+
// No state layer when disabled
|
|
1581
|
+
"group-data-[disabled]/icon-button:hidden"
|
|
1582
|
+
]);
|
|
1583
|
+
var iconButtonIconVariants = cva(
|
|
1584
|
+
[
|
|
1585
|
+
"relative z-10 inline-flex shrink-0 items-center justify-center",
|
|
1586
|
+
"transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects"
|
|
1587
|
+
],
|
|
1588
|
+
{
|
|
1589
|
+
variants: {
|
|
1590
|
+
size: {
|
|
1591
|
+
xsmall: "size-5",
|
|
1592
|
+
// 20dp
|
|
1593
|
+
small: "size-6",
|
|
1594
|
+
// 24dp
|
|
1595
|
+
medium: "size-6",
|
|
1596
|
+
// 24dp
|
|
1597
|
+
large: "size-8",
|
|
1598
|
+
// 32dp
|
|
1599
|
+
xlarge: "size-10"
|
|
1600
|
+
// 40dp
|
|
1601
|
+
}
|
|
1602
|
+
},
|
|
1603
|
+
defaultVariants: {
|
|
1604
|
+
size: "medium"
|
|
1356
1605
|
}
|
|
1357
1606
|
}
|
|
1358
1607
|
);
|
|
1359
1608
|
var IconButton = forwardRef(
|
|
1360
1609
|
({
|
|
1361
|
-
// Variant props (CVA)
|
|
1610
|
+
// Variant props (CVA / design-time)
|
|
1362
1611
|
variant = "standard",
|
|
1363
1612
|
color = "primary",
|
|
1364
1613
|
size = "medium",
|
|
1614
|
+
width = "default",
|
|
1615
|
+
shape = "round",
|
|
1365
1616
|
// IconButton specific props
|
|
1366
1617
|
children,
|
|
1618
|
+
selectedIcon,
|
|
1367
1619
|
value,
|
|
1368
1620
|
selected,
|
|
1369
1621
|
disableRipple = false,
|
|
1370
1622
|
className,
|
|
1371
1623
|
// React Aria props
|
|
1372
|
-
isDisabled
|
|
1624
|
+
isDisabled = false,
|
|
1373
1625
|
onPress,
|
|
1374
1626
|
onMouseDown,
|
|
1375
1627
|
"aria-label": ariaLabel,
|
|
@@ -1388,7 +1640,8 @@ var IconButton = forwardRef(
|
|
|
1388
1640
|
console.warn("[IconButton] IconButton should have an icon as children.");
|
|
1389
1641
|
}
|
|
1390
1642
|
}
|
|
1391
|
-
const
|
|
1643
|
+
const isToggle = selected !== void 0;
|
|
1644
|
+
const isSelected = isToggle ? selected ?? false : false;
|
|
1392
1645
|
const { onMouseDown: handleRipple, ripples } = useRipple({
|
|
1393
1646
|
disabled: isDisabled || disableRipple
|
|
1394
1647
|
});
|
|
@@ -1406,32 +1659,37 @@ var IconButton = forwardRef(
|
|
|
1406
1659
|
...getConnectedRadiusClasses(groupCtx, value),
|
|
1407
1660
|
groupCtx.enforceMinWidth ? "min-w-12" : ""
|
|
1408
1661
|
] : [];
|
|
1662
|
+
const iconNode = isToggle && isSelected && selectedIcon ? selectedIcon : children;
|
|
1409
1663
|
return /* @__PURE__ */ jsxs(
|
|
1410
1664
|
IconButtonHeadless,
|
|
1411
1665
|
{
|
|
1412
1666
|
ref,
|
|
1413
1667
|
className: cn(
|
|
1414
|
-
// CVA
|
|
1415
|
-
|
|
1416
|
-
//
|
|
1417
|
-
|
|
1418
|
-
//
|
|
1419
|
-
// path, preventing the overshoot-to-0px sharp-corner flash.
|
|
1668
|
+
// Root CVA — sets CSS role variables, dimensions, shape, transitions
|
|
1669
|
+
iconButtonRootVariants({ variant, color, size, width, shape }),
|
|
1670
|
+
// Group scope for child slot selectors
|
|
1671
|
+
"group/icon-button",
|
|
1672
|
+
// ButtonGroup asymmetric border-radius easing (connected selection morph)
|
|
1420
1673
|
isGroupSelected ? "btn-transition-selected" : "",
|
|
1421
1674
|
...connectedClasses,
|
|
1422
|
-
//
|
|
1675
|
+
// Consumer custom classes
|
|
1423
1676
|
className
|
|
1424
1677
|
),
|
|
1425
1678
|
"aria-label": ariaLabel,
|
|
1679
|
+
isSelected,
|
|
1680
|
+
isToggle,
|
|
1426
1681
|
"data-variant": variant,
|
|
1427
1682
|
"data-color": color,
|
|
1683
|
+
"data-size": size,
|
|
1684
|
+
"data-width": width,
|
|
1685
|
+
"data-shape": shape,
|
|
1428
1686
|
"data-group-selected": isGroupSelected ? "" : void 0,
|
|
1429
|
-
...selected !== void 0 && { selected },
|
|
1430
1687
|
...title && { title },
|
|
1431
1688
|
...mergedPropsValue,
|
|
1432
1689
|
children: [
|
|
1690
|
+
/* @__PURE__ */ jsx("span", { className: iconButtonStateLayerVariants(), "aria-hidden": "true", "data-state-layer": "" }),
|
|
1433
1691
|
ripples,
|
|
1434
|
-
/* @__PURE__ */ jsx("span", { className:
|
|
1692
|
+
/* @__PURE__ */ jsx("span", { className: iconButtonIconVariants({ size }), "data-icon-slot": "", "aria-hidden": "true", children: iconNode })
|
|
1435
1693
|
]
|
|
1436
1694
|
}
|
|
1437
1695
|
);
|