From 3360f15c6ca5fb4e7470e1ef8a90b1ea9747c9d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20S=C3=A1ros?= Date: Tue, 17 Feb 2026 14:50:13 +0100 Subject: [PATCH 1/3] feat(ui-buttons): migrate buttons to updated theme Reworked Button, CondensedButton, and IconButton theming: - Removed individual component theme.ts files in favor of centralized BaseButton styles - Updated icon sizing inside buttons - Fixed button active state - Added condensed size and disabled variant styling - Set AI button to use transparent background - Migrated button wrapper components to new theme structure --- packages/ui-buttons/src/BaseButton/index.tsx | 24 +- packages/ui-buttons/src/BaseButton/props.ts | 2 +- packages/ui-buttons/src/BaseButton/styles.ts | 316 ++++++++++++------ packages/ui-buttons/src/Button/README.md | 13 + packages/ui-buttons/src/Button/index.tsx | 6 +- packages/ui-buttons/src/Button/props.ts | 2 +- packages/ui-buttons/src/Button/theme.ts | 25 -- .../ui-buttons/src/CondensedButton/index.tsx | 6 +- .../ui-buttons/src/CondensedButton/props.ts | 2 +- .../ui-buttons/src/CondensedButton/theme.ts | 25 -- packages/ui-buttons/src/IconButton/index.tsx | 6 +- packages/ui-buttons/src/IconButton/theme.ts | 25 -- 12 files changed, 244 insertions(+), 208 deletions(-) delete mode 100644 packages/ui-buttons/src/Button/theme.ts delete mode 100644 packages/ui-buttons/src/CondensedButton/theme.ts delete mode 100644 packages/ui-buttons/src/IconButton/theme.ts diff --git a/packages/ui-buttons/src/BaseButton/index.tsx b/packages/ui-buttons/src/BaseButton/index.tsx index 103d973438..e0319ad35d 100644 --- a/packages/ui-buttons/src/BaseButton/index.tsx +++ b/packages/ui-buttons/src/BaseButton/index.tsx @@ -28,11 +28,11 @@ import keycode from 'keycode' import { getElementType, getInteraction, - passthroughProps, - callRenderProp + passthroughProps } from '@instructure/ui-react-utils' import { isActiveElement } from '@instructure/ui-dom-utils' import { hasVisibleChildren } from '@instructure/ui-a11y-utils' +import { renderIconWithProps } from '@instructure/ui-icons' import { View } from '@instructure/ui-view' import type { ViewProps } from '@instructure/ui-view' @@ -41,10 +41,9 @@ import type { ViewProps } from '@instructure/ui-view' import { isSafari } from '@instructure/ui-utils' import { combineDataCid } from '@instructure/ui-utils' -import { withStyleRework as withStyle } from '@instructure/emotion' +import { withStyle } from '@instructure/emotion' import generateStyles from './styles' -import generateComponentTheme from './theme' import { allowedProps } from './props' import type { BaseButtonProps, BaseButtonStyleProps } from './props' @@ -55,7 +54,15 @@ category: components/utilities --- **/ -@withStyle(generateStyles, generateComponentTheme) +const buttonSizeToIconSize = { + small: 'sm', + medium: 'md', + large: 'lg', + condensedSmall: 'xs', + condensedMedium: 'xs' +} as const + +@withStyle(generateStyles) class BaseButton extends Component { static readonly componentId = 'BaseButton' @@ -201,7 +208,7 @@ class BaseButton extends Component { } renderChildren() { - const { renderIcon, children, styles } = this.props + const { renderIcon, children, styles, size } = this.props const wrappedChildren = {children} @@ -210,8 +217,11 @@ class BaseButton extends Component { } const { hasOnlyIconVisible } = this + const iconSize = buttonSizeToIconSize[size!] const wrappedIcon = ( - {callRenderProp(renderIcon)} + + {renderIconWithProps(renderIcon, iconSize, 'inherit')} + ) const flexChildren = hasOnlyIconVisible ? ( diff --git a/packages/ui-buttons/src/BaseButton/props.ts b/packages/ui-buttons/src/BaseButton/props.ts index 9a20f6c296..599205c1db 100644 --- a/packages/ui-buttons/src/BaseButton/props.ts +++ b/packages/ui-buttons/src/BaseButton/props.ts @@ -53,7 +53,7 @@ type BaseButtonOwnProps = { /** * The size of the `Button` */ - size?: 'small' | 'medium' | 'large' + size?: 'small' | 'medium' | 'large' | 'condensedSmall' | 'condensedMedium' /** * Provides a reference to the `Button`'s underlying html element. diff --git a/packages/ui-buttons/src/BaseButton/styles.ts b/packages/ui-buttons/src/BaseButton/styles.ts index 7837346d79..4ed10b7f77 100644 --- a/packages/ui-buttons/src/BaseButton/styles.ts +++ b/packages/ui-buttons/src/BaseButton/styles.ts @@ -22,29 +22,18 @@ * SOFTWARE. */ -import type { BaseButtonTheme } from '@instructure/shared-types' +import type { NewComponentTypes, SharedTokens } from '@instructure/ui-themes' import type { BaseButtonProps, BaseButtonStyleProps, BaseButtonStyle } from './props' -import { darken, lighten } from '@instructure/ui-color-utils' - -/** - * --- - * private: true - * --- - * Generates the style object from the theme and provided additional information - * @param {Object} componentTheme The theme variable object. - * @param {Object} props the props of the component, the style is applied to - * @param {Object} state the state of the component, the style is applied to - * @return {Object} The final style object, which will be used in the component - */ const generateStyle = ( - componentTheme: BaseButtonTheme, - props: BaseButtonProps, - state: BaseButtonStyleProps + componentTheme: NewComponentTypes['BaseButton'], + params: BaseButtonProps, + _sharedTokens: SharedTokens, + extraArgs: BaseButtonStyleProps ): BaseButtonStyle => { const { size, @@ -54,9 +43,17 @@ const generateStyle = ( withBackground, withBorder, isCondensed - } = props + } = params - const { isDisabled, hasOnlyIconVisible, isEnabled } = state + const { isDisabled, hasOnlyIconVisible, isEnabled } = extraArgs + + const gapForSize = { + small: componentTheme.gapButtonContentSm, + medium: componentTheme.gapButtonContentMd, + large: componentTheme.gapButtonContentLg, + condensedSmall: componentTheme.gapButtonContentSm, + condensedMedium: componentTheme.gapButtonContentSm + } const shapeVariants = { circle: { borderRadius: '50%' }, @@ -69,21 +66,12 @@ const generateStyle = ( fontSize: componentTheme.smallFontSize, paddingLeft: componentTheme.smallPaddingHorizontal, paddingRight: componentTheme.smallPaddingHorizontal, + minHeight: componentTheme.smallHeight, ...(hasOnlyIconVisible && { paddingLeft: 0, paddingRight: 0, - height: componentTheme.smallHeight, width: componentTheme.smallHeight }) - }, - children: { - paddingTop: componentTheme.smallPaddingTop, - paddingBottom: componentTheme.smallPaddingBottom - }, - iconSVG: { - fontSize: isCondensed - ? componentTheme.smallFontSize - : componentTheme.iconSizeSmall } }, medium: { @@ -91,21 +79,12 @@ const generateStyle = ( fontSize: componentTheme.mediumFontSize, paddingLeft: componentTheme.mediumPaddingHorizontal, paddingRight: componentTheme.mediumPaddingHorizontal, + minHeight: componentTheme.mediumHeight, ...(hasOnlyIconVisible && { paddingLeft: 0, paddingRight: 0, - height: componentTheme.mediumHeight, width: componentTheme.mediumHeight }) - }, - children: { - paddingTop: componentTheme.mediumPaddingTop, - paddingBottom: componentTheme.mediumPaddingBottom - }, - iconSVG: { - fontSize: isCondensed - ? componentTheme.mediumFontSize - : componentTheme.iconSizeMedium } }, large: { @@ -113,21 +92,38 @@ const generateStyle = ( fontSize: componentTheme.largeFontSize, paddingLeft: componentTheme.largePaddingHorizontal, paddingRight: componentTheme.largePaddingHorizontal, + minHeight: componentTheme.largeHeight, ...(hasOnlyIconVisible && { paddingLeft: 0, paddingRight: 0, - height: componentTheme.largeHeight, width: componentTheme.largeHeight }) - }, - children: { - paddingTop: componentTheme.largePaddingTop, - paddingBottom: componentTheme.largePaddingBottom - }, - iconSVG: { - fontSize: isCondensed - ? componentTheme.largeFontSize - : componentTheme.iconSizeLarge + } + }, + condensedSmall: { + content: { + fontSize: componentTheme.smallFontSize, + paddingLeft: componentTheme.smallPaddingHorizontal, + paddingRight: componentTheme.smallPaddingHorizontal, + height: componentTheme.heightXxs, + ...(hasOnlyIconVisible && { + paddingLeft: 0, + paddingRight: 0, + width: componentTheme.heightXxs + }) + } + }, + condensedMedium: { + content: { + fontSize: componentTheme.smallFontSize, + paddingLeft: componentTheme.smallPaddingHorizontal, + paddingRight: componentTheme.smallPaddingHorizontal, + height: componentTheme.heightXs, + ...(hasOnlyIconVisible && { + paddingLeft: 0, + paddingRight: 0, + width: componentTheme.heightXs + }) } } } @@ -135,7 +131,7 @@ const generateStyle = ( const colorVariants = { 'ai-primary': { default: { - color: componentTheme.primaryColor, + color: componentTheme.aiBaseTextColor, background: ` linear-gradient(to bottom, ${componentTheme.aiBackgroundTopGradientColor} 0%, ${componentTheme.aiBackgroundBottomGradientColor} 100%) padding-box, linear-gradient(to bottom, ${componentTheme.aiBorderTopGradientColor} 0%, ${componentTheme.aiBorderBottomGradientColor} 100%) border-box`, @@ -143,42 +139,44 @@ const generateStyle = ( borderColor: 'transparent', boxShadow: componentTheme.primaryBoxShadow }, - active: {}, + active: { + background: ` + linear-gradient(to bottom, ${componentTheme.aiActiveBackgroundTopGradientColor} 0%, ${componentTheme.aiActiveBackgroundBottomGradientColor} 100%) padding-box, + linear-gradient(to bottom, ${componentTheme.aiActiveBorderTopGradientColor} 0%, ${componentTheme.aiActiveBorderBottomGradientColor} 100%) border-box`, + borderStyle: 'solid', + borderColor: 'transparent', + color: componentTheme.aiActiveTextColor + }, hover: { background: ` - linear-gradient(to bottom, ${darken( - componentTheme.aiBackgroundTopGradientColor, - 10 - )} 0%, ${darken( - componentTheme.aiBackgroundBottomGradientColor, - 10 - )} 100%) padding-box, - linear-gradient(to bottom, ${darken( - componentTheme.aiBorderTopGradientColor, - 10 - )} 0%, ${darken( - componentTheme.aiBorderBottomGradientColor, - 10 - )} 100%) border-box`, + linear-gradient(to bottom, ${componentTheme.aiHoverBackgroundTopGradientColor} 0%, ${componentTheme.aiHoverBackgroundBottomGradientColor} 100%) padding-box, + linear-gradient(to bottom, ${componentTheme.aiHoverBorderTopGradientColor} 0%, ${componentTheme.aiHoverBorderBottomGradientColor} 100%) border-box`, borderStyle: 'solid', borderColor: 'transparent', + color: componentTheme.aiHoverTextColor, boxShadow: componentTheme.primaryHoverBoxShadow + }, + disabled: { + background: componentTheme.aiDisabledBackgroundColor, + borderColor: componentTheme.aiDisabledBorderColor, + color: componentTheme.aiDisabledTextColor } }, 'ai-secondary': { default: { boxShadow: componentTheme.primaryBoxShadow }, - active: {}, + active: { + background: ` + linear-gradient(to bottom, ${componentTheme.aiSecondaryActiveBackgroundTopGradientColor} 0%, ${componentTheme.aiSecondaryActiveBackgroundBottomGradientColor} 100%)` + }, hover: { background: ` - linear-gradient(to bottom, ${lighten( - componentTheme.aiBackgroundTopGradientColor, - 70 - )} 0%, ${lighten( - componentTheme.aiBackgroundBottomGradientColor, - 70 - )} 100%)` + linear-gradient(to bottom, ${componentTheme.aiSecondaryHoverBackgroundTopGradientColor} 0%, ${componentTheme.aiSecondaryHoverBackgroundBottomGradientColor} 100%)` + }, + disabled: { + borderColor: componentTheme.aiSecondaryDisabledBorderColor, + color: componentTheme.aiSecondaryDisabledTextColor } }, primary: withBackground @@ -191,11 +189,19 @@ const generateStyle = ( }, active: { background: componentTheme.primaryActiveBackground, - boxShadow: componentTheme.primaryActiveBoxShadow + color: componentTheme.primaryActiveTextColor, + borderColor: componentTheme.primaryActiveBorderColor }, hover: { background: componentTheme.primaryHoverBackground, - boxShadow: componentTheme.primaryHoverBoxShadow + boxShadow: componentTheme.primaryHoverBoxShadow, + color: componentTheme.primaryHoverTextColor, + borderColor: componentTheme.primaryHoverBorderColor + }, + disabled: { + background: componentTheme.primaryDisabledBackgroundColor, + borderColor: componentTheme.primaryDisabledBorderColor, + color: componentTheme.primaryDisabledTextColor } } : { @@ -207,11 +213,19 @@ const generateStyle = ( }, active: { background: componentTheme.primaryGhostActiveBackground, - boxShadow: componentTheme.primaryGhostActiveBoxShadow + color: componentTheme.tertiaryActiveTextColor, + borderColor: componentTheme.tertiaryActiveBorderColor }, hover: { background: componentTheme.primaryGhostHoverBackground, - boxShadow: componentTheme.primaryHoverBoxShadow + boxShadow: componentTheme.primaryHoverBoxShadow, + color: componentTheme.tertiaryHoverTextColor, + borderColor: componentTheme.tertiaryHoverBorderColor + }, + disabled: { + background: 'transparent', + borderColor: componentTheme.tertiaryDisabledBorderColor, + color: componentTheme.tertiaryDisabledTextColor } }, @@ -225,11 +239,19 @@ const generateStyle = ( }, active: { background: componentTheme.secondaryActiveBackground, - boxShadow: componentTheme.secondaryActiveBoxShadow + color: componentTheme.secondaryActiveTextColor, + borderColor: componentTheme.secondaryActiveBorderColor }, hover: { background: componentTheme.secondaryHoverBackground, - boxShadow: componentTheme.secondaryHoverBoxShadow + boxShadow: componentTheme.secondaryHoverBoxShadow, + color: componentTheme.secondaryHoverTextColor, + borderColor: componentTheme.secondaryHoverBorderColor + }, + disabled: { + background: componentTheme.secondaryDisabledBackgroundColor, + borderColor: componentTheme.secondaryDisabledBorderColor, + color: componentTheme.secondaryDisabledTextColor } } : { @@ -241,11 +263,13 @@ const generateStyle = ( }, active: { background: componentTheme.secondaryGhostActiveBackground, - boxShadow: componentTheme.secondaryGhostActiveBoxShadow }, hover: { background: componentTheme.secondaryGhostHoverBackground, boxShadow: componentTheme.secondaryGhostHoverBoxShadow + }, + disabled: { + background: 'transparent' } }, @@ -259,11 +283,19 @@ const generateStyle = ( }, active: { background: componentTheme.primaryInverseActiveBackground, - boxShadow: componentTheme.primaryInverseActiveBoxShadow + color: componentTheme.primaryOnColorActiveTextColor, + borderColor: componentTheme.primaryOnColorActiveBorderColor }, hover: { background: componentTheme.primaryInverseHoverBackground, - boxShadow: componentTheme.primaryInverseHoverBoxShadow + boxShadow: componentTheme.primaryInverseHoverBoxShadow, + color: componentTheme.primaryOnColorHoverTextColor, + borderColor: componentTheme.primaryOnColorHoverBorderColor + }, + disabled: { + background: componentTheme.primaryOnColorDisabledBackgroundColor, + borderColor: componentTheme.primaryOnColorDisabledBorderColor, + color: componentTheme.primaryOnColorDisabledTextColor } } : { @@ -275,11 +307,19 @@ const generateStyle = ( }, active: { background: componentTheme.primaryInverseGhostActiveBackground, - boxShadow: componentTheme.primaryInverseGhostActiveBoxShadow + color: componentTheme.secondaryOnColorActiveTextColor, + borderColor: componentTheme.secondaryOnColorActiveBorderColor }, hover: { background: componentTheme.primaryInverseGhostHoverBackground, - boxShadow: componentTheme.primaryInverseGhostHoverBoxShadow + boxShadow: componentTheme.primaryInverseGhostHoverBoxShadow, + color: componentTheme.secondaryOnColorHoverTextColor, + borderColor: componentTheme.secondaryOnColorHoverBorderColor + }, + disabled: { + background: 'transparent', + borderColor: componentTheme.secondaryOnColorDisabledBorderColor, + color: componentTheme.secondaryOnColorDisabledTextColor } }, @@ -293,11 +333,19 @@ const generateStyle = ( }, active: { background: componentTheme.successActiveBackground, - boxShadow: componentTheme.successActiveBoxShadow + color: componentTheme.successActiveTextColor, + borderColor: componentTheme.successActiveBorderColor }, hover: { background: componentTheme.successHoverBackground, - boxShadow: componentTheme.successHoverBoxShadow + boxShadow: componentTheme.successHoverBoxShadow, + color: componentTheme.successHoverTextColor, + borderColor: componentTheme.successHoverBorderColor + }, + disabled: { + background: componentTheme.successDisabledBackgroundColor, + borderColor: componentTheme.successDisabledBorderColor, + color: componentTheme.successDisabledTextColor } } : { @@ -309,11 +357,19 @@ const generateStyle = ( }, active: { background: componentTheme.successGhostActiveBackground, - boxShadow: componentTheme.successGhostActiveBoxShadow + color: componentTheme.successSecondaryActiveTextColor, + borderColor: componentTheme.successSecondaryActiveBorderColor }, hover: { background: componentTheme.successGhostHoverBackground, - boxShadow: componentTheme.successGhostHoverBoxShadow + boxShadow: componentTheme.successGhostHoverBoxShadow, + color: componentTheme.successSecondaryHoverTextColor, + borderColor: componentTheme.successSecondaryHoverBorderColor + }, + disabled: { + background: 'transparent', + borderColor: componentTheme.successSecondaryDisabledBorderColor, + color: componentTheme.successSecondaryDisabledTextColor } }, @@ -327,11 +383,19 @@ const generateStyle = ( }, active: { background: componentTheme.dangerActiveBackground, - boxShadow: componentTheme.dangerActiveBoxShadow + color: componentTheme.destructiveActiveTextColor, + borderColor: componentTheme.destructiveActiveBorderColor }, hover: { background: componentTheme.dangerHoverBackground, - boxShadow: componentTheme.dangerHoverBoxShadow + boxShadow: componentTheme.dangerHoverBoxShadow, + color: componentTheme.destructiveHoverTextColor, + borderColor: componentTheme.destructiveHoverBorderColor + }, + disabled: { + background: componentTheme.destructiveDisabledBackgroundColor, + borderColor: componentTheme.destructiveDisabledBorderColor, + color: componentTheme.destructiveDisabledTextColor } } : { @@ -343,11 +407,19 @@ const generateStyle = ( }, active: { background: componentTheme.dangerGhostActiveBackground, - boxShadow: componentTheme.dangerGhostActiveBoxShadow + color: componentTheme.destructiveSecondaryActiveTextColor, + borderColor: componentTheme.destructiveSecondaryActiveBorderColor }, hover: { background: componentTheme.dangerGhostHoverBackground, - boxShadow: componentTheme.dangerGhostHoverBoxShadow + boxShadow: componentTheme.dangerGhostHoverBoxShadow, + color: componentTheme.destructiveSecondaryHoverTextColor, + borderColor: componentTheme.destructiveSecondaryHoverBorderColor + }, + disabled: { + background: 'transparent', + borderColor: componentTheme.destructiveSecondaryDisabledBorderColor, + color: componentTheme.destructiveSecondaryDisabledTextColor } } } @@ -376,23 +448,35 @@ const generateStyle = ( '&:focus': { textDecoration: 'none' }, - '&:active > [class$=-baseButton__content]': - colorVariants[color!].active, '&:hover > [class$=-baseButton__content]': colorVariants[color!].hover, + '&:active > [class$=-baseButton__content]': + colorVariants[color!].active, //TODO not the greatest solution. Must be stronger than the same &&& enforcement of ...(color === 'ai-secondary' ? { '&&&&&&&&&&': { - background: ` - linear-gradient(to bottom, ${componentTheme.aiBorderTopGradientColor} 0%, ${componentTheme.aiBorderBottomGradientColor} 100%)`, padding: componentTheme.borderWidth, ...(shape !== 'circle' ? { borderRadius: `calc(${componentTheme.borderRadius} + ${componentTheme.borderWidth})` } - : { borderRadius: '50%' }) + : { borderRadius: '50%' }), + '&::before': { + content: '""', + position: 'absolute', + inset: '0', + borderRadius: 'inherit', + padding: componentTheme.borderWidth, + background: `linear-gradient(to bottom, ${componentTheme.aiBorderTopGradientColor} 0%, ${componentTheme.aiBorderBottomGradientColor} 100%)`, + WebkitMask: + 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)', + WebkitMaskComposite: 'xor', + mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)', + maskComposite: 'exclude', + pointerEvents: 'none' + } } } : {}) @@ -406,7 +490,8 @@ const generateStyle = ( label: 'baseButton__content', boxSizing: 'border-box', width: '100%', - display: 'block', + display: 'flex', + alignItems: 'center', direction: 'inherit', userSelect: 'none', transition: 'background 0.2s, transform 0.2s', @@ -427,11 +512,14 @@ const generateStyle = ( ...(color === 'ai-secondary' ? { border: 'none', - background: 'white', + background: 'transparent', transition: 'none' } : {}), + paddingTop: componentTheme.paddingVertical, + paddingBottom: componentTheme.paddingVertical, + ...sizeVariants[size!].content, ...colorVariants[color!].default, ...shapeVariants[shape!], @@ -440,8 +528,13 @@ const generateStyle = ( paddingLeft: 0, paddingRight: 0 }), + ...((size === 'condensedSmall' || size === 'condensedMedium') && { + background: 'transparent', + borderStyle: 'none' + }), ...(isDisabled && { - opacity: 0.5 + ...colorVariants[color!].disabled, + opacity: componentTheme.opacityDisabled }), ...(hasOnlyIconVisible && { lineHeight: 1 @@ -454,8 +547,7 @@ const generateStyle = ( children: { label: 'baseButton__children', display: 'block', - - ...sizeVariants[size!].children, + minWidth: 0, ...(isCondensed && { paddingTop: 0, @@ -463,10 +555,16 @@ const generateStyle = ( }), ...(color === 'ai-secondary' ? { - background: ` - linear-gradient(to bottom, ${componentTheme.aiBorderTopGradientColor} 0%, ${componentTheme.aiBorderBottomGradientColor} 100%)`, - backgroundClip: 'text', - color: 'transparent' + ...(isDisabled + ? { + color: componentTheme.aiSecondaryDisabledTextColor + } + : { + background: ` + linear-gradient(to bottom, ${componentTheme.aiSecondaryTextTopGradientColor} 0%, ${componentTheme.aiSecondaryTextBottomGradientColor} 100%)`, + backgroundClip: 'text', + color: 'transparent' + }) } : {}) }, @@ -474,9 +572,7 @@ const generateStyle = ( iconSVG: { label: 'baseButton__iconSVG', display: 'flex', - alignItems: 'center', - - ...sizeVariants[size!].iconSVG + alignItems: 'center' }, childrenLayout: { @@ -510,9 +606,7 @@ const generateStyle = ( label: 'baseButton__iconWrapper', boxSizing: 'border-box', minWidth: '0.0625rem', - paddingInlineEnd: isCondensed - ? componentTheme.iconTextGapCondensed - : componentTheme.iconTextGap, + paddingInlineEnd: gapForSize[size!], flexShrink: 0, maxWidth: '100%', overflowX: 'visible', diff --git a/packages/ui-buttons/src/Button/README.md b/packages/ui-buttons/src/Button/README.md index 8e25f5e567..aac87a194d 100644 --- a/packages/ui-buttons/src/Button/README.md +++ b/packages/ui-buttons/src/Button/README.md @@ -63,6 +63,19 @@ type: example ``` +There are also two condensed size variants for compact layouts: `condensedSmall` and `condensedMedium`. + +```js +--- +type: example +--- + + + + + +``` + ### Rendering icons in Buttons An icon can be rendered alongside the Button content using the `renderIcon` prop. Use [IconButton](IconButton) instead if your Button only displays an Icon with no other visual content. diff --git a/packages/ui-buttons/src/Button/index.tsx b/packages/ui-buttons/src/Button/index.tsx index 9e3f384e8a..2ef3e94ed0 100644 --- a/packages/ui-buttons/src/Button/index.tsx +++ b/packages/ui-buttons/src/Button/index.tsx @@ -26,9 +26,7 @@ import { Component } from 'react' import { getInteraction, passthroughProps } from '@instructure/ui-react-utils' -import { withStyleRework as withStyle } from '@instructure/emotion' - -import generateComponentTheme from './theme' +import { withStyle } from '@instructure/emotion' import { BaseButton } from '../BaseButton' import { allowedProps } from './props' @@ -40,7 +38,7 @@ category: components --- **/ // needed for listing the available theme variables on docs page -@withStyle(null, generateComponentTheme) +@withStyle(null, 'BaseButton') class Button extends Component { static readonly componentId = 'Button' diff --git a/packages/ui-buttons/src/Button/props.ts b/packages/ui-buttons/src/Button/props.ts index f139519679..6cf077f098 100644 --- a/packages/ui-buttons/src/Button/props.ts +++ b/packages/ui-buttons/src/Button/props.ts @@ -47,7 +47,7 @@ type ButtonOwnProps = { /** * The size of the `Button` */ - size?: 'small' | 'medium' | 'large' + size?: 'small' | 'medium' | 'large' | 'condensedSmall' | 'condensedMedium' /** * Provides a reference to the `Button`'s underlying html element. diff --git a/packages/ui-buttons/src/Button/theme.ts b/packages/ui-buttons/src/Button/theme.ts deleted file mode 100644 index 0810ff4ec1..0000000000 --- a/packages/ui-buttons/src/Button/theme.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 - present Instructure, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -export { default } from '../BaseButton/theme' diff --git a/packages/ui-buttons/src/CondensedButton/index.tsx b/packages/ui-buttons/src/CondensedButton/index.tsx index 73d086325a..fe5293a196 100644 --- a/packages/ui-buttons/src/CondensedButton/index.tsx +++ b/packages/ui-buttons/src/CondensedButton/index.tsx @@ -26,9 +26,7 @@ import { Component } from 'react' import { passthroughProps } from '@instructure/ui-react-utils' -import { withStyleRework as withStyle } from '@instructure/emotion' - -import generateComponentTheme from './theme' +import { withStyle } from '@instructure/emotion' import { BaseButton } from '../BaseButton' import { allowedProps } from './props' @@ -40,7 +38,7 @@ category: components --- **/ // needed for listing the available theme variables on docs page -@withStyle(null, generateComponentTheme) +@withStyle(null, 'BaseButton') class CondensedButton extends Component { static readonly componentId = 'CondensedButton' diff --git a/packages/ui-buttons/src/CondensedButton/props.ts b/packages/ui-buttons/src/CondensedButton/props.ts index 954df0cd32..c595e7aff9 100644 --- a/packages/ui-buttons/src/CondensedButton/props.ts +++ b/packages/ui-buttons/src/CondensedButton/props.ts @@ -47,7 +47,7 @@ type CondensedButtonOwnProps = { /** * The size of the `CondensedButton` */ - size?: 'small' | 'medium' | 'large' + size?: 'small' | 'medium' | 'large' | 'condensedSmall' | 'condensedMedium' /** * Provides a reference to the `CondensedButton`'s underlying html element. diff --git a/packages/ui-buttons/src/CondensedButton/theme.ts b/packages/ui-buttons/src/CondensedButton/theme.ts deleted file mode 100644 index 0810ff4ec1..0000000000 --- a/packages/ui-buttons/src/CondensedButton/theme.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 - present Instructure, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -export { default } from '../BaseButton/theme' diff --git a/packages/ui-buttons/src/IconButton/index.tsx b/packages/ui-buttons/src/IconButton/index.tsx index c6c22d22d5..4c2d31c365 100644 --- a/packages/ui-buttons/src/IconButton/index.tsx +++ b/packages/ui-buttons/src/IconButton/index.tsx @@ -28,9 +28,7 @@ import { passthroughProps } from '@instructure/ui-react-utils' import { ScreenReaderContent } from '@instructure/ui-a11y-content' import { combineDataCid } from '@instructure/ui-utils' -import { withStyleRework as withStyle } from '@instructure/emotion' - -import generateComponentTheme from './theme' +import { withStyle } from '@instructure/emotion' import { BaseButton } from '../BaseButton' import { allowedProps } from './props' @@ -43,7 +41,7 @@ category: components **/ // needed for listing the available theme variables on docs page -@withStyle(null, generateComponentTheme) +@withStyle(null, 'BaseButton') class IconButton extends Component { static readonly componentId = 'IconButton' diff --git a/packages/ui-buttons/src/IconButton/theme.ts b/packages/ui-buttons/src/IconButton/theme.ts deleted file mode 100644 index 0810ff4ec1..0000000000 --- a/packages/ui-buttons/src/IconButton/theme.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 - present Instructure, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -export { default } from '../BaseButton/theme' From 5c6e6e61eb978fafc8f96fd42f98c22b07f6feaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20S=C3=A1ros?= Date: Thu, 19 Feb 2026 15:16:40 +0100 Subject: [PATCH 2/3] feat(ui-buttons): use the new icons --- packages/ui-buttons/src/BaseButton/index.tsx | 26 ++- packages/ui-buttons/src/BaseButton/theme.ts | 214 ------------------ packages/ui-buttons/src/Button/README.md | 22 +- packages/ui-buttons/src/IconButton/README.md | 18 +- .../ui-buttons/src/ToggleButton/README.md | 4 +- .../ui-buttons/src/ToggleButton/index.tsx | 7 +- 6 files changed, 43 insertions(+), 248 deletions(-) delete mode 100644 packages/ui-buttons/src/BaseButton/theme.ts diff --git a/packages/ui-buttons/src/BaseButton/index.tsx b/packages/ui-buttons/src/BaseButton/index.tsx index e0319ad35d..79de0e6952 100644 --- a/packages/ui-buttons/src/BaseButton/index.tsx +++ b/packages/ui-buttons/src/BaseButton/index.tsx @@ -48,12 +48,6 @@ import generateStyles from './styles' import { allowedProps } from './props' import type { BaseButtonProps, BaseButtonStyleProps } from './props' -/** ---- -category: components/utilities ---- -**/ - const buttonSizeToIconSize = { small: 'sm', medium: 'md', @@ -62,6 +56,21 @@ const buttonSizeToIconSize = { condensedMedium: 'xs' } as const +const buttonColorToIconColor = { + 'primary': 'inherit', + 'primary-inverse': 'inherit', + 'secondary': 'inherit', + 'success': 'inherit', + 'danger': 'inherit', + 'ai-primary': 'inherit', + 'ai-secondary': 'ai' +} as const + +/** +--- +category: components/utilities +--- +**/ @withStyle(generateStyles) class BaseButton extends Component { static readonly componentId = 'BaseButton' @@ -208,7 +217,7 @@ class BaseButton extends Component { } renderChildren() { - const { renderIcon, children, styles, size } = this.props + const { renderIcon, children, styles, size, color } = this.props const wrappedChildren = {children} @@ -218,9 +227,10 @@ class BaseButton extends Component { const { hasOnlyIconVisible } = this const iconSize = buttonSizeToIconSize[size!] + const iconColor = buttonColorToIconColor[color!] const wrappedIcon = ( - {renderIconWithProps(renderIcon, iconSize, 'inherit')} + {renderIconWithProps(renderIcon, iconSize, iconColor)} ) diff --git a/packages/ui-buttons/src/BaseButton/theme.ts b/packages/ui-buttons/src/BaseButton/theme.ts deleted file mode 100644 index a2b5dbba41..0000000000 --- a/packages/ui-buttons/src/BaseButton/theme.ts +++ /dev/null @@ -1,214 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 - present Instructure, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import type { Theme, ThemeSpecificStyle } from '@instructure/ui-themes' -import { BaseButtonTheme } from '@instructure/shared-types' -import { alpha, darken } from '@instructure/ui-color-utils' - -const activeShadow = 'inset 0 0 0.1875rem 0.0625rem' - -/** - * Generates the theme object for the component from the theme and provided additional information - * @param {Object} theme The actual theme object. - * @return {Object} The final theme object with the overrides and component variables - */ -const generateComponentTheme = (theme: Theme): BaseButtonTheme => { - const { borders, colors, forms, spacing, typography, key: themeName } = theme - - const themeSpecificStyle: ThemeSpecificStyle = { - canvas: { - primaryColor: theme['ic-brand-button--primary-text']!, - primaryBorderColor: darken(theme['ic-brand-button--primary-bgd']!), - primaryBackground: theme['ic-brand-button--primary-bgd']!, - primaryHoverBackground: darken(theme['ic-brand-button--primary-bgd']!), - primaryActiveBackground: darken(theme['ic-brand-button--primary-bgd']!), - primaryActiveBoxShadow: `${activeShadow} ${theme[ - 'ic-brand-button--primary-bgd' - ]!}`, - primaryGhostColor: darken(theme['ic-brand-button--primary-bgd']!), - primaryGhostBorderColor: darken(theme['ic-brand-button--primary-bgd']!), - primaryGhostBackground: 'transparent', - primaryGhostHoverBackground: alpha( - darken(theme['ic-brand-button--primary-bgd']!), - 10 - ), - primaryGhostActiveBackground: 'transparent', - primaryGhostActiveBoxShadow: `${activeShadow} ${alpha( - theme['ic-brand-button--primary-bgd']!, - 28 - )}` - } - } - - const componentVariables: BaseButtonTheme = { - transform: 'none', - hoverTransform: 'none', - fontFamily: typography?.fontFamily, - fontWeight: typography?.fontWeightNormal, - textTransform: 'none', - letterSpacing: 'normal', - borderRadius: borders?.radiusMedium, - borderStyle: borders?.style, - borderWidth: borders?.widthSmall, - - smallHeight: forms?.inputHeightSmall, - smallFontSize: typography?.fontSizeSmall, - smallPaddingHorizontal: spacing?.xSmall, - smallPaddingTop: '0.375rem', - smallPaddingBottom: '0.3125rem', - - mediumHeight: forms?.inputHeightMedium, - mediumFontSize: typography?.fontSizeMedium, - mediumPaddingHorizontal: spacing?.small, - mediumPaddingTop: '0.5625rem', - mediumPaddingBottom: '0.5625rem', - - largeHeight: forms?.inputHeightLarge, - largeFontSize: typography?.fontSizeLarge, - largePaddingHorizontal: spacing?.medium, - largePaddingTop: '0.6875rem', - largePaddingBottom: '0.6875rem', - - lineHeight: typography?.lineHeightFit, - - iconSizeSmall: '1rem', - iconSizeMedium: '1.25rem', - iconSizeLarge: '1.625rem', - iconTextGap: spacing.xSmall, - iconTextGapCondensed: spacing.xxSmall, - - primaryColor: colors?.contrasts?.white1010, - primaryBorderColor: colors?.contrasts?.blue5782, - primaryBackground: colors?.contrasts?.blue4570, - primaryHoverBackground: colors?.contrasts?.blue5782, - primaryActiveBackground: colors?.contrasts?.blue5782, - primaryActiveBoxShadow: `${activeShadow} ${colors?.contrasts?.white1010}`, - primaryGhostColor: colors?.contrasts?.blue5782, - primaryGhostBorderColor: colors?.contrasts?.blue4570, - primaryGhostBackground: 'transparent', - primaryGhostHoverBackground: colors?.contrasts?.blue1212, - primaryGhostActiveBackground: 'transparent', - primaryGhostActiveBoxShadow: `${activeShadow} ${alpha( - colors?.contrasts?.blue1212, - 28 - )}`, - primaryBoxShadow: 'none', - primaryGhostBoxShadow: 'none', - primaryHoverBoxShadow: 'none', - primaryGhostHoverBoxShadow: 'none', - - secondaryColor: colors?.contrasts?.grey125125, - secondaryBorderColor: colors?.contrasts?.grey1424, - secondaryBackground: colors?.contrasts?.grey1111, - secondaryHoverBackground: colors?.contrasts?.grey1214, - secondaryActiveBackground: colors?.contrasts?.grey1214, - secondaryActiveBoxShadow: `${activeShadow} ${colors?.contrasts?.white1010}`, - secondaryGhostColor: colors?.contrasts?.grey125125, - secondaryGhostBorderColor: colors?.contrasts?.grey125125, - secondaryGhostBackground: 'transparent', - secondaryGhostHoverBackground: colors?.contrasts?.grey1111, - secondaryGhostActiveBackground: 'transparent', - secondaryGhostActiveBoxShadow: `${activeShadow} ${alpha( - colors?.contrasts?.grey125125, - 28 - )}`, - secondaryBoxShadow: 'none', - secondaryGhostBoxShadow: 'none', - secondaryHoverBoxShadow: 'none', - secondaryGhostHoverBoxShadow: 'none', - - successColor: colors?.contrasts?.white1010, - successBorderColor: colors?.contrasts?.green5782, - successBackground: colors?.contrasts?.green4570, - successHoverBackground: colors?.contrasts?.green5782, - successActiveBackground: colors?.contrasts?.green5782, - successActiveBoxShadow: `${activeShadow} ${colors?.contrasts?.white1010}`, - successGhostColor: colors?.contrasts?.green4570, - successGhostBorderColor: colors?.contrasts?.green4570, - successGhostBackground: 'transparent', - successGhostHoverBackground: alpha(colors?.contrasts?.green4570, 10), - successGhostActiveBackground: 'transparent', - successGhostActiveBoxShadow: `${activeShadow} ${alpha( - colors?.contrasts?.green4570, - 28 - )}`, - successBoxShadow: 'none', - successGhostBoxShadow: 'none', - successHoverBoxShadow: 'none', - successGhostHoverBoxShadow: 'none', - - dangerColor: colors?.contrasts?.white1010, - dangerBorderColor: colors?.contrasts?.red5782, - dangerBackground: colors?.contrasts?.red4570, - dangerHoverBackground: colors?.contrasts?.red5782, - dangerActiveBackground: colors?.contrasts?.red5782, - dangerActiveBoxShadow: `${activeShadow} ${colors?.contrasts?.white1010}`, - dangerGhostColor: colors?.contrasts?.red4570, - dangerGhostBorderColor: colors?.contrasts?.red4570, - dangerGhostBackground: 'transparent', - dangerGhostHoverBackground: alpha(colors?.contrasts?.red4570, 10), - dangerGhostActiveBackground: 'transparent', - dangerGhostActiveBoxShadow: `${activeShadow} ${alpha( - colors?.contrasts?.red4570, - 28 - )}`, - dangerBoxShadow: 'none', - dangerGhostBoxShadow: 'none', - dangerHoverBoxShadow: 'none', - dangerGhostHoverBoxShadow: 'none', - - primaryInverseColor: colors?.contrasts?.grey125125, - primaryInverseBorderColor: colors?.contrasts?.grey1214, - primaryInverseBackground: colors?.contrasts?.white1010, - primaryInverseHoverBackground: colors?.contrasts?.grey1111, - primaryInverseActiveBackground: colors?.contrasts?.white1010, - primaryInverseActiveBoxShadow: `${activeShadow} ${colors?.contrasts?.white1010}`, - primaryInverseGhostColor: colors?.contrasts?.white1010, - primaryInverseGhostBorderColor: colors?.contrasts?.white1010, - primaryInverseGhostBackground: 'transparent', - primaryInverseGhostHoverBackground: alpha(colors?.contrasts?.white1010, 10), - primaryInverseGhostActiveBackground: 'transparent', - primaryInverseGhostActiveBoxShadow: `${activeShadow} ${alpha( - colors?.contrasts?.white1010, - 28 - )}`, - primaryInverseBoxShadow: 'none', - primaryInverseGhostBoxShadow: 'none', - primaryInverseHoverBoxShadow: 'none', - primaryInverseGhostHoverBoxShadow: 'none', - - aiBackgroundTopGradientColor: colors?.contrasts?.violet4570, - aiBackgroundBottomGradientColor: colors?.contrasts?.sea4570, - aiBorderTopGradientColor: colors?.contrasts?.violet5790, - aiBorderBottomGradientColor: colors?.contrasts?.sea5790, - aiActiveBoxShadow: '0px 0px 5px 0px #013451 inset' - } - - return { - ...componentVariables, - ...themeSpecificStyle[themeName] - } -} - -export default generateComponentTheme diff --git a/packages/ui-buttons/src/Button/README.md b/packages/ui-buttons/src/Button/README.md index aac87a194d..785b025ca1 100644 --- a/packages/ui-buttons/src/Button/README.md +++ b/packages/ui-buttons/src/Button/README.md @@ -39,12 +39,12 @@ There is a specific need for `AI buttons`, which has an icon and gradient colors type: example --- - - - - - - + + + + + + ``` @@ -84,7 +84,7 @@ An icon can be rendered alongside the Button content using the `renderIcon` prop --- type: example --- - + ``` ### Text wrapping @@ -172,7 +172,7 @@ type: example withVisualDebug > + - + ``` @@ -281,7 +281,7 @@ type: example withBackground={this.state.withBackground} color={this.state.color} themeOverride={overrides}> - + diff --git a/packages/ui-buttons/src/IconButton/README.md b/packages/ui-buttons/src/IconButton/README.md index 4ef604af20..ed4b91c05b 100644 --- a/packages/ui-buttons/src/IconButton/README.md +++ b/packages/ui-buttons/src/IconButton/README.md @@ -9,7 +9,7 @@ It is not recommended to set the size of an icon inside an IconButton. Only use --- type: example --- - + ``` ### Accessibility @@ -20,7 +20,7 @@ Because the IconButton visually only renders an icon, a description is necessary --- type: example --- - + ``` Using [Tooltip](Tooltip) in conjunction with IconButton can also provide necessary context when the IconButton alone would be insufficient. @@ -34,7 +34,7 @@ type: example on={['hover', 'focus']} placement="bottom" > - + ``` @@ -45,8 +45,8 @@ type: example type: example --- - - + + ``` @@ -59,8 +59,8 @@ The `shape` prop specifies if the IconButton will render as a `rectangle` or `ci type: example --- - - + + ``` @@ -75,12 +75,12 @@ type: example - + - + diff --git a/packages/ui-buttons/src/ToggleButton/README.md b/packages/ui-buttons/src/ToggleButton/README.md index cddd98ffeb..0ee0cf4038 100644 --- a/packages/ui-buttons/src/ToggleButton/README.md +++ b/packages/ui-buttons/src/ToggleButton/README.md @@ -21,7 +21,7 @@ type: example { interaction={interaction} aria-pressed={status === 'pressed'} data-cid="ToggleButton" - > - {callRenderProp(renderIcon)} - + renderIcon={renderIcon} + /> ) } From c14d18d671fdde4fa051b8d6117005b58a9044ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20S=C3=A1ros?= Date: Fri, 20 Feb 2026 10:29:33 +0100 Subject: [PATCH 3/3] feat(ui-buttons): migrate closebutton --- .../src/ComponentThemeVariables.ts | 8 +--- packages/ui-buttons/src/CloseButton/index.tsx | 8 ++-- packages/ui-buttons/src/CloseButton/props.ts | 4 +- packages/ui-buttons/src/CloseButton/styles.ts | 17 +++---- packages/ui-buttons/src/CloseButton/theme.ts | 48 ------------------- 5 files changed, 17 insertions(+), 68 deletions(-) delete mode 100644 packages/ui-buttons/src/CloseButton/theme.ts diff --git a/packages/shared-types/src/ComponentThemeVariables.ts b/packages/shared-types/src/ComponentThemeVariables.ts index 1a87ad1a53..644add22dd 100644 --- a/packages/shared-types/src/ComponentThemeVariables.ts +++ b/packages/shared-types/src/ComponentThemeVariables.ts @@ -267,12 +267,6 @@ export type BaseButtonTheme = { aiActiveBoxShadow: string } -export type CloseButtonTheme = { - offsetMedium: Spacing['medium'] - offsetSmall: Spacing['small'] - offsetXSmall: Spacing['xSmall'] - zIndex: Stacking['above'] -} export type BylineTheme = { fontFamily: Typography['fontFamily'] @@ -1803,7 +1797,7 @@ export interface ThemeVariables { Breadcrumb: BreadcrumbTheme BaseButton: BaseButtonTheme Button: BaseButtonTheme - CloseButton: CloseButtonTheme + CloseButton: BaseButtonTheme CondensedButton: BaseButtonTheme IconButton: BaseButtonTheme Byline: BylineTheme diff --git a/packages/ui-buttons/src/CloseButton/index.tsx b/packages/ui-buttons/src/CloseButton/index.tsx index a1364f96d8..f4837c0ab0 100644 --- a/packages/ui-buttons/src/CloseButton/index.tsx +++ b/packages/ui-buttons/src/CloseButton/index.tsx @@ -28,10 +28,9 @@ import { IconXSolid } from '@instructure/ui-icons' import { ScreenReaderContent } from '@instructure/ui-a11y-content' import { getInteraction, passthroughProps } from '@instructure/ui-react-utils' -import { withStyleRework as withStyle } from '@instructure/emotion' +import { withStyle } from '@instructure/emotion' import generateStyle from './styles' -import generateComponentTheme from './theme' import { BaseButton } from '../BaseButton' import { allowedProps } from './props' @@ -42,7 +41,7 @@ import type { CloseButtonProps } from './props' category: components --- **/ -@withStyle(generateStyle, generateComponentTheme) +@withStyle(generateStyle, 'BaseButton') class CloseButton extends Component { static readonly componentId = 'CloseButton' @@ -104,6 +103,8 @@ class CloseButton extends Component { ...props } = this.props + const themeOverride = this.props.themeOverride + return ( { href={href} cursor={cursor} tabIndex={tabIndex} + themeOverride={themeOverride} data-cid="CloseButton" > {screenReaderLabel} diff --git a/packages/ui-buttons/src/CloseButton/props.ts b/packages/ui-buttons/src/CloseButton/props.ts index b85a96d1ae..4b44991779 100644 --- a/packages/ui-buttons/src/CloseButton/props.ts +++ b/packages/ui-buttons/src/CloseButton/props.ts @@ -31,7 +31,7 @@ import type { import type { ToProp, AsElementType, - CloseButtonTheme, + BaseButtonTheme, OtherHTMLAttributes } from '@instructure/shared-types' import type { Cursor } from '@instructure/shared-types' @@ -122,7 +122,7 @@ type PropKeys = keyof CloseButtonOwnProps type AllowedPropKeys = Readonly> type CloseButtonProps = CloseButtonOwnProps & - WithStyleProps & + WithStyleProps & OtherHTMLAttributes & ToProp diff --git a/packages/ui-buttons/src/CloseButton/styles.ts b/packages/ui-buttons/src/CloseButton/styles.ts index 81a33dca1f..358c603a14 100644 --- a/packages/ui-buttons/src/CloseButton/styles.ts +++ b/packages/ui-buttons/src/CloseButton/styles.ts @@ -22,7 +22,7 @@ * SOFTWARE. */ -import type { CloseButtonTheme } from '@instructure/shared-types' +import type { NewComponentTypes, SharedTokens } from '@instructure/ui-themes' import type { CloseButtonProps, CloseButtonStyle } from './props' /** @@ -32,20 +32,21 @@ import type { CloseButtonProps, CloseButtonStyle } from './props' * Generates the style object from the theme and provided additional information * @param {Object} componentTheme The theme variable object. * @param {Object} props the props of the component, the style is applied to - * @param {Object} state the state of the component, the style is applied to + * @param {Object} sharedTokens the shared design tokens * @return {Object} The final style object, which will be used in the component */ const generateStyle = ( - componentTheme: CloseButtonTheme, - props: CloseButtonProps + _componentTheme: NewComponentTypes['BaseButton'], + props: CloseButtonProps, + sharedTokens: SharedTokens ): CloseButtonStyle => { const { placement, offset } = props const offsetValueMap = { none: 0, - 'x-small': componentTheme.offsetXSmall, - small: componentTheme.offsetSmall, - medium: componentTheme.offsetMedium + 'x-small': sharedTokens.legacy.spacing.xSmall, + small: sharedTokens.legacy.spacing.small, + medium: sharedTokens.legacy.spacing.medium } const getOffsetStyle = () => { @@ -63,7 +64,7 @@ const generateStyle = ( return { closeButton: { label: 'closeButton', - zIndex: componentTheme.zIndex, + zIndex: 1, display: 'inline-block', ...(placement === 'static' ? { diff --git a/packages/ui-buttons/src/CloseButton/theme.ts b/packages/ui-buttons/src/CloseButton/theme.ts deleted file mode 100644 index 04f7fc90d5..0000000000 --- a/packages/ui-buttons/src/CloseButton/theme.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 - present Instructure, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import type { Theme } from '@instructure/ui-themes' -import { CloseButtonTheme } from '@instructure/shared-types' - -/** - * Generates the theme object for the component from the theme and provided additional information - * @param {Object} theme The actual theme object. - * @return {Object} The final theme object with the overrides and component variables - */ -const generateComponentTheme = (theme: Theme): CloseButtonTheme => { - const { spacing, stacking } = theme - - const componentVariables: CloseButtonTheme = { - offsetMedium: spacing?.medium, - offsetSmall: spacing?.small, - offsetXSmall: spacing?.xSmall, - zIndex: stacking?.above - } - - return { - ...componentVariables - } -} - -export default generateComponentTheme