diff --git a/superset-frontend/src/components/IconButton/IconButton.stories.tsx b/superset-frontend/src/components/IconButton/IconButton.stories.tsx
index 0cc10f32f82ba26a330bdbecc972a8497c18fe04..3b47e4a0c321b8d602ae81c897ad2ccfac5896ed 100644
--- a/superset-frontend/src/components/IconButton/IconButton.stories.tsx
+++ b/superset-frontend/src/components/IconButton/IconButton.stories.tsx
@@ -16,42 +16,37 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import IconButton, { IconButtonProps } from '.';
+import { Meta, StoryObj } from '@storybook/react';
+import { IconButton } from 'src/components/IconButton';
 
-export default {
-  title: 'IconButton',
+const meta: Meta<typeof IconButton> = {
+  title: 'Components/IconButton',
   component: IconButton,
+  argTypes: {
+    onClick: { action: 'clicked' },
+  },
+  parameters: {
+    a11y: {
+      enabled: true,
+    },
+  },
 };
 
-export const InteractiveIconButton = (args: IconButtonProps) => (
-  <IconButton
-    buttonText={args.buttonText}
-    altText={args.altText}
-    icon={args.icon}
-    href={args.href}
-    target={args.target}
-    htmlType={args.htmlType}
-  />
-);
+export default meta;
 
-InteractiveIconButton.args = {
-  buttonText: 'This is the IconButton text',
-  altText: 'This is an example of non-default alt text',
-  href: 'https://preset.io/',
-  target: '_blank',
+type Story = StoryObj<typeof IconButton>;
+
+export const Default: Story = {
+  args: {
+    buttonText: 'Default IconButton',
+    altText: 'Default icon button alt text',
+  },
 };
 
-InteractiveIconButton.argTypes = {
-  icon: {
-    defaultValue: '/images/icons/sql.svg',
-    control: {
-      type: 'select',
-    },
-    options: [
-      '/images/icons/sql.svg',
-      '/images/icons/server.svg',
-      '/images/icons/image.svg',
-      'Click to see example alt text',
-    ],
+export const CustomIcon: Story = {
+  args: {
+    buttonText: 'Custom icon IconButton',
+    altText: 'Custom icon button alt text',
+    icon: '/images/sqlite.png',
   },
 };
diff --git a/superset-frontend/src/components/IconButton/IconButton.test.jsx b/superset-frontend/src/components/IconButton/IconButton.test.jsx
deleted file mode 100644
index aa37d8949091d5d7ffe2e2c8074e14d127a38512..0000000000000000000000000000000000000000
--- a/superset-frontend/src/components/IconButton/IconButton.test.jsx
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import { render, screen } from 'spec/helpers/testing-library';
-import IconButton from 'src/components/IconButton';
-
-const defaultProps = {
-  buttonText: 'This is the IconButton text',
-  icon: '/images/icons/sql.svg',
-};
-
-describe('IconButton', () => {
-  it('renders an IconButton', () => {
-    render(<IconButton {...defaultProps} />);
-
-    const icon = screen.getByRole('img');
-    const buttonText = screen.getByText(/this is the iconbutton text/i);
-
-    expect(icon).toBeVisible();
-    expect(buttonText).toBeVisible();
-  });
-});
diff --git a/superset-frontend/src/components/IconButton/IconButton.test.tsx b/superset-frontend/src/components/IconButton/IconButton.test.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..dc45fe003ecc6a8d886791e88f64e00a1eccaa43
--- /dev/null
+++ b/superset-frontend/src/components/IconButton/IconButton.test.tsx
@@ -0,0 +1,90 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { render, screen, fireEvent } from 'spec/helpers/testing-library';
+import { IconButton } from 'src/components/IconButton';
+
+const defaultProps = {
+  buttonText: 'This is the IconButton text',
+  icon: '/images/icons/sql.svg',
+};
+
+describe('IconButton', () => {
+  it('renders an IconButton with icon and text', () => {
+    render(<IconButton {...defaultProps} />);
+
+    const icon = screen.getByRole('img');
+    const buttonText = screen.getByText(/this is the iconbutton text/i);
+
+    expect(icon).toBeVisible();
+    expect(buttonText).toBeVisible();
+  });
+
+  it('is keyboard accessible and has correct aria attributes', () => {
+    render(<IconButton {...defaultProps} />);
+
+    const button = screen.getByRole('button');
+
+    expect(button).toHaveAttribute('tabIndex', '0');
+    expect(button).toHaveAttribute('aria-label', defaultProps.buttonText);
+  });
+
+  it('handles Enter and Space key presses', () => {
+    const mockOnClick = jest.fn();
+    render(<IconButton {...defaultProps} onClick={mockOnClick} />);
+
+    const button = screen.getByRole('button');
+
+    fireEvent.keyDown(button, { key: 'Enter', code: 'Enter' });
+    expect(mockOnClick).toHaveBeenCalledTimes(1);
+
+    fireEvent.keyDown(button, { key: ' ', code: 'Space' });
+    expect(mockOnClick).toHaveBeenCalledTimes(2);
+  });
+
+  it('uses custom alt text when provided', () => {
+    const customAltText = 'Custom Alt Text';
+    render(
+      <IconButton
+        buttonText="Custom Alt Text Button"
+        icon="/images/icons/sql.svg"
+        altText={customAltText}
+      />,
+    );
+
+    const icon = screen.getByAltText(customAltText);
+    expect(icon).toBeVisible();
+  });
+
+  it('displays tooltip with button text', () => {
+    render(<IconButton {...defaultProps} />);
+
+    const tooltipTrigger = screen.getByText(/this is the iconbutton text/i);
+    expect(tooltipTrigger).toBeVisible();
+  });
+
+  it('calls onClick handler when clicked', () => {
+    const mockOnClick = jest.fn();
+    render(<IconButton {...defaultProps} onClick={mockOnClick} />);
+
+    const button = screen.getByRole('button');
+    fireEvent.click(button);
+
+    expect(mockOnClick).toHaveBeenCalledTimes(1);
+  });
+});
diff --git a/superset-frontend/src/components/IconButton/index.tsx b/superset-frontend/src/components/IconButton/index.tsx
index f6b0650776f48eb63285dea46f80b83edf9089d3..b8ec447a5ea70b4ff701d118b2cb09b3c326182c 100644
--- a/superset-frontend/src/components/IconButton/index.tsx
+++ b/superset-frontend/src/components/IconButton/index.tsx
@@ -16,129 +16,90 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { styled } from '@superset-ui/core';
-import Button, { ButtonProps as AntdButtonProps } from 'src/components/Button';
+
+// eslint-disable-next-line
+import { Typography } from 'src/components';
+import { Tooltip } from 'src/components/Tooltip';
+import Card, { CardProps } from 'src/components/Card';
 import { Icons } from 'src/components/Icons';
-import LinesEllipsis from 'react-lines-ellipsis';
+import { SupersetTheme, css } from '@superset-ui/core';
 
-export interface IconButtonProps extends AntdButtonProps {
+export interface IconButtonProps extends CardProps {
   buttonText: string;
   icon: string;
   altText?: string;
 }
 
-const StyledButton = styled(Button)`
-  height: auto;
-  display: flex;
-  flex-direction: column;
-  padding: 0;
-`;
-
-const StyledImage = styled.div`
-  padding: ${({ theme }) => theme.gridUnit * 4}px;
-  height: ${({ theme }) => theme.gridUnit * 18}px;
-  margin: ${({ theme }) => theme.gridUnit * 3}px 0;
-
-  .default-db-icon {
-    font-size: 36px;
-    color: ${({ theme }) => theme.colors.grayscale.base};
-    margin-right: 0;
-    span:first-of-type {
-      margin-right: 0;
-    }
-  }
-
-  &:first-of-type {
-    margin-right: 0;
-  }
-
-  img {
-    width: ${({ theme }) => theme.gridUnit * 10}px;
-    height: ${({ theme }) => theme.gridUnit * 10}px;
-    margin: 0;
-    &:first-of-type {
-      margin-right: 0;
-    }
-  }
-  svg {
-    &:first-of-type {
-      margin-right: 0;
+const IconButton: React.FC<IconButtonProps> = ({
+  buttonText,
+  icon,
+  altText,
+  ...cardProps
+}) => {
+  const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
+    if (e.key === 'Enter' || e.key === ' ') {
+      if (cardProps.onClick) {
+        (cardProps.onClick as React.EventHandler<React.SyntheticEvent>)(e);
+      }
+      if (e.key === ' ') {
+        e.preventDefault();
+      }
     }
-  }
-`;
-
-const StyledInner = styled.div`
-  max-height: calc(1.5em * 2);
-  white-space: break-spaces;
-
-  &:first-of-type {
-    margin-right: 0;
-  }
-
-  .LinesEllipsis {
-    &:first-of-type {
-      margin-right: 0;
-    }
-  }
-`;
-
-const StyledBottom = styled.div`
-  padding: ${({ theme }) => theme.gridUnit * 4}px 0;
-  border-radius: 0 0 ${({ theme }) => theme.borderRadius}px
-    ${({ theme }) => theme.borderRadius}px;
-  background-color: ${({ theme }) => theme.colors.grayscale.light4};
-  width: 100%;
-  line-height: 1.5em;
-  overflow: hidden;
-  white-space: no-wrap;
-  text-overflow: ellipsis;
-
-  &:first-of-type {
-    margin-right: 0;
-  }
-`;
+    cardProps.onKeyDown?.(e);
+  };
 
-const IconButton = styled(
-  ({ icon, altText, buttonText, ...props }: IconButtonProps) => (
-    <StyledButton {...props}>
-      <StyledImage>
-        {icon && <img src={icon} alt={altText} />}
-        {!icon && (
-          <Icons.DatabaseOutlined
-            className="default-db-icon"
-            aria-label="default-icon"
-          />
-        )}
-      </StyledImage>
+  const renderIcon = () => {
+    const iconContent = icon ? (
+      <img
+        src={icon}
+        alt={altText || buttonText}
+        css={css`
+          width: 100%;
+          height: 120px;
+          object-fit: contain;
+        `}
+      />
+    ) : (
+      <div
+        css={css`
+          display: flex;
+          align-content: center;
+          align-items: center;
+          height: 120px;
+        `}
+      >
+        <Icons.DatabaseOutlined
+          css={css`
+            font-size: 48px;
+          `}
+          aria-label="default-icon"
+        />
+      </div>
+    );
 
-      <StyledBottom>
-        <StyledInner>
-          <LinesEllipsis
-            text={buttonText}
-            maxLine="2"
-            basedOn="words"
-            trimRight
-          />
-        </StyledInner>
-      </StyledBottom>
-    </StyledButton>
-  ),
-)`
-  text-transform: none;
-  background-color: ${({ theme }) => theme.colors.grayscale.light5};
-  font-weight: ${({ theme }) => theme.typography.weights.normal};
-  color: ${({ theme }) => theme.colors.grayscale.dark2};
-  border: 1px solid ${({ theme }) => theme.colors.grayscale.light2};
-  margin: 0;
-  width: 100%;
+    return iconContent;
+  };
 
-  &:hover,
-  &:focus {
-    background-color: ${({ theme }) => theme.colors.grayscale.light5};
-    color: ${({ theme }) => theme.colors.grayscale.dark2};
-    border: 1px solid ${({ theme }) => theme.colors.grayscale.light2};
-    box-shadow: 4px 4px 20px ${({ theme }) => theme.colors.grayscale.light2};
-  }
-`;
+  return (
+    <Card
+      hoverable
+      role="button"
+      tabIndex={0}
+      aria-label={buttonText}
+      onKeyDown={handleKeyDown}
+      cover={renderIcon()}
+      css={(theme: SupersetTheme) => ({
+        padding: theme.gridUnit * 3,
+        textAlign: 'center',
+        ...cardProps.style,
+      })}
+      {...cardProps}
+    >
+      <Tooltip title={buttonText}>
+        <Typography.Text ellipsis>{buttonText}</Typography.Text>
+      </Tooltip>
+    </Card>
+  );
+};
 
-export default IconButton;
+export { IconButton };
diff --git a/superset-frontend/src/features/databases/DatabaseModal/index.tsx b/superset-frontend/src/features/databases/DatabaseModal/index.tsx
index 6efe47bdd261507b027dae1c7634ff5e2366053b..8b359cc141b153827b73aaa2dafddaea7d915b6b 100644
--- a/superset-frontend/src/features/databases/DatabaseModal/index.tsx
+++ b/superset-frontend/src/features/databases/DatabaseModal/index.tsx
@@ -45,7 +45,7 @@ import { AntdSelect, Upload } from 'src/components';
 import Alert from 'src/components/Alert';
 import Modal from 'src/components/Modal';
 import Button from 'src/components/Button';
-import IconButton from 'src/components/IconButton';
+import { IconButton } from 'src/components/IconButton';
 import InfoTooltip from 'src/components/InfoTooltip';
 import withToasts from 'src/components/MessageToasts/withToasts';
 import ValidatedInput from 'src/components/Form/LabeledErrorBoundInput';