]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-21656 Remove legacy buttons
authorJeremy Davis <jeremy.davis@sonarsource.com>
Thu, 7 Mar 2024 13:57:28 +0000 (14:57 +0100)
committersonartech <sonartech@sonarsource.com>
Thu, 7 Mar 2024 20:02:26 +0000 (20:02 +0000)
server/sonar-web/src/main/js/apps/settings/components/NewCodeDefinition.tsx
server/sonar-web/src/main/js/apps/settings/components/inputs/InputForFormattedText.tsx
server/sonar-web/src/main/js/apps/settings/styles.css
server/sonar-web/src/main/js/components/controls/buttons.css [deleted file]
server/sonar-web/src/main/js/components/controls/buttons.tsx [deleted file]
server/sonar-web/src/main/js/components/rules/MoreInfoRuleDescription.tsx
server/sonar-web/src/main/js/components/workspace/WorkspaceHeader.tsx
server/sonar-web/src/main/js/components/workspace/WorkspaceNavItem.tsx

index 8191401ce619b10463587af5c237f5d9caa6d5f8..6ee818fdb16a1ec3389159ac97aaa21af4a7c0b0 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+import { Spinner } from '@sonarsource/echoes-react';
 import classNames from 'classnames';
-import { Spinner } from 'design-system';
+import { ButtonPrimary, ButtonSecondary } from 'design-system';
 import React, { useCallback, useEffect } from 'react';
 import { FormattedMessage } from 'react-intl';
 import DocumentationLink from '../../../components/common/DocumentationLink';
-import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons';
 import NewCodeDefinitionDaysOption from '../../../components/new-code-definition/NewCodeDefinitionDaysOption';
 import NewCodeDefinitionPreviousVersionOption from '../../../components/new-code-definition/NewCodeDefinitionPreviousVersionOption';
 import { NewCodeDefinitionLevels } from '../../../components/new-code-definition/utils';
@@ -117,7 +117,7 @@ export default function NewCodeDefinition() {
                 </div>
 
                 <div className="settings-definition-right">
-                  <Spinner loading={isLoading}>
+                  <Spinner isLoading={isLoading}>
                     <form className="sw-flex sw-flex-col sw-items-stretch" onSubmit={onSubmit}>
                       <NewCodeDefinitionPreviousVersionOption
                         isDefault
@@ -127,7 +127,7 @@ export default function NewCodeDefinition() {
                         }
                       />
                       <NewCodeDefinitionDaysOption
-                        className="spacer-top sw-mb-4"
+                        className="sw-mt-2 sw-mb-4"
                         days={numberOfDays}
                         currentDaysValue={
                           newCodeDefinition?.type === NewCodeDefinitionType.NumberOfDays
@@ -148,25 +148,25 @@ export default function NewCodeDefinition() {
                       />
                       <div className="sw-mt-4">
                         <p
-                          className={classNames('spacer-bottom', {
+                          className={classNames('sw-mb-2', {
                             'sw-invisible': !isFormTouched,
                           })}
                         >
                           {translate('baseline.next_analysis_notice')}
                         </p>
-                        <Spinner className="spacer-right" loading={isSaving} />
+                        <Spinner className="sw-mr-2" isLoading={isSaving} />
                         {!isSaving && (
                           <>
-                            <SubmitButton disabled={!isFormTouched || !isValid}>
+                            <ButtonPrimary type="submit" disabled={!isFormTouched || !isValid}>
                               {translate('save')}
-                            </SubmitButton>
-                            <ResetButtonLink
-                              className="spacer-left"
+                            </ButtonPrimary>
+                            <ButtonSecondary
+                              className="sw-ml-2"
                               disabled={!isFormTouched}
                               onClick={resetNewCodeDefinition}
                             >
                               {translate('cancel')}
-                            </ResetButtonLink>
+                            </ButtonSecondary>
                           </>
                         )}
                       </div>
index de9029a024172bca9192405655c6f21ee22f2eb0..81310536cc705e9a164933161a99d8aff86d3d84 100644 (file)
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-import { InputTextArea } from 'design-system';
+import styled from '@emotion/styled';
+import {
+  ButtonSecondary,
+  HtmlFormatter,
+  InputTextArea,
+  PencilIcon,
+  themeBorder,
+  themeColor,
+} from 'design-system';
 import * as React from 'react';
 import FormattingTipsWithLink from '../../../../components/common/FormattingTipsWithLink';
-import { Button } from '../../../../components/controls/buttons';
-import EditIcon from '../../../../components/icons/EditIcon';
 import { translate } from '../../../../helpers/l10n';
 import { sanitizeUserInput } from '../../../../helpers/sanitize';
 import { DefaultSpecializedInputProps, getPropertyName } from '../../utils';
@@ -53,15 +59,26 @@ export default function InputForFormattedText(props: DefaultSpecializedInputProp
     </div>
   ) : (
     <>
-      <div
-        className="markdown-preview markdown"
-        // eslint-disable-next-line react/no-danger
-        dangerouslySetInnerHTML={{ __html: sanitizeUserInput(formattedValue ?? '') }}
-      />
-      <Button className="spacer-top" onClick={props.onEditing}>
-        <EditIcon className="spacer-right" />
+      <HtmlFormatter>
+        <FormattedPreviewBox
+          // eslint-disable-next-line react/no-danger
+          dangerouslySetInnerHTML={{ __html: sanitizeUserInput(formattedValue ?? '') }}
+        />
+      </HtmlFormatter>
+
+      <ButtonSecondary className="sw-mt-2" onClick={props.onEditing} icon={<PencilIcon />}>
         {translate('edit')}
-      </Button>
+      </ButtonSecondary>
     </>
   );
 }
+
+const FormattedPreviewBox = styled.div`
+  width: 450px;
+  background-color: ${themeColor('infoBackground')};
+  border: ${themeBorder('default', 'infoBorder')};
+  border-radius: 2px;
+  padding: 16px;
+  overflow-wrap: break-word;
+  line-height: 1.5;
+`;
index 2eaca9065a931078852825c59d74dfb0a1246e87..130b9aff0dcc1bde71ac5e82475ee3b57d53cc9c 100644 (file)
   justify-content: space-between;
   margin: 0px -16px;
 }
-
-.markdown-preview {
-  width: 450px;
-  background-color: var(--info50);
-  border: 1px solid var(--info200);
-  border-radius: 2px;
-  padding: 16px;
-  overflow-wrap: break-word;
-}
diff --git a/server/sonar-web/src/main/js/components/controls/buttons.css b/server/sonar-web/src/main/js/components/controls/buttons.css
deleted file mode 100644 (file)
index fb4a5db..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-.button {
-  display: inline-flex;
-  align-items: center;
-  justify-content: center;
-  vertical-align: middle;
-  height: var(--controlHeight);
-  line-height: calc(var(--controlHeight) - 2px);
-  padding: 0 var(--gridSize);
-  border: 1px solid var(--darkBlue);
-  border-radius: 2px;
-  box-sizing: border-box;
-  background: transparent;
-  color: var(--darkBlue);
-  font-weight: 600;
-  font-size: var(--smallFontSize);
-  text-decoration: none;
-  cursor: pointer;
-  transition:
-    border-color 0.2s ease,
-    box-shadow 0.2s ease,
-    background-color 0.2s ease;
-}
-
-.button:hover,
-.button.selected {
-  background: var(--darkBlue);
-  color: var(--white);
-}
-
-.button-primary {
-  background: var(--darkBlue);
-  border-color: var(--darkBlue);
-  color: var(--white);
-}
-
-.button-primary:hover {
-  background: var(--veryDarkBlue);
-  border-color: var(--veryDarkBlue);
-}
-
-.button-primary.button-light {
-  background: var(--blue);
-  border-color: var(--blue);
-  color: var(--white);
-}
-
-.button-primary.button-light:hover {
-  background: var(--darkBlue);
-  border-color: var(--darkBlue);
-}
-
-.button.disabled {
-  color: var(--disableGrayText) !important;
-  border-color: var(--disableGrayBorder) !important;
-  background: var(--disableGrayBg) !important;
-  cursor: not-allowed !important;
-}
-
-/* #region .button-red */
-.button-red {
-  border-color: var(--red);
-  color: var(--red);
-}
-
-.button-red:hover,
-.button-red.active {
-  background: var(--red);
-  color: var(--white);
-}
-
-/* #endregion */
-
-/* #region .button-success */
-.button-success {
-  border-color: var(--green);
-  color: var(--green);
-}
-
-.button-success:hover,
-.button-success.active {
-  background: var(--green);
-  color: var(--white);
-}
-
-/* #endregion */
-
-/* #region .button-plain */
-.button-plain {
-  box-sizing: border-box;
-  background: inherit;
-  color: inherit;
-  cursor: pointer;
-  border: 0;
-}
-
-.button-plain:disabled {
-  color: var(--disableGrayText) !important;
-  cursor: not-allowed !important;
-}
-
-/* #endregion */
-
-/* #region .button-link */
-.button-link {
-  display: inline-flex;
-  height: auto;
-  /* Keep this to not inherit the height from .button */
-  line-height: 1;
-  margin: 0;
-  padding: 0;
-  border: none;
-  border-radius: 0;
-  background: transparent;
-  color: var(--darkBlue);
-  border-bottom: 1px solid var(--primarya40);
-  font-weight: 400;
-  font-size: inherit;
-  transition:
-    border-color 0.2s ease,
-    box-shadow 0.2s ease,
-    color 0.2s ease,
-    border-bottom 0.2s ease;
-}
-
-.dropdown .button-link {
-  border-bottom: none;
-}
-
-.button-link:hover {
-  background: transparent;
-  color: var(--darkBlue);
-  border-bottom-color: var(--primary);
-}
-
-.button-link.disabled {
-  color: var(--secondFontColor) !important;
-  background: transparent !important;
-  cursor: default;
-}
-
-/* #endregion */
-
-.button-small {
-  height: var(--smallControlHeight);
-  line-height: 18px;
-  padding: 0 6px;
-  font-size: 11px;
-}
-
-.button-tiny {
-  height: var(--tinyControlHeight);
-  line-height: var(--tinyControlHeight);
-  padding: 0 calc(var(--gridSize) / 2);
-}
-
-.button-large {
-  height: var(--largeControlHeight);
-  padding: 0 16px;
-  font-size: var(--mediumFontSize);
-}
-
-.button-huge {
-  flex-direction: column;
-  padding: calc(2 * var(--gridSize)) var(--gridSize);
-  width: 180px;
-  height: 180px;
-  background-color: var(--white);
-  border: solid 1px var(--white);
-  border-radius: 3px;
-  transition: all 0.2s ease;
-}
-
-.button-huge:hover,
-.button-huge:focus,
-.button-huge:active {
-  background-color: var(--white);
-  color: var(--darkBlue);
-  transform: translateY(-2px);
-}
-
-/* #region .button-icon */
-.button-icon {
-  display: inline-flex;
-  justify-content: center;
-  align-items: center;
-  vertical-align: middle;
-  width: var(--controlHeight);
-  height: var(--controlHeight);
-  padding: 0;
-  border: none;
-  color: inherit;
-}
-
-.button-icon.button-small {
-  width: var(--smallControlHeight);
-  height: var(--smallControlHeight);
-  padding: 0;
-}
-
-.button-icon.button-small svg {
-  margin-top: 0;
-}
-
-.button-icon.button-tiny {
-  width: var(--tinyControlHeight);
-  height: var(--tinyControlHeight);
-  padding: 0;
-}
-
-.button-icon.button-tiny svg {
-  margin-top: 0;
-}
-
-.button-icon:hover,
-.button-icon:focus-visible {
-  background-color: currentColor;
-}
-
-.button-icon:not(.disabled):hover svg,
-.button-icon:not(.disabled):focus-visible svg {
-  color: var(--white);
-}
-
-.button.button-icon.disabled {
-  background: transparent !important;
-}
-
-/* #endregion */
-
-.button-list {
-  display: inline-flex;
-  justify-content: space-between;
-  height: auto;
-  border: 1px solid var(--barBorderColor);
-  padding: var(--gridSize);
-  margin: calc(var(--gridSize) / 2);
-  color: var(--secondFontColor);
-  font-weight: normal;
-}
-
-.button-list:hover {
-  background-color: white;
-  border-color: var(--blue);
-  color: var(--darkBlue);
-}
-
-.no-select {
-  user-select: none !important;
-}
-
-a[download].button.disabled {
-  pointer-events: none;
-}
diff --git a/server/sonar-web/src/main/js/components/controls/buttons.tsx b/server/sonar-web/src/main/js/components/controls/buttons.tsx
deleted file mode 100644 (file)
index 249395a..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import classNames from 'classnames';
-import * as React from 'react';
-import { colors } from '../../app/theme';
-import ChevronRightIcon from '../icons/ChevronRightIcon';
-import ClearIcon, { ClearIconProps } from '../icons/ClearIcon';
-import DeleteIcon from '../icons/DeleteIcon';
-import EditIcon from '../icons/EditIcon';
-import { IconProps } from '../icons/Icon';
-import './buttons.css';
-import Tooltip, { TooltipProps } from './Tooltip';
-
-type AllowedButtonAttributes = Pick<
-  React.ButtonHTMLAttributes<HTMLButtonElement>,
-  | 'aria-label'
-  | 'className'
-  | 'disabled'
-  | 'id'
-  | 'style'
-  | 'title'
-  | 'onFocus'
-  | 'onBlur'
-  | 'onMouseOver'
-  | 'onMouseLeave'
-  | 'tabIndex'
-  | 'role'
->;
-
-interface ButtonProps extends AllowedButtonAttributes {
-  autoFocus?: boolean;
-  children?: React.ReactNode;
-  innerRef?: React.Ref<HTMLButtonElement>;
-  name?: string;
-  onClick?: () => void;
-  preventDefault?: boolean;
-  stopPropagation?: boolean;
-  type?: 'button' | 'submit' | 'reset';
-}
-
-export class Button extends React.PureComponent<ButtonProps> {
-  handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
-    const { disabled, onClick, preventDefault = true, stopPropagation = false } = this.props;
-
-    if (preventDefault || disabled) {
-      event.preventDefault();
-    }
-    if (stopPropagation) {
-      event.stopPropagation();
-    }
-
-    if (onClick && !disabled) {
-      onClick();
-    }
-  };
-
-  render() {
-    const {
-      className,
-      disabled,
-      innerRef,
-      onClick,
-      preventDefault,
-      stopPropagation,
-      type = 'button',
-      ...props
-    } = this.props;
-
-    // Instead of undoing button style we simply not apply the class.
-    const isPlain = className && className.indexOf('button-plain') !== -1;
-    return (
-      <button
-        {...props}
-        aria-disabled={disabled}
-        disabled={disabled}
-        className={classNames(isPlain ? '' : 'button', className, { disabled })}
-        id={this.props.id}
-        onClick={this.handleClick}
-        ref={this.props.innerRef}
-        // eslint-disable-next-line react/button-has-type
-        type={type}
-      />
-    );
-  }
-}
-
-export function ButtonLink({ className, ...props }: ButtonProps) {
-  return <Button {...props} className={classNames('button-link', className)} />;
-}
-
-export function ButtonPlain({ className, ...props }: ButtonProps) {
-  return <Button {...props} className={classNames('button-plain', className)} />;
-}
-
-export function SubmitButton(props: Omit<ButtonProps, 'type'>) {
-  // do not prevent default to actually submit a form
-  return <Button {...props} preventDefault={false} type="submit" />;
-}
-
-export function ResetButtonLink(props: Omit<ButtonProps, 'type'>) {
-  return <ButtonLink {...props} type="reset" />;
-}
-
-export interface ButtonIconProps extends ButtonProps {
-  'aria-label'?: string;
-  'aria-labelledby'?: string;
-  className?: string;
-  color?: string;
-  onClick?: () => void;
-  tooltip?: React.ReactNode;
-  tooltipProps?: Partial<TooltipProps>;
-}
-
-export function ButtonIcon(props: ButtonIconProps) {
-  const { className, color, tooltip, tooltipProps, ...other } = props;
-  return (
-    <Tooltip mouseEnterDelay={0.4} overlay={tooltip} {...tooltipProps}>
-      <Button
-        className={classNames(className, 'button-icon')}
-        stopPropagation
-        style={{ color: color || colors.darkBlue }}
-        {...other}
-      />
-    </Tooltip>
-  );
-}
-
-interface ClearButtonProps extends ButtonIconProps {
-  className?: string;
-  iconProps?: ClearIconProps;
-  onClick?: () => void;
-}
-
-export function ClearButton({ color, iconProps = {}, ...props }: ClearButtonProps) {
-  return (
-    <ButtonIcon color={color || colors.gray60} {...props}>
-      <ClearIcon {...iconProps} />
-    </ButtonIcon>
-  );
-}
-
-interface ActionButtonProps extends ButtonIconProps {
-  className?: string;
-  iconProps?: IconProps;
-  onClick?: () => void;
-}
-
-export function DeleteButton({ iconProps = {}, ...props }: ActionButtonProps) {
-  return (
-    <ButtonIcon color={colors.red} {...props}>
-      <DeleteIcon {...iconProps} />
-    </ButtonIcon>
-  );
-}
-
-export function EditButton({ iconProps = {}, ...props }: ActionButtonProps) {
-  return (
-    <ButtonIcon {...props}>
-      <EditIcon {...iconProps} />
-    </ButtonIcon>
-  );
-}
-
-export function ListButton({ className, children, ...props }: ButtonProps) {
-  return (
-    <Button className={classNames('button-list', className)} {...props}>
-      {children}
-      <ChevronRightIcon />
-    </Button>
-  );
-}
index 7fa2d76ab28ac0dfecca68d065f6ab9428d6f7c7..2023eead1391140886436ec662b4155b35e9d2c0 100644 (file)
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import styled from '@emotion/styled';
-import { FlagMessage, SubTitle, themeBorder, themeColor } from 'design-system';
+import { ButtonSecondary, FlagMessage, SubTitle, themeBorder, themeColor } from 'design-system';
 import * as React from 'react';
 import { RuleDescriptionSection } from '../../apps/coding-rules/rule';
 import { translate } from '../../helpers/l10n';
 import { Dict } from '../../types/types';
-import { ButtonLink } from '../controls/buttons';
 import RuleDescription from './RuleDescription';
 import DefenseInDepth from './educationPrinciples/DefenseInDepth';
 import NeverTrustUserInput from './educationPrinciples/NeverTrustUserInput';
@@ -63,17 +62,16 @@ export default class MoreInfoRuleDescription extends React.PureComponent<Props>
       <div className="sw-my-6 rule-desc">
         {displayEducationalPrinciplesNotification && (
           <FlagMessage variant="info">
-            <p className="little-spacer-bottom little-spacer-top">
-              {translate('coding_rules.more_info.notification_message')}
-            </p>
+            <p className="sw-my-1">{translate('coding_rules.more_info.notification_message')}</p>
 
-            <ButtonLink
+            <ButtonSecondary
+              className="sw-whitespace-nowrap"
               onClick={() => {
                 this.handleNotificationScroll();
               }}
             >
               {translate('coding_rules.more_info.scroll_message')}
-            </ButtonLink>
+            </ButtonSecondary>
           </FlagMessage>
         )}
 
index f248732cddd41eac735917481672bc1b77309386..f4f9f5bb0a4c43742effe142812a0e1a4a042448 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+import { IconProps, InteractiveIcon } from 'design-system';
 import * as React from 'react';
 import { DraggableCore, DraggableData } from 'react-draggable';
-import { ButtonIcon } from '../../components/controls/buttons';
 import ClearIcon from '../../components/icons/ClearIcon';
 import CollapseIcon from '../../components/icons/CollapseIcon';
 import ExpandIcon from '../../components/icons/ExpandIcon';
-import { IconProps } from '../../components/icons/Icon';
 import MinimizeIcon from '../../components/icons/MinimizeIcon';
 import { translate } from '../../helpers/l10n';
+import Tooltip from '../controls/Tooltip';
 
 export interface Props {
   children: React.ReactNode;
@@ -55,27 +55,27 @@ export default class WorkspaceHeader extends React.PureComponent<Props> {
           <WorkspaceHeaderButton
             icon={MinimizeIcon}
             onClick={this.props.onCollapse}
-            tooltip="workspace.minimize"
+            tooltipContent="workspace.minimize"
           />
 
           {this.props.maximized ? (
             <WorkspaceHeaderButton
               icon={CollapseIcon}
               onClick={this.props.onMinimize}
-              tooltip="workspace.normal_size"
+              tooltipContent="workspace.normal_size"
             />
           ) : (
             <WorkspaceHeaderButton
               icon={ExpandIcon}
               onClick={this.props.onMaximize}
-              tooltip="workspace.full_window"
+              tooltipContent="workspace.full_window"
             />
           )}
 
           <WorkspaceHeaderButton
             icon={ClearIcon}
             onClick={this.props.onClose}
-            tooltip="workspace.close"
+            tooltipContent="workspace.close"
           />
         </div>
       </header>
@@ -84,21 +84,22 @@ export default class WorkspaceHeader extends React.PureComponent<Props> {
 }
 
 interface WorkspaceHeaderButtonProps {
-  icon: React.FC<React.PropsWithChildren<IconProps>>;
+  icon: React.ComponentType<React.PropsWithChildren<IconProps>>;
   onClick: () => void;
-  tooltip: string;
+  tooltipContent: string;
 }
 
-function WorkspaceHeaderButton({ icon: Icon, onClick, tooltip }: WorkspaceHeaderButtonProps) {
+function WorkspaceHeaderButton({ icon, onClick, tooltipContent }: WorkspaceHeaderButtonProps) {
   return (
-    <ButtonIcon
-      className="workspace-header-icon"
-      aria-label={translate(tooltip)}
-      color="#fff"
-      onClick={onClick}
-      tooltip={translate(tooltip)}
-    >
-      <Icon fill={undefined} />
-    </ButtonIcon>
+    <Tooltip overlay={translate(tooltipContent)}>
+      <InteractiveIcon
+        className="workspace-header-icon"
+        aria-label={translate(tooltipContent)}
+        Icon={icon}
+        currentColor
+        onClick={onClick}
+        size="small"
+      />
+    </Tooltip>
   );
 }
index 12402c2029ccf72e13dbfc42fdf164ab34c1f6ff..d687959befc4f6a405fa4cfe154e8addcda13679 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+import styled from '@emotion/styled';
+import { CloseIcon, InteractiveIcon } from 'design-system';
 import * as React from 'react';
-import { ClearButton } from '../../components/controls/buttons';
+import { translate } from '../../helpers/l10n';
 
 export interface Props {
   children: React.ReactNode;
@@ -35,17 +37,23 @@ export default class WorkspaceNavItem extends React.PureComponent<Props> {
 
   render() {
     return (
-      <li className="workspace-nav-item">
+      <StyledWorkspaceNavItem className="workspace-nav-item">
         <a className="workspace-nav-item-link" href="#" onClick={this.handleNameClick}>
           {this.props.children}
         </a>
-        <ClearButton
-          className="js-close workspace-nav-item-close workspace-header-icon button-small little-spacer-left"
-          color="#fff"
-          iconProps={{ size: 12 }}
+        <InteractiveIcon
+          aria-label={translate('close')}
+          className="js-close sw-ml-1 sw-absolute sw-right-1 sw-top-1"
           onClick={this.props.onClose}
+          currentColor
+          Icon={CloseIcon}
+          size="small"
         />
-      </li>
+      </StyledWorkspaceNavItem>
     );
   }
 }
+
+const StyledWorkspaceNavItem = styled.li`
+  color: white;
+`;