Add BDS link styles and update existing link styles

- Introduced new styles for BDS link icons, including hover and focus states.
- Updated existing link styles to exclude BDS links from certain color and hover effects.
- Ensured consistent styling across light and dark themes for BDS links.
- Refactored landing page link styles to accommodate new BDS link classes.
This commit is contained in:
akcodez
2025-12-02 10:21:52 -08:00
parent 5b73ccb8be
commit 2ff14e4224
11 changed files with 1736 additions and 34 deletions

View File

@@ -0,0 +1,168 @@
import React from 'react';
import clsx from 'clsx';
import { LinkArrow, LinkArrowVariant } from './LinkArrow';
export type LinkVariant = 'internal' | 'external' | 'inline';
export type LinkSize = 'small' | 'medium' | 'large';
export type LinkIconType = 'arrow' | 'external' | null;
export interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
/**
* Link variant - internal, external, or inline
* @default 'internal'
*/
variant?: LinkVariant;
/**
* Size of the link
* @default 'medium'
*/
size?: LinkSize;
/**
* Icon type - arrow, external, or null
* If null, icon is determined by variant (internal/external)
* Arrow icons animate to chevron shape on hover
* @default null
*/
icon?: LinkIconType;
/**
* Disabled state - prevents navigation and applies disabled styles
* @default false
*/
disabled?: boolean;
/**
* Link URL (required)
*/
href: string;
/**
* Link text content
*/
children: React.ReactNode;
}
/**
* Link Component
*
* A comprehensive link component supporting multiple sizes, icon types, and states.
* Arrow icons animate to chevron shape on hover.
*
* Color states are handled automatically via CSS per theme:
*
* Light Mode:
* - Enabled: Green 400 (#0DAA3E)
* - Hover/Focus: Green 500 (#078139) + underline + arrow animates to chevron
* - Active: Green 400 (#0DAA3E) + underline
* - Visited: Lilac 400 (#7649E3)
* - Disabled: Gray 400 (#A2A2A4)
* - Focus outline: Black (#000000)
*
* Dark Mode:
* - Enabled: Green 300 (#21E46B)
* - Hover/Focus: Green 200 (#70EE97) + underline + arrow animates to chevron
* - Active: Green 300 (#21E46B) + underline
* - Visited: Lilac 300 (#C0A7FF)
* - Disabled: Gray 500 (#838386)
* - Focus outline: White (#FFFFFF)
*
* @see Link.md for full documentation
*
* @example
* ```tsx
* // Basic internal link (arrow animates to chevron on hover)
* <Link href="/docs" size="medium">
* View documentation
* </Link>
*
* // External link
* <Link href="https://example.com" variant="external" size="large">
* External resource
* </Link>
*
* // Disabled link
* <Link href="#" disabled>
* Coming soon
* </Link>
*
* // Inline link (no icon)
* <Link href="/docs" variant="inline">
* Learn more
* </Link>
* ```
*/
export const Link: React.FC<LinkProps> = ({
variant = 'internal',
size = 'medium',
icon = null,
disabled = false,
href,
children,
className,
onClick,
...rest
}) => {
// Determine icon type based on variant if not explicitly provided
const getIconType = (): LinkArrowVariant | null => {
if (icon === null) {
// Auto-determine icon based on variant
if (variant === 'external') {
return 'external';
}
if (variant === 'internal') {
return 'internal'; // Default to internal arrow for internal variant
}
return null; // Inline links have no icon
}
// Map icon prop to LinkArrow variant
if (icon === 'arrow') return 'internal';
if (icon === 'external') return 'external';
return null;
};
const iconType = getIconType();
const shouldShowIcon = variant !== 'inline' && iconType !== null;
const classes = clsx(
'bds-link',
`bds-link--${variant}`,
`bds-link--${size}`,
{
'bds-link--disabled': disabled,
},
className
);
const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
if (disabled) {
e.preventDefault();
e.stopPropagation();
return;
}
onClick?.(e);
};
return (
<a
href={disabled ? '#' : href}
className={classes}
onClick={handleClick}
aria-disabled={disabled}
{...rest}
>
{children}
{shouldShowIcon && (
<LinkArrow
variant={iconType as LinkArrowVariant}
size={size}
disabled={disabled}
/>
)}
</a>
);
};
Link.displayName = 'Link';