diff --git a/packages/dify-ui/src/button/index.stories.tsx b/packages/dify-ui/src/button/index.stories.tsx
index dec3a3aaf6f..be16f4cd36b 100644
--- a/packages/dify-ui/src/button/index.stories.tsx
+++ b/packages/dify-ui/src/button/index.stories.tsx
@@ -1,7 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react-vite'
import * as React from 'react'
import { expect, fn } from 'storybook/test'
-import { Button } from '.'
+import { Button, buttonVariants } from '.'
const meta = {
title: 'Base/UI/Button',
@@ -151,11 +151,24 @@ export const LargeSize: Story = {
},
}
-export const AsLink: Story = {
- args: {
- variant: 'ghost-accent',
- render: ,
- nativeButton: false,
- children: 'Link Button',
+export const StyledLink: Story = {
+ render: () => (
+
+ Link styled as a button
+
+ ),
+ play: async ({ canvas }) => {
+ await expect(canvas.getByRole('link', { name: 'Link styled as a button' })).toHaveAttribute(
+ 'href',
+ 'https://example.com',
+ )
+ },
+ parameters: {
+ docs: {
+ description: {
+ story:
+ 'Rendering an anchor through `Button` is an anti-pattern because Base UI enforces button semantics. Keep the native link and apply `buttonVariants` directly when a link needs button styling. See the [Base UI Button usage guidelines](https://base-ui.com/react/components/button#rendering-links-as-buttons).',
+ },
+ },
},
}
diff --git a/packages/dify-ui/src/button/index.tsx b/packages/dify-ui/src/button/index.tsx
index 631680fa950..cd8d0a8b7bb 100644
--- a/packages/dify-ui/src/button/index.tsx
+++ b/packages/dify-ui/src/button/index.tsx
@@ -6,7 +6,7 @@ import { Button as BaseButton } from '@base-ui/react/button'
import { cva } from 'class-variance-authority'
import { cn } from '../cn'
-const buttonVariants = cva(
+export const buttonVariants = cva(
'inline-flex cursor-pointer items-center justify-center whitespace-nowrap outline-hidden focus-visible:ring-2 focus-visible:ring-state-accent-solid data-[disabled]:cursor-not-allowed',
{
variants: {