@instructure/ui-buttons 11.7.4-snapshot-52 → 11.7.4-snapshot-53

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/CHANGELOG.md CHANGED
@@ -3,9 +3,12 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [11.7.4-snapshot-52](https://github.com/instructure/instructure-ui/compare/v11.7.3...v11.7.4-snapshot-52) (2026-06-19)
6
+ ## [11.7.4-snapshot-53](https://github.com/instructure/instructure-ui/compare/v11.7.3...v11.7.4-snapshot-53) (2026-06-22)
7
7
 
8
- **Note:** Version bump only for package @instructure/ui-buttons
8
+
9
+ ### Bug Fixes
10
+
11
+ * **ui-buttons:** fix buttons disabled style and color ([2f2f7b0](https://github.com/instructure/instructure-ui/commit/2f2f7b04c7d666aef0e76054c9f722dab9f679e7))
9
12
 
10
13
 
11
14
 
@@ -218,7 +218,7 @@ let BaseButton = (_dec = withStyleNew(generateStyles), _dec(_class = class BaseB
218
218
  hasOnlyIconVisible
219
219
  } = this;
220
220
  const iconSize = buttonSizeToIconSize[size];
221
- const iconColor = buttonColorToIconColor[color];
221
+ const iconColor = this.isDisabled && color === 'ai-secondary' ? 'inherit' : buttonColorToIconColor[color];
222
222
  const wrappedIcon = _jsx("span", {
223
223
  css: styles?.iconSVG,
224
224
  children: renderIconWithProps(renderIcon, iconSize, iconColor)
@@ -253,7 +253,9 @@ const generateStyle = (componentTheme, params, _sharedTokens, extraArgs) => {
253
253
  boxShadow: componentTheme.secondaryGhostHoverBoxShadow
254
254
  },
255
255
  disabled: {
256
- background: 'transparent'
256
+ background: 'transparent',
257
+ borderColor: componentTheme.secondaryDisabledBorderColor,
258
+ color: componentTheme.secondaryDisabledTextColor
257
259
  }
258
260
  },
259
261
  'primary-inverse': withBackground ? {
@@ -399,29 +401,38 @@ const generateStyle = (componentTheme, params, _sharedTokens, extraArgs) => {
399
401
  }
400
402
  };
401
403
  return {
402
- baseButton: isEnabled ? {
403
- label: 'baseButton',
404
- appearance: 'none',
405
- textDecoration: 'none' /* for links styled as buttons */,
406
- touchAction: 'manipulation',
407
- // This sets the focus ring's border radius displayed by the `View`
408
- borderRadius: size === 'condensedSmall' || size === 'condensedMedium' ? componentTheme.borderRadiusSm : componentTheme.borderRadius,
409
- ...shapeVariants[shape],
410
- // Prevents vertical stretching in flex parents with fixed height
411
- // Avoids background/focus ring distortion
412
- height: 'fit-content',
413
- '&::-moz-focus-inner': {
414
- border: '0' /* removes default dotted focus outline in Firefox */
415
- },
416
- '*': {
417
- pointerEvents: 'none' /* Ensures that button or link is always the event target */
418
- },
419
- '&:focus': {
420
- textDecoration: 'none'
421
- },
422
- '&:hover > [class$=-baseButton__content]': colorVariants[color].hover,
423
- '&:active > [class$=-baseButton__content]': colorVariants[color].active,
404
+ baseButton: {
405
+ ...(isEnabled ? {
406
+ label: 'baseButton',
407
+ appearance: 'none',
408
+ textDecoration: 'none' /* for links styled as buttons */,
409
+ touchAction: 'manipulation',
410
+ // This sets the focus ring's border radius displayed by the `View`
411
+ borderRadius: size === 'condensedSmall' || size === 'condensedMedium' ? componentTheme.borderRadiusSm : componentTheme.borderRadius,
412
+ ...shapeVariants[shape],
413
+ // Prevents vertical stretching in flex parents with fixed height
414
+ // Avoids background/focus ring distortion
415
+ height: 'fit-content',
416
+ '&::-moz-focus-inner': {
417
+ border: '0' /* removes default dotted focus outline in Firefox */
418
+ },
419
+ '*': {
420
+ pointerEvents: 'none' /* Ensures that button or link is always the event target */
421
+ },
422
+ '&:focus': {
423
+ textDecoration: 'none'
424
+ },
425
+ '&:hover > [class$=-baseButton__content]': colorVariants[color].hover,
426
+ '&:active > [class$=-baseButton__content]': colorVariants[color].active
427
+ } :
428
+ // When not enabled (disabled/readonly) skip all interactive styles (hover/active/focus)
429
+ {
430
+ textDecoration: 'none',
431
+ label: 'baseButton',
432
+ appearance: 'none'
433
+ }),
424
434
  //TODO not the greatest solution. Must be stronger than the same &&& enforcement of <View>
435
+ // The ai-secondary border must render in both enabled and disabled states.
425
436
  ...(color === 'ai-secondary' ? {
426
437
  '&&&&&&&&&&': {
427
438
  padding: componentTheme.borderWidth,
@@ -436,7 +447,7 @@ const generateStyle = (componentTheme, params, _sharedTokens, extraArgs) => {
436
447
  inset: '0',
437
448
  borderRadius: 'inherit',
438
449
  padding: componentTheme.borderWidth,
439
- background: `linear-gradient(to bottom, ${componentTheme.aiBorderTopGradientColor} 0%, ${componentTheme.aiBorderBottomGradientColor} 100%)`,
450
+ background: isDisabled ? componentTheme.aiSecondaryDisabledBorderColor : `linear-gradient(to bottom, ${componentTheme.aiBorderTopGradientColor} 0%, ${componentTheme.aiBorderBottomGradientColor} 100%)`,
440
451
  WebkitMask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
441
452
  WebkitMaskComposite: 'xor',
442
453
  mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
@@ -445,10 +456,6 @@ const generateStyle = (componentTheme, params, _sharedTokens, extraArgs) => {
445
456
  }
446
457
  }
447
458
  } : {})
448
- } : {
449
- textDecoration: 'none',
450
- label: 'baseButton',
451
- appearance: 'none'
452
459
  },
453
460
  content: {
454
461
  label: 'baseButton__content',
@@ -226,7 +226,7 @@ let BaseButton = exports.BaseButton = (_dec = (0, _emotion.withStyleNew)(_styles
226
226
  hasOnlyIconVisible
227
227
  } = this;
228
228
  const iconSize = buttonSizeToIconSize[size];
229
- const iconColor = buttonColorToIconColor[color];
229
+ const iconColor = this.isDisabled && color === 'ai-secondary' ? 'inherit' : buttonColorToIconColor[color];
230
230
  const wrappedIcon = (0, _jsxRuntime.jsx)("span", {
231
231
  css: styles?.iconSVG,
232
232
  children: (0, _renderIconWithProps.renderIconWithProps)(renderIcon, iconSize, iconColor)
@@ -259,7 +259,9 @@ const generateStyle = (componentTheme, params, _sharedTokens, extraArgs) => {
259
259
  boxShadow: componentTheme.secondaryGhostHoverBoxShadow
260
260
  },
261
261
  disabled: {
262
- background: 'transparent'
262
+ background: 'transparent',
263
+ borderColor: componentTheme.secondaryDisabledBorderColor,
264
+ color: componentTheme.secondaryDisabledTextColor
263
265
  }
264
266
  },
265
267
  'primary-inverse': withBackground ? {
@@ -405,29 +407,38 @@ const generateStyle = (componentTheme, params, _sharedTokens, extraArgs) => {
405
407
  }
406
408
  };
407
409
  return {
408
- baseButton: isEnabled ? {
409
- label: 'baseButton',
410
- appearance: 'none',
411
- textDecoration: 'none' /* for links styled as buttons */,
412
- touchAction: 'manipulation',
413
- // This sets the focus ring's border radius displayed by the `View`
414
- borderRadius: size === 'condensedSmall' || size === 'condensedMedium' ? componentTheme.borderRadiusSm : componentTheme.borderRadius,
415
- ...shapeVariants[shape],
416
- // Prevents vertical stretching in flex parents with fixed height
417
- // Avoids background/focus ring distortion
418
- height: 'fit-content',
419
- '&::-moz-focus-inner': {
420
- border: '0' /* removes default dotted focus outline in Firefox */
421
- },
422
- '*': {
423
- pointerEvents: 'none' /* Ensures that button or link is always the event target */
424
- },
425
- '&:focus': {
426
- textDecoration: 'none'
427
- },
428
- '&:hover > [class$=-baseButton__content]': colorVariants[color].hover,
429
- '&:active > [class$=-baseButton__content]': colorVariants[color].active,
410
+ baseButton: {
411
+ ...(isEnabled ? {
412
+ label: 'baseButton',
413
+ appearance: 'none',
414
+ textDecoration: 'none' /* for links styled as buttons */,
415
+ touchAction: 'manipulation',
416
+ // This sets the focus ring's border radius displayed by the `View`
417
+ borderRadius: size === 'condensedSmall' || size === 'condensedMedium' ? componentTheme.borderRadiusSm : componentTheme.borderRadius,
418
+ ...shapeVariants[shape],
419
+ // Prevents vertical stretching in flex parents with fixed height
420
+ // Avoids background/focus ring distortion
421
+ height: 'fit-content',
422
+ '&::-moz-focus-inner': {
423
+ border: '0' /* removes default dotted focus outline in Firefox */
424
+ },
425
+ '*': {
426
+ pointerEvents: 'none' /* Ensures that button or link is always the event target */
427
+ },
428
+ '&:focus': {
429
+ textDecoration: 'none'
430
+ },
431
+ '&:hover > [class$=-baseButton__content]': colorVariants[color].hover,
432
+ '&:active > [class$=-baseButton__content]': colorVariants[color].active
433
+ } :
434
+ // When not enabled (disabled/readonly) skip all interactive styles (hover/active/focus)
435
+ {
436
+ textDecoration: 'none',
437
+ label: 'baseButton',
438
+ appearance: 'none'
439
+ }),
430
440
  //TODO not the greatest solution. Must be stronger than the same &&& enforcement of <View>
441
+ // The ai-secondary border must render in both enabled and disabled states.
431
442
  ...(color === 'ai-secondary' ? {
432
443
  '&&&&&&&&&&': {
433
444
  padding: componentTheme.borderWidth,
@@ -442,7 +453,7 @@ const generateStyle = (componentTheme, params, _sharedTokens, extraArgs) => {
442
453
  inset: '0',
443
454
  borderRadius: 'inherit',
444
455
  padding: componentTheme.borderWidth,
445
- background: `linear-gradient(to bottom, ${componentTheme.aiBorderTopGradientColor} 0%, ${componentTheme.aiBorderBottomGradientColor} 100%)`,
456
+ background: isDisabled ? componentTheme.aiSecondaryDisabledBorderColor : `linear-gradient(to bottom, ${componentTheme.aiBorderTopGradientColor} 0%, ${componentTheme.aiBorderBottomGradientColor} 100%)`,
446
457
  WebkitMask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
447
458
  WebkitMaskComposite: 'xor',
448
459
  mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
@@ -451,10 +462,6 @@ const generateStyle = (componentTheme, params, _sharedTokens, extraArgs) => {
451
462
  }
452
463
  }
453
464
  } : {})
454
- } : {
455
- textDecoration: 'none',
456
- label: 'baseButton',
457
- appearance: 'none'
458
465
  },
459
466
  content: {
460
467
  label: 'baseButton__content',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instructure/ui-buttons",
3
- "version": "11.7.4-snapshot-52",
3
+ "version": "11.7.4-snapshot-53",
4
4
  "description": "Accessible button components",
5
5
  "author": "Instructure, Inc. Engineering and Product Design",
6
6
  "module": "./es/index.js",
@@ -16,28 +16,28 @@
16
16
  "dependencies": {
17
17
  "@babel/runtime": "^7.29.2",
18
18
  "keycode": "^2",
19
- "@instructure/console": "11.7.4-snapshot-52",
20
- "@instructure/emotion": "11.7.4-snapshot-52",
21
- "@instructure/shared-types": "11.7.4-snapshot-52",
22
- "@instructure/ui-a11y-content": "11.7.4-snapshot-52",
23
- "@instructure/ui-a11y-utils": "11.7.4-snapshot-52",
24
- "@instructure/ui-dom-utils": "11.7.4-snapshot-52",
25
- "@instructure/ui-color-utils": "11.7.4-snapshot-52",
26
- "@instructure/ui-position": "11.7.4-snapshot-52",
27
- "@instructure/ui-themes": "11.7.4-snapshot-52",
28
- "@instructure/ui-react-utils": "11.7.4-snapshot-52",
29
- "@instructure/ui-icons": "11.7.4-snapshot-52",
30
- "@instructure/ui-tooltip": "11.7.4-snapshot-52",
31
- "@instructure/ui-utils": "11.7.4-snapshot-52",
32
- "@instructure/ui-view": "11.7.4-snapshot-52"
19
+ "@instructure/emotion": "11.7.4-snapshot-53",
20
+ "@instructure/ui-a11y-content": "11.7.4-snapshot-53",
21
+ "@instructure/shared-types": "11.7.4-snapshot-53",
22
+ "@instructure/console": "11.7.4-snapshot-53",
23
+ "@instructure/ui-a11y-utils": "11.7.4-snapshot-53",
24
+ "@instructure/ui-dom-utils": "11.7.4-snapshot-53",
25
+ "@instructure/ui-position": "11.7.4-snapshot-53",
26
+ "@instructure/ui-react-utils": "11.7.4-snapshot-53",
27
+ "@instructure/ui-color-utils": "11.7.4-snapshot-53",
28
+ "@instructure/ui-tooltip": "11.7.4-snapshot-53",
29
+ "@instructure/ui-icons": "11.7.4-snapshot-53",
30
+ "@instructure/ui-themes": "11.7.4-snapshot-53",
31
+ "@instructure/ui-view": "11.7.4-snapshot-53",
32
+ "@instructure/ui-utils": "11.7.4-snapshot-53"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@testing-library/jest-dom": "^6.6.3",
36
36
  "@testing-library/react": "15.0.7",
37
37
  "@testing-library/user-event": "^14.6.1",
38
38
  "vitest": "^3.2.2",
39
- "@instructure/ui-axe-check": "11.7.4-snapshot-52",
40
- "@instructure/ui-babel-preset": "11.7.4-snapshot-52"
39
+ "@instructure/ui-babel-preset": "11.7.4-snapshot-53",
40
+ "@instructure/ui-axe-check": "11.7.4-snapshot-53"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "react": ">=18 <=19"
@@ -228,7 +228,10 @@ class BaseButton extends Component<BaseButtonProps> {
228
228
 
229
229
  const { hasOnlyIconVisible } = this
230
230
  const iconSize = buttonSizeToIconSize[size!]
231
- const iconColor = buttonColorToIconColor[color!]
231
+ const iconColor =
232
+ this.isDisabled && color === 'ai-secondary'
233
+ ? 'inherit'
234
+ : buttonColorToIconColor[color!]
232
235
  const wrappedIcon = (
233
236
  <span css={styles?.iconSVG}>
234
237
  {renderIconWithProps(renderIcon, iconSize, iconColor)}
@@ -269,7 +269,9 @@ const generateStyle = (
269
269
  boxShadow: componentTheme.secondaryGhostHoverBoxShadow
270
270
  },
271
271
  disabled: {
272
- background: 'transparent'
272
+ background: 'transparent',
273
+ borderColor: componentTheme.secondaryDisabledBorderColor,
274
+ color: componentTheme.secondaryDisabledTextColor
273
275
  }
274
276
  },
275
277
 
@@ -425,70 +427,76 @@ const generateStyle = (
425
427
  }
426
428
 
427
429
  return {
428
- baseButton: isEnabled
429
- ? {
430
- label: 'baseButton',
431
- appearance: 'none',
432
- textDecoration: 'none' /* for links styled as buttons */,
433
- touchAction: 'manipulation',
434
- // This sets the focus ring's border radius displayed by the `View`
435
- borderRadius:
436
- size === 'condensedSmall' || size === 'condensedMedium'
437
- ? componentTheme.borderRadiusSm
438
- : componentTheme.borderRadius,
439
- ...shapeVariants[shape!],
440
- // Prevents vertical stretching in flex parents with fixed height
441
- // Avoids background/focus ring distortion
442
- height: 'fit-content',
430
+ baseButton: {
431
+ ...(isEnabled
432
+ ? {
433
+ label: 'baseButton',
434
+ appearance: 'none',
435
+ textDecoration: 'none' /* for links styled as buttons */,
436
+ touchAction: 'manipulation',
437
+ // This sets the focus ring's border radius displayed by the `View`
438
+ borderRadius:
439
+ size === 'condensedSmall' || size === 'condensedMedium'
440
+ ? componentTheme.borderRadiusSm
441
+ : componentTheme.borderRadius,
442
+ ...shapeVariants[shape!],
443
+ // Prevents vertical stretching in flex parents with fixed height
444
+ // Avoids background/focus ring distortion
445
+ height: 'fit-content',
443
446
 
444
- '&::-moz-focus-inner': {
445
- border: '0' /* removes default dotted focus outline in Firefox */
446
- },
447
- '*': {
448
- pointerEvents:
449
- 'none' /* Ensures that button or link is always the event target */
450
- },
451
- '&:focus': {
452
- textDecoration: 'none'
453
- },
454
- '&:hover > [class$=-baseButton__content]':
455
- colorVariants[color!].hover,
456
- '&:active > [class$=-baseButton__content]':
457
- colorVariants[color!].active,
447
+ '&::-moz-focus-inner': {
448
+ border: '0' /* removes default dotted focus outline in Firefox */
449
+ },
450
+ '*': {
451
+ pointerEvents:
452
+ 'none' /* Ensures that button or link is always the event target */
453
+ },
454
+ '&:focus': {
455
+ textDecoration: 'none'
456
+ },
457
+ '&:hover > [class$=-baseButton__content]':
458
+ colorVariants[color!].hover,
459
+ '&:active > [class$=-baseButton__content]':
460
+ colorVariants[color!].active
461
+ }
462
+ : // When not enabled (disabled/readonly) skip all interactive styles (hover/active/focus)
463
+ {
464
+ textDecoration: 'none',
465
+ label: 'baseButton',
466
+ appearance: 'none'
467
+ }),
458
468
 
459
- //TODO not the greatest solution. Must be stronger than the same &&& enforcement of <View>
460
- ...(color === 'ai-secondary'
461
- ? {
462
- '&&&&&&&&&&': {
463
- padding: componentTheme.borderWidth,
464
- ...(shape !== 'circle'
465
- ? {
466
- borderRadius: `calc(${componentTheme.borderRadius} + ${componentTheme.borderWidth})`
467
- }
468
- : { borderRadius: componentTheme.borderRadiusFull }),
469
- '&::before': {
470
- content: '""',
471
- position: 'absolute',
472
- inset: '0',
473
- borderRadius: 'inherit',
474
- padding: componentTheme.borderWidth,
475
- background: `linear-gradient(to bottom, ${componentTheme.aiBorderTopGradientColor} 0%, ${componentTheme.aiBorderBottomGradientColor} 100%)`,
476
- WebkitMask:
477
- 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
478
- WebkitMaskComposite: 'xor',
479
- mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
480
- maskComposite: 'exclude',
481
- pointerEvents: 'none'
469
+ //TODO not the greatest solution. Must be stronger than the same &&& enforcement of <View>
470
+ // The ai-secondary border must render in both enabled and disabled states.
471
+ ...(color === 'ai-secondary'
472
+ ? {
473
+ '&&&&&&&&&&': {
474
+ padding: componentTheme.borderWidth,
475
+ ...(shape !== 'circle'
476
+ ? {
477
+ borderRadius: `calc(${componentTheme.borderRadius} + ${componentTheme.borderWidth})`
482
478
  }
483
- }
479
+ : { borderRadius: componentTheme.borderRadiusFull }),
480
+ '&::before': {
481
+ content: '""',
482
+ position: 'absolute',
483
+ inset: '0',
484
+ borderRadius: 'inherit',
485
+ padding: componentTheme.borderWidth,
486
+ background: isDisabled
487
+ ? componentTheme.aiSecondaryDisabledBorderColor
488
+ : `linear-gradient(to bottom, ${componentTheme.aiBorderTopGradientColor} 0%, ${componentTheme.aiBorderBottomGradientColor} 100%)`,
489
+ WebkitMask:
490
+ 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
491
+ WebkitMaskComposite: 'xor',
492
+ mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
493
+ maskComposite: 'exclude',
494
+ pointerEvents: 'none'
484
495
  }
485
- : {})
486
- }
487
- : {
488
- textDecoration: 'none',
489
- label: 'baseButton',
490
- appearance: 'none'
491
- },
496
+ }
497
+ }
498
+ : {})
499
+ },
492
500
  content: {
493
501
  label: 'baseButton__content',
494
502
  opacity: componentTheme.opacityBase,