mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-12-06 17:27:57 +00:00
add proper focus and active / hover states
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Button } from 'shared/components/Button';
|
import { Button } from 'shared/components/Button';
|
||||||
import { PageGrid, PageGridCol, PageGridRow } from 'shared/components/page-grid';
|
import { PageGrid, PageGridCol, PageGridRow } from 'shared/components/PageGrid/page-grid';
|
||||||
|
|
||||||
export const frontmatter = {
|
export const frontmatter = {
|
||||||
seo: {
|
seo: {
|
||||||
@@ -11,19 +11,11 @@ export const frontmatter = {
|
|||||||
|
|
||||||
export default function ButtonShowcase() {
|
export default function ButtonShowcase() {
|
||||||
const [clickCount, setClickCount] = React.useState(0);
|
const [clickCount, setClickCount] = React.useState(0);
|
||||||
const [isLoading, setIsLoading] = React.useState(false);
|
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
setClickCount((prev) => prev + 1);
|
setClickCount((prev) => prev + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAsyncClick = async () => {
|
|
||||||
setIsLoading(true);
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
||||||
setIsLoading(false);
|
|
||||||
setClickCount((prev) => prev + 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="landing">
|
<div className="landing">
|
||||||
<section className="container-new py-26">
|
<section className="container-new py-26">
|
||||||
@@ -96,16 +88,96 @@ export default function ButtonShowcase() {
|
|||||||
<Button variant="primary" onClick={handleClick} className="me-4 mb-4">
|
<Button variant="primary" onClick={handleClick} className="me-4 mb-4">
|
||||||
Hover Me
|
Hover Me
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="primary" onClick={handleClick} className="me-4 mb-4">
|
<Button variant="primary" onClick={handleClick} className="mb-4">
|
||||||
Focus Me (Tab)
|
Focus Me (Tab)
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="primary" onClick={handleClick} className="mb-4">
|
</div>
|
||||||
Active State (Click)
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Black Color Variant */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Black Color Variant</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Color Theme</h6>
|
||||||
|
</div>
|
||||||
|
<p className="mb-4 text-muted">
|
||||||
|
Primary buttons can use a black color theme for dark backgrounds or alternative styling needs.
|
||||||
|
</p>
|
||||||
|
<div className="d-flex flex-wrap align-items-center">
|
||||||
|
<Button variant="primary" color="black" onClick={handleClick} className="me-4 mb-4">
|
||||||
|
Black Primary
|
||||||
|
</Button>
|
||||||
|
<Button variant="primary" color="black" onClick={handleClick} className="me-4 mb-4">
|
||||||
|
Dark Button
|
||||||
|
</Button>
|
||||||
|
<Button variant="primary" color="black" onClick={handleClick} className="mb-4">
|
||||||
|
Get Started
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Black Variant States */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Black Variant States</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Interactive States</h6>
|
||||||
|
</div>
|
||||||
|
<PageGrid>
|
||||||
|
<PageGridRow>
|
||||||
|
<PageGridCol span={{ base: 4, lg: 6 }}>
|
||||||
|
<div className="p-6-sm p-10-until-sm br-8" style={{ backgroundColor: '#f5f5f7' }}>
|
||||||
|
<h5 className="mb-4">Enabled State</h5>
|
||||||
|
<p className="mb-4 text-muted">Black background with white text.</p>
|
||||||
|
<Button variant="primary" color="black" onClick={handleClick}>
|
||||||
|
Enabled Button
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</PageGridCol>
|
||||||
|
<PageGridCol span={{ base: 4, lg: 6 }}>
|
||||||
|
<div className="p-6-sm p-10-until-sm br-8" style={{ backgroundColor: '#f5f5f7' }}>
|
||||||
|
<h5 className="mb-4">Disabled State</h5>
|
||||||
|
<p className="mb-4 text-muted">Same disabled styling as green variant.</p>
|
||||||
|
<Button variant="primary" color="black" disabled>
|
||||||
|
Disabled Button
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</PageGridCol>
|
||||||
|
</PageGridRow>
|
||||||
|
</PageGrid>
|
||||||
|
<div className="mt-10">
|
||||||
|
<h5 className="mb-4">Hover & Focus States</h5>
|
||||||
|
<p className="mb-4 text-muted">
|
||||||
|
Hover over the buttons or use Tab to focus them. Notice the background darkens slightly on hover.
|
||||||
|
</p>
|
||||||
|
<div className="d-flex flex-wrap">
|
||||||
|
<Button variant="primary" color="black" onClick={handleClick} className="me-4 mb-4">
|
||||||
|
Hover Me
|
||||||
|
</Button>
|
||||||
|
<Button variant="primary" color="black" onClick={handleClick} className="mb-4">
|
||||||
|
Focus Me (Tab)
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
{/* Green vs Black Comparison */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Green vs Black Comparison</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Color Themes</h6>
|
||||||
|
</div>
|
||||||
|
<p className="mb-4 text-muted">Compare the green (default) and black color themes side by side.</p>
|
||||||
|
<div className="d-flex flex-wrap align-items-center">
|
||||||
|
<Button variant="primary" color="green" onClick={handleClick} className="me-4 mb-4">
|
||||||
|
Green Primary
|
||||||
|
</Button>
|
||||||
|
<Button variant="primary" color="black" onClick={handleClick} className="mb-4">
|
||||||
|
Black Primary
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
{/* Without Icon */}
|
{/* Without Icon */}
|
||||||
<section className="container-new py-26">
|
<section className="container-new py-26">
|
||||||
<div className="d-flex flex-column-reverse">
|
<div className="d-flex flex-column-reverse">
|
||||||
@@ -149,23 +221,6 @@ export default function ButtonShowcase() {
|
|||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Loading State Simulation */}
|
|
||||||
<section className="container-new py-26">
|
|
||||||
<div className="d-flex flex-column-reverse">
|
|
||||||
<h2 className="h4 mb-8">Async Actions</h2>
|
|
||||||
<h6 className="eyebrow mb-3">Loading States</h6>
|
|
||||||
</div>
|
|
||||||
<p className="mb-4 text-muted">
|
|
||||||
Example of handling async actions. The button is disabled during the async operation.
|
|
||||||
</p>
|
|
||||||
<Button variant="primary" disabled={isLoading} onClick={handleAsyncClick}>
|
|
||||||
{isLoading ? 'Loading...' : 'Async Action'}
|
|
||||||
</Button>
|
|
||||||
{clickCount > 0 && (
|
|
||||||
<p className="mt-4 text-muted">Async action completed {clickCount} time{clickCount !== 1 ? 's' : ''}</p>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Responsive Behavior */}
|
{/* Responsive Behavior */}
|
||||||
<section className="container-new py-26">
|
<section className="container-new py-26">
|
||||||
<div className="d-flex flex-column-reverse">
|
<div className="d-flex flex-column-reverse">
|
||||||
@@ -252,11 +307,16 @@ export default function ButtonShowcase() {
|
|||||||
<pre style={{ margin: 0, overflow: 'auto' }}>
|
<pre style={{ margin: 0, overflow: 'auto' }}>
|
||||||
<code>{`import { Button } from 'shared/components/Button';
|
<code>{`import { Button } from 'shared/components/Button';
|
||||||
|
|
||||||
// Basic usage
|
// Basic usage (green theme - default)
|
||||||
<Button variant="primary" onClick={handleClick}>
|
<Button variant="primary" onClick={handleClick}>
|
||||||
Get Started
|
Get Started
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
// Black color theme
|
||||||
|
<Button variant="primary" color="black" onClick={handleClick}>
|
||||||
|
Dark Button
|
||||||
|
</Button>
|
||||||
|
|
||||||
// Disabled state
|
// Disabled state
|
||||||
<Button variant="primary" disabled>
|
<Button variant="primary" disabled>
|
||||||
Submit
|
Submit
|
||||||
@@ -305,49 +365,90 @@ export default function ButtonShowcase() {
|
|||||||
</PageGridRow>
|
</PageGridRow>
|
||||||
</PageGrid>
|
</PageGrid>
|
||||||
<div className="mt-10">
|
<div className="mt-10">
|
||||||
<h5 className="mb-4">State Colors</h5>
|
<h5 className="mb-4">State Colors - Green Theme</h5>
|
||||||
<table className="table" style={{ width: '100%' }}>
|
<div style={{ width: '100%', backgroundColor: '#FFFFFF' }}>
|
||||||
<thead>
|
{/* Header */}
|
||||||
<tr>
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '2px solid #E0E0E1' }}>
|
||||||
<th>State</th>
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>State</div>
|
||||||
<th>Text Color</th>
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Text Color</div>
|
||||||
<th>Background Color</th>
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Background Color</div>
|
||||||
<th>Border</th>
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Border</div>
|
||||||
</tr>
|
</div>
|
||||||
</thead>
|
{/* Rows */}
|
||||||
<tbody>
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
<tr>
|
<div style={{ padding: '12px' }}>Enabled</div>
|
||||||
<td>Enabled</td>
|
<div style={{ padding: '12px' }}>#141414 (Neutral Black)</div>
|
||||||
<td>#141414 (Neutral Black)</td>
|
<div style={{ padding: '12px' }}>#21E46B (Green 300)</div>
|
||||||
<td>#21E46B (Green 300)</td>
|
<div style={{ padding: '12px' }}>None</div>
|
||||||
<td>None</td>
|
</div>
|
||||||
</tr>
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
<tr>
|
<div style={{ padding: '12px' }}>Hover</div>
|
||||||
<td>Hover</td>
|
<div style={{ padding: '12px' }}>#141414 (Neutral Black)</div>
|
||||||
<td>#141414 (Neutral Black)</td>
|
<div style={{ padding: '12px' }}>#70EE97 (Green 200)</div>
|
||||||
<td>#70EE97 (Green 200)</td>
|
<div style={{ padding: '12px' }}>None</div>
|
||||||
<td>None</td>
|
</div>
|
||||||
</tr>
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
<tr>
|
<div style={{ padding: '12px' }}>Focus</div>
|
||||||
<td>Focus</td>
|
<div style={{ padding: '12px' }}>#141414 (Neutral Black)</div>
|
||||||
<td>#141414 (Neutral Black)</td>
|
<div style={{ padding: '12px' }}>#70EE97 (Green 200)</div>
|
||||||
<td>#70EE97 (Green 200)</td>
|
<div style={{ padding: '12px' }}>2px solid #141414</div>
|
||||||
<td>2px solid #141414</td>
|
</div>
|
||||||
</tr>
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
<tr>
|
<div style={{ padding: '12px' }}>Active</div>
|
||||||
<td>Active</td>
|
<div style={{ padding: '12px' }}>#141414 (Neutral Black)</div>
|
||||||
<td>#141414 (Neutral Black)</td>
|
<div style={{ padding: '12px' }}>#21E46B (Green 300)</div>
|
||||||
<td>#21E46B (Green 300)</td>
|
<div style={{ padding: '12px' }}>None</div>
|
||||||
<td>None</td>
|
</div>
|
||||||
</tr>
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr' }}>
|
||||||
<tr>
|
<div style={{ padding: '12px' }}>Disabled</div>
|
||||||
<td>Disabled</td>
|
<div style={{ padding: '12px' }}>#838386 (Gray 500)</div>
|
||||||
<td>#838386 (Gray 500)</td>
|
<div style={{ padding: '12px' }}>#E0E0E1 (Gray 200)</div>
|
||||||
<td>#E0E0E1 (Gray 200)</td>
|
<div style={{ padding: '12px' }}>None</div>
|
||||||
<td>None</td>
|
</div>
|
||||||
</tr>
|
</div>
|
||||||
</tbody>
|
</div>
|
||||||
</table>
|
<div className="mt-10">
|
||||||
|
<h5 className="mb-4">State Colors - Black Theme</h5>
|
||||||
|
<div style={{ width: '100%', backgroundColor: '#FFFFFF' }}>
|
||||||
|
{/* Header */}
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '2px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>State</div>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Text Color</div>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Background Color</div>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Border</div>
|
||||||
|
</div>
|
||||||
|
{/* Rows */}
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Enabled</div>
|
||||||
|
<div style={{ padding: '12px' }}>#FFFFFF (White)</div>
|
||||||
|
<div style={{ padding: '12px' }}>#141414 (Neutral Black)</div>
|
||||||
|
<div style={{ padding: '12px' }}>None</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Hover</div>
|
||||||
|
<div style={{ padding: '12px' }}>#FFFFFF (White)</div>
|
||||||
|
<div style={{ padding: '12px' }}>rgba(20, 20, 20, 0.8) (80% Black)</div>
|
||||||
|
<div style={{ padding: '12px' }}>None</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Focus</div>
|
||||||
|
<div style={{ padding: '12px' }}>#FFFFFF (White)</div>
|
||||||
|
<div style={{ padding: '12px' }}>rgba(20, 20, 20, 0.8) (80% Black)</div>
|
||||||
|
<div style={{ padding: '12px' }}>2px solid #141414</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Active</div>
|
||||||
|
<div style={{ padding: '12px' }}>#FFFFFF (White)</div>
|
||||||
|
<div style={{ padding: '12px' }}>#141414 (Neutral Black)</div>
|
||||||
|
<div style={{ padding: '12px' }}>None</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Disabled</div>
|
||||||
|
<div style={{ padding: '12px' }}>#838386 (Gray 500)</div>
|
||||||
|
<div style={{ padding: '12px' }}>#E0E0E1 (Gray 200)</div>
|
||||||
|
<div style={{ padding: '12px' }}>None</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
528
about/button-showcase-secondary.page.tsx
Normal file
528
about/button-showcase-secondary.page.tsx
Normal file
@@ -0,0 +1,528 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { Button } from 'shared/components/Button';
|
||||||
|
import { PageGrid, PageGridCol, PageGridRow } from 'shared/components/PageGrid/page-grid';
|
||||||
|
|
||||||
|
export const frontmatter = {
|
||||||
|
seo: {
|
||||||
|
title: 'BDS Secondary Button Component Showcase',
|
||||||
|
description: 'Interactive showcase of the Brand Design System Secondary Button component with all states and variants.',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ButtonShowcaseSecondary() {
|
||||||
|
const [clickCount, setClickCount] = React.useState(0);
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
setClickCount((prev) => prev + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="landing">
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse col-lg-8 mx-auto">
|
||||||
|
<h1 className="mb-0">BDS Secondary Button</h1>
|
||||||
|
<h6 className="eyebrow mb-3">Brand Design System</h6>
|
||||||
|
</div>
|
||||||
|
<p className="col-lg-8 mx-auto mt-10">
|
||||||
|
The Secondary button is an outline-style button used for secondary actions. It features a transparent
|
||||||
|
background with a green stroke/border, providing visual hierarchy below the Primary button while maintaining
|
||||||
|
brand consistency.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Basic Usage */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Basic Usage</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Secondary Variant</h6>
|
||||||
|
</div>
|
||||||
|
<div className="d-flex flex-wrap align-items-center">
|
||||||
|
<Button variant="secondary" onClick={handleClick} className="me-4 mb-4">
|
||||||
|
Learn More
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary" onClick={handleClick} className="me-4 mb-4">
|
||||||
|
View Details
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary" onClick={handleClick} className="mb-4">
|
||||||
|
Explore
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{clickCount > 0 && (
|
||||||
|
<p className="mt-4 text-muted">
|
||||||
|
Button clicked {clickCount} time{clickCount !== 1 ? 's' : ''}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Primary vs Secondary Comparison */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Primary vs Secondary</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Visual Hierarchy</h6>
|
||||||
|
</div>
|
||||||
|
<p className="mb-4 text-muted">
|
||||||
|
Use Primary for main actions and Secondary for supporting actions to create clear visual hierarchy.
|
||||||
|
</p>
|
||||||
|
<div className="d-flex flex-wrap align-items-center">
|
||||||
|
<Button variant="primary" onClick={handleClick} className="me-4 mb-4">
|
||||||
|
Get Started
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary" onClick={handleClick} className="mb-4">
|
||||||
|
Learn More
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* States */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Button States</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Interactive States</h6>
|
||||||
|
</div>
|
||||||
|
<PageGrid>
|
||||||
|
<PageGridRow>
|
||||||
|
<PageGridCol span={{ base: 4, lg: 6 }}>
|
||||||
|
<div className="p-6-sm p-10-until-sm br-8" style={{ backgroundColor: '#f5f5f7' }}>
|
||||||
|
<h5 className="mb-4">Enabled State</h5>
|
||||||
|
<p className="mb-4 text-muted">Default outline style with green border and text.</p>
|
||||||
|
<Button variant="secondary" onClick={handleClick}>
|
||||||
|
Enabled Button
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</PageGridCol>
|
||||||
|
<PageGridCol span={{ base: 4, lg: 6 }}>
|
||||||
|
<div className="p-6-sm p-10-until-sm br-8" style={{ backgroundColor: '#f5f5f7' }}>
|
||||||
|
<h5 className="mb-4">Disabled State</h5>
|
||||||
|
<p className="mb-4 text-muted">Gray border and text indicate non-interactive state.</p>
|
||||||
|
<Button variant="secondary" disabled>
|
||||||
|
Disabled Button
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</PageGridCol>
|
||||||
|
</PageGridRow>
|
||||||
|
</PageGrid>
|
||||||
|
<div className="mt-10">
|
||||||
|
<h5 className="mb-4">Hover & Focus States</h5>
|
||||||
|
<p className="mb-4 text-muted">
|
||||||
|
Hover over the buttons or use Tab to focus them. Notice the light green background fill and darker green
|
||||||
|
border on hover/focus.
|
||||||
|
</p>
|
||||||
|
<div className="d-flex flex-wrap">
|
||||||
|
<Button variant="secondary" onClick={handleClick} className="me-4 mb-4">
|
||||||
|
Hover Me
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary" onClick={handleClick} className="mb-4">
|
||||||
|
Focus Me (Tab)
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Black Color Variant */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Black Color Variant</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Color Theme</h6>
|
||||||
|
</div>
|
||||||
|
<p className="mb-4 text-muted">
|
||||||
|
Secondary buttons can use a black color theme with black text and border instead of green.
|
||||||
|
</p>
|
||||||
|
<div className="d-flex flex-wrap align-items-center">
|
||||||
|
<Button variant="secondary" color="black" onClick={handleClick} className="me-4 mb-4">
|
||||||
|
Black Secondary
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary" color="black" onClick={handleClick} className="me-4 mb-4">
|
||||||
|
Learn More
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary" color="black" onClick={handleClick} className="mb-4">
|
||||||
|
View Details
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Black Variant States */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Black Variant States</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Interactive States</h6>
|
||||||
|
</div>
|
||||||
|
<PageGrid>
|
||||||
|
<PageGridRow>
|
||||||
|
<PageGridCol span={{ base: 4, lg: 6 }}>
|
||||||
|
<div className="p-6-sm p-10-until-sm br-8" style={{ backgroundColor: '#f5f5f7' }}>
|
||||||
|
<h5 className="mb-4">Enabled State</h5>
|
||||||
|
<p className="mb-4 text-muted">Black border and text with transparent background.</p>
|
||||||
|
<Button variant="secondary" color="black" onClick={handleClick}>
|
||||||
|
Enabled Button
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</PageGridCol>
|
||||||
|
<PageGridCol span={{ base: 4, lg: 6 }}>
|
||||||
|
<div className="p-6-sm p-10-until-sm br-8" style={{ backgroundColor: '#f5f5f7' }}>
|
||||||
|
<h5 className="mb-4">Disabled State</h5>
|
||||||
|
<p className="mb-4 text-muted">Same disabled styling as green variant.</p>
|
||||||
|
<Button variant="secondary" color="black" disabled>
|
||||||
|
Disabled Button
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</PageGridCol>
|
||||||
|
</PageGridRow>
|
||||||
|
</PageGrid>
|
||||||
|
<div className="mt-10">
|
||||||
|
<h5 className="mb-4">Hover & Focus States</h5>
|
||||||
|
<p className="mb-4 text-muted">
|
||||||
|
Hover over the buttons or use Tab to focus them. Notice the subtle black background fill on hover.
|
||||||
|
</p>
|
||||||
|
<div className="d-flex flex-wrap">
|
||||||
|
<Button variant="secondary" color="black" onClick={handleClick} className="me-4 mb-4">
|
||||||
|
Hover Me
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary" color="black" onClick={handleClick} className="mb-4">
|
||||||
|
Focus Me (Tab)
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Green vs Black Comparison */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Green vs Black Comparison</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Color Themes</h6>
|
||||||
|
</div>
|
||||||
|
<p className="mb-4 text-muted">Compare the green (default) and black color themes side by side.</p>
|
||||||
|
<div className="d-flex flex-wrap align-items-center">
|
||||||
|
<Button variant="secondary" color="green" onClick={handleClick} className="me-4 mb-4">
|
||||||
|
Green Secondary
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary" color="black" onClick={handleClick} className="mb-4">
|
||||||
|
Black Secondary
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Without Icon */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Without Icon</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Icon Control</h6>
|
||||||
|
</div>
|
||||||
|
<p className="mb-4 text-muted">Secondary buttons can also be rendered without the arrow icon.</p>
|
||||||
|
<div className="d-flex flex-wrap">
|
||||||
|
<Button variant="secondary" showIcon={false} onClick={handleClick} className="me-4 mb-4">
|
||||||
|
No Icon Button
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary" showIcon={true} onClick={handleClick} className="mb-4">
|
||||||
|
With Icon Button
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Button Types */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Button Types</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Form Integration</h6>
|
||||||
|
</div>
|
||||||
|
<p className="mb-4 text-muted">Secondary buttons can be used for form actions like cancel or reset.</p>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
alert('Form submitted!');
|
||||||
|
}}
|
||||||
|
className="d-flex flex-wrap"
|
||||||
|
>
|
||||||
|
<Button variant="primary" type="submit" className="me-4 mb-4">
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary" type="reset" className="me-4 mb-4">
|
||||||
|
Reset
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary" type="button" onClick={() => alert('Cancelled!')} className="mb-4">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Responsive Behavior */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Responsive Behavior</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Breakpoint Adjustments</h6>
|
||||||
|
</div>
|
||||||
|
<p className="mb-4 text-muted">
|
||||||
|
Button padding adjusts automatically across breakpoints. Resize your browser window to see the changes:
|
||||||
|
</p>
|
||||||
|
<ul className="mb-4">
|
||||||
|
<li>
|
||||||
|
<strong>Desktop (≥1024px):</strong> Padding: 6px 17px 6px 18px (compensates for 2px border)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Tablet/Mobile (≤1023px):</strong> Padding: 6px 13px 6px 14px
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Hover/Focus:</strong> Gap increases (22px desktop, 21px mobile) with adjusted padding
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div className="d-flex flex-wrap">
|
||||||
|
<Button variant="secondary" onClick={handleClick} className="me-4 mb-4">
|
||||||
|
Responsive Button
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary" onClick={handleClick} className="mb-4">
|
||||||
|
Long Button Label Example
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Accessibility */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Accessibility Features</h2>
|
||||||
|
<h6 className="eyebrow mb-3">WCAG Compliance</h6>
|
||||||
|
</div>
|
||||||
|
<PageGrid>
|
||||||
|
<PageGridRow>
|
||||||
|
<PageGridCol span={{ base: 4, lg: 6 }}>
|
||||||
|
<h5 className="mb-4">Keyboard Navigation</h5>
|
||||||
|
<ul>
|
||||||
|
<li>Tab to focus buttons</li>
|
||||||
|
<li>Enter or Space to activate</li>
|
||||||
|
<li>Focus indicator: 2px black outline (additional to green border)</li>
|
||||||
|
<li>Disabled buttons are not focusable</li>
|
||||||
|
</ul>
|
||||||
|
</PageGridCol>
|
||||||
|
<PageGridCol span={{ base: 4, lg: 6 }}>
|
||||||
|
<h5 className="mb-4">Screen Reader Support</h5>
|
||||||
|
<ul>
|
||||||
|
<li>Button labels are announced</li>
|
||||||
|
<li>Disabled state communicated via aria-disabled</li>
|
||||||
|
<li>Icons are hidden from screen readers (aria-hidden)</li>
|
||||||
|
<li>Semantic button element used</li>
|
||||||
|
</ul>
|
||||||
|
</PageGridCol>
|
||||||
|
</PageGridRow>
|
||||||
|
</PageGrid>
|
||||||
|
<div className="mt-10">
|
||||||
|
<h5 className="mb-4">Color Contrast</h5>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<strong>Enabled:</strong> Green 400 (#0DAA3E) on White = 4.52:1 (AA for large text)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Hover:</strong> Green 500 (#078139) on Green 100 (#EAFCF1) = 4.87:1 (AA)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Disabled:</strong> Gray 400 (#A2A2A4) on White = reduced contrast (acceptable for disabled state)
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Code Examples */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Code Examples</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Implementation</h6>
|
||||||
|
</div>
|
||||||
|
<div className="p-6-sm p-10-until-sm br-8" style={{ backgroundColor: '#1e1e1e', color: '#d4d4d4' }}>
|
||||||
|
<pre style={{ margin: 0, overflow: 'auto' }}>
|
||||||
|
<code>{`import { Button } from 'shared/components/Button';
|
||||||
|
|
||||||
|
// Basic secondary button (green theme - default)
|
||||||
|
<Button variant="secondary" onClick={handleClick}>
|
||||||
|
Learn More
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
// Black color theme
|
||||||
|
<Button variant="secondary" color="black" onClick={handleClick}>
|
||||||
|
Learn More
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
// Disabled state
|
||||||
|
<Button variant="secondary" disabled>
|
||||||
|
Unavailable
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
// Without icon
|
||||||
|
<Button variant="secondary" showIcon={false}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
// Primary + Secondary pairing
|
||||||
|
<Button variant="primary" type="submit">
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
<Button variant="secondary" type="button">
|
||||||
|
Cancel
|
||||||
|
</Button>`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Design Specifications */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Design Specifications</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Visual Details</h6>
|
||||||
|
</div>
|
||||||
|
<PageGrid>
|
||||||
|
<PageGridRow>
|
||||||
|
<PageGridCol span={{ base: 4, lg: 6 }}>
|
||||||
|
<h5 className="mb-4">Typography</h5>
|
||||||
|
<ul>
|
||||||
|
<li>Font: Booton, sans-serif</li>
|
||||||
|
<li>Size: 16px</li>
|
||||||
|
<li>Weight: 400</li>
|
||||||
|
<li>Line Height: 23.2px</li>
|
||||||
|
<li>Letter Spacing: 0px</li>
|
||||||
|
</ul>
|
||||||
|
</PageGridCol>
|
||||||
|
<PageGridCol span={{ base: 4, lg: 6 }}>
|
||||||
|
<h5 className="mb-4">Spacing & Layout</h5>
|
||||||
|
<ul>
|
||||||
|
<li>Border Radius: 100px (fully rounded)</li>
|
||||||
|
<li>Border Width: 2px solid</li>
|
||||||
|
<li>Icon Size: 15px × 14px</li>
|
||||||
|
<li>Icon Gap: 16px (default), 22px (hover/focus desktop), 21px (hover/focus mobile)</li>
|
||||||
|
<li>Max Height: 40px</li>
|
||||||
|
</ul>
|
||||||
|
</PageGridCol>
|
||||||
|
</PageGridRow>
|
||||||
|
</PageGrid>
|
||||||
|
<div className="mt-10">
|
||||||
|
<h5 className="mb-4">State Colors - Green Theme</h5>
|
||||||
|
<div style={{ width: '100%', backgroundColor: '#FFFFFF' }}>
|
||||||
|
{/* Header */}
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '2px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>State</div>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Text Color</div>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Background</div>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Border</div>
|
||||||
|
</div>
|
||||||
|
{/* Rows */}
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Enabled</div>
|
||||||
|
<div style={{ padding: '12px' }}>#0DAA3E (Green 400)</div>
|
||||||
|
<div style={{ padding: '12px' }}>Transparent</div>
|
||||||
|
<div style={{ padding: '12px' }}>2px #0DAA3E (Green 400)</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Hover</div>
|
||||||
|
<div style={{ padding: '12px' }}>#078139 (Green 500)</div>
|
||||||
|
<div style={{ padding: '12px' }}>#EAFCF1 (Green 100)</div>
|
||||||
|
<div style={{ padding: '12px' }}>2px #078139 (Green 500)</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Focus</div>
|
||||||
|
<div style={{ padding: '12px' }}>#078139 (Green 500)</div>
|
||||||
|
<div style={{ padding: '12px' }}>#EAFCF1 (Green 100)</div>
|
||||||
|
<div style={{ padding: '12px' }}>2px #078139 + 2px #141414 outline</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Active</div>
|
||||||
|
<div style={{ padding: '12px' }}>#0DAA3E (Green 400)</div>
|
||||||
|
<div style={{ padding: '12px' }}>Transparent</div>
|
||||||
|
<div style={{ padding: '12px' }}>2px #0DAA3E (Green 400)</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Disabled</div>
|
||||||
|
<div style={{ padding: '12px' }}>#A2A2A4 (Gray 400)</div>
|
||||||
|
<div style={{ padding: '12px' }}>Transparent</div>
|
||||||
|
<div style={{ padding: '12px' }}>2px #A2A2A4 (Gray 400)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mt-10">
|
||||||
|
<h5 className="mb-4">State Colors - Black Theme</h5>
|
||||||
|
<div style={{ width: '100%', backgroundColor: '#FFFFFF' }}>
|
||||||
|
{/* Header */}
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '2px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>State</div>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Text Color</div>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Background</div>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Border</div>
|
||||||
|
</div>
|
||||||
|
{/* Rows */}
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Enabled</div>
|
||||||
|
<div style={{ padding: '12px' }}>#141414 (Neutral Black)</div>
|
||||||
|
<div style={{ padding: '12px' }}>Transparent</div>
|
||||||
|
<div style={{ padding: '12px' }}>2px #141414 (Neutral Black)</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Hover</div>
|
||||||
|
<div style={{ padding: '12px' }}>#141414 (Neutral Black)</div>
|
||||||
|
<div style={{ padding: '12px' }}>rgba(20, 20, 20, 0.15) (15% Black)</div>
|
||||||
|
<div style={{ padding: '12px' }}>2px #141414 (Neutral Black)</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Focus</div>
|
||||||
|
<div style={{ padding: '12px' }}>#141414 (Neutral Black)</div>
|
||||||
|
<div style={{ padding: '12px' }}>rgba(20, 20, 20, 0.15) (15% Black)</div>
|
||||||
|
<div style={{ padding: '12px' }}>2px #141414 + 2px #141414 outline</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Active</div>
|
||||||
|
<div style={{ padding: '12px' }}>#141414 (Neutral Black)</div>
|
||||||
|
<div style={{ padding: '12px' }}>Transparent</div>
|
||||||
|
<div style={{ padding: '12px' }}>2px #141414 (Neutral Black)</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Disabled</div>
|
||||||
|
<div style={{ padding: '12px' }}>#A2A2A4 (Gray 400)</div>
|
||||||
|
<div style={{ padding: '12px' }}>Transparent</div>
|
||||||
|
<div style={{ padding: '12px' }}>2px #A2A2A4 (Gray 400)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Key Differences from Primary */}
|
||||||
|
<section className="container-new py-26">
|
||||||
|
<div className="d-flex flex-column-reverse">
|
||||||
|
<h2 className="h4 mb-8">Key Differences from Primary</h2>
|
||||||
|
<h6 className="eyebrow mb-3">Comparison</h6>
|
||||||
|
</div>
|
||||||
|
<div style={{ width: '100%', backgroundColor: '#FFFFFF' }}>
|
||||||
|
{/* Header */}
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', borderBottom: '2px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Aspect</div>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Primary</div>
|
||||||
|
<div style={{ padding: '12px', fontWeight: 'bold' }}>Secondary</div>
|
||||||
|
</div>
|
||||||
|
{/* Rows */}
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Background (Enabled)</div>
|
||||||
|
<div style={{ padding: '12px' }}>Green 300 (#21E46B)</div>
|
||||||
|
<div style={{ padding: '12px' }}>Transparent</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Background (Hover)</div>
|
||||||
|
<div style={{ padding: '12px' }}>Green 200 (#70EE97)</div>
|
||||||
|
<div style={{ padding: '12px' }}>Green 100 (#EAFCF1)</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Border (Enabled)</div>
|
||||||
|
<div style={{ padding: '12px' }}>None</div>
|
||||||
|
<div style={{ padding: '12px' }}>2px Green 400</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Text Color (Enabled)</div>
|
||||||
|
<div style={{ padding: '12px' }}>Black (#141414)</div>
|
||||||
|
<div style={{ padding: '12px' }}>Green 400 (#0DAA3E)</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', borderBottom: '1px solid #E0E0E1' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Disabled Background</div>
|
||||||
|
<div style={{ padding: '12px' }}>Gray 200 (#E0E0E1)</div>
|
||||||
|
<div style={{ padding: '12px' }}>Transparent</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr' }}>
|
||||||
|
<div style={{ padding: '12px' }}>Arrow Icon</div>
|
||||||
|
<div style={{ padding: '12px' }}>✅ Shared</div>
|
||||||
|
<div style={{ padding: '12px' }}>✅ Shared</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Button } from 'shared/components/Button';
|
import { Button } from 'shared/components/Button';
|
||||||
import { PageGrid, PageGridCol, PageGridRow } from 'shared/components/page-grid';
|
import { PageGrid, PageGridCol, PageGridRow } from 'shared/components/PageGrid/page-grid';
|
||||||
|
|
||||||
export const frontmatter = {
|
export const frontmatter = {
|
||||||
seo: {
|
seo: {
|
||||||
|
|||||||
494
secondary-button-logic.md
Normal file
494
secondary-button-logic.md
Normal file
@@ -0,0 +1,494 @@
|
|||||||
|
# Secondary Button Logic
|
||||||
|
|
||||||
|
> **Design Source:** [Figma - Button Component](https://www.figma.com/design/MZOPJQOw9oWC6NDxLRH4ws/Button?node-id=5226-8948&m=dev) (Second Column - Secondary)
|
||||||
|
> **Target Component:** `shared/components/Button/Button.tsx` & `Button.scss`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The **Secondary Button** is an outline-style button used for secondary actions. It features a transparent background with a colored stroke/border, providing visual hierarchy below the Primary button while maintaining brand consistency.
|
||||||
|
|
||||||
|
**Key Characteristics:**
|
||||||
|
- Outline/ghost style (transparent background in default states)
|
||||||
|
- Green stroke/border in enabled state
|
||||||
|
- Filled background appears on hover/focus states
|
||||||
|
- **Shares arrow icon & animation with Primary button** (no duplicate code)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Shared Code Architecture
|
||||||
|
|
||||||
|
The Secondary button **inherits** all arrow icon logic from the base `.bds-btn` class. This ensures:
|
||||||
|
- ✅ No duplicate arrow animation code
|
||||||
|
- ✅ Consistent hover behavior across variants
|
||||||
|
- ✅ Single source of truth for icon styling
|
||||||
|
|
||||||
|
### Already Shared in Base `.bds-btn` Class
|
||||||
|
|
||||||
|
```scss
|
||||||
|
// These styles are already in the base class and apply to ALL variants:
|
||||||
|
|
||||||
|
.bds-btn {
|
||||||
|
// Icon element (SVG container) - SHARED
|
||||||
|
&__icon {
|
||||||
|
width: 15px;
|
||||||
|
height: 14px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
transition: opacity $bds-btn-transition-duration $bds-btn-transition-timing;
|
||||||
|
color: currentColor; // Inherits text color from parent
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arrow horizontal line - SHARED
|
||||||
|
&__icon-line {
|
||||||
|
transform-box: fill-box;
|
||||||
|
transform-origin: right center;
|
||||||
|
transform: scaleX(1);
|
||||||
|
transition: transform $bds-btn-transition-duration $bds-btn-transition-timing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arrow chevron - SHARED
|
||||||
|
&__icon-chevron {
|
||||||
|
transition: transform $bds-btn-transition-duration $bds-btn-transition-timing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hover/Focus animation - SHARED (applies to ALL variants)
|
||||||
|
&:hover:not(:disabled):not(.bds-btn--disabled),
|
||||||
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
.bds-btn__icon-line {
|
||||||
|
transform: scaleX(0); // Line shrinks from left-to-right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### What Secondary Button Needs to Define
|
||||||
|
|
||||||
|
The `.bds-btn--secondary` class only needs to define:
|
||||||
|
1. **Colors** (text, background, border) - different from Primary
|
||||||
|
2. **Padding & Gap** values per state - adjusted for border width
|
||||||
|
3. **Border** styling (Primary has no border, Secondary has 2px border)
|
||||||
|
|
||||||
|
The icon color automatically updates via `currentColor` inheritance from the text color
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Visual Specifications
|
||||||
|
|
||||||
|
### Button Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ [Label Text] [gap] [Icon] │
|
||||||
|
└─────────────────────────────────────────────┘
|
||||||
|
↑ ↑
|
||||||
|
.bds-btn__label .bds-btn__icon
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Border Radius:** `100px` (pill shape)
|
||||||
|
- **Border Width:** `2px` solid
|
||||||
|
- **Max Height:** `40px`
|
||||||
|
- **Typography:** Label R token (Booton, 16px, 400 weight, 23.2px line-height)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## State Specifications
|
||||||
|
|
||||||
|
### 1. Enabled State (Default)
|
||||||
|
|
||||||
|
| Property | Value | SCSS Variable |
|
||||||
|
|----------|-------|---------------|
|
||||||
|
| **Text Color** | Green 400 `#0DAA3E` | `$green-400` |
|
||||||
|
| **Background** | Transparent | `transparent` |
|
||||||
|
| **Border Color** | Green 400 `#0DAA3E` | `$green-400` |
|
||||||
|
| **Border Width** | `2px` | - |
|
||||||
|
|
||||||
|
> **Icon Color:** Inherits text color via `currentColor` (no separate definition needed)
|
||||||
|
|
||||||
|
**Desktop Padding & Gap:**
|
||||||
|
| Property | With Icon | Without Icon |
|
||||||
|
|----------|-----------|--------------|
|
||||||
|
| Padding | `8px 19px 8px 20px` | `8px 20px` |
|
||||||
|
| Gap | `16px` | N/A |
|
||||||
|
|
||||||
|
**Tablet/Mobile Padding & Gap (≤1023px):**
|
||||||
|
| Property | With Icon | Without Icon |
|
||||||
|
|----------|-----------|--------------|
|
||||||
|
| Padding | `8px 15px 8px 16px` | `8px 16px` |
|
||||||
|
| Gap | `16px` | N/A |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Hover State
|
||||||
|
|
||||||
|
| Property | Value | SCSS Variable |
|
||||||
|
|----------|-------|---------------|
|
||||||
|
| **Text Color** | Green 500 `#078139` | `$green-500` |
|
||||||
|
| **Background** | Green 100 `#EAFCF1` | `$green-100` |
|
||||||
|
| **Border Color** | Green 500 `#078139` | `$green-500` |
|
||||||
|
| **Border Width** | `2px` | - |
|
||||||
|
|
||||||
|
> **Icon Color:** Inherits text color via `currentColor` (automatically becomes Green 500)
|
||||||
|
|
||||||
|
**Desktop Padding & Gap:**
|
||||||
|
| Property | With Icon | Without Icon |
|
||||||
|
|----------|-----------|--------------|
|
||||||
|
| Padding | `8px 13px 8px 20px` | `8px 20px` |
|
||||||
|
| Gap | `22px` | N/A |
|
||||||
|
|
||||||
|
**Tablet/Mobile Padding & Gap (≤1023px):**
|
||||||
|
| Property | With Icon | Without Icon |
|
||||||
|
|----------|-----------|--------------|
|
||||||
|
| Padding | `8px 10px 8px 16px` | `8px 16px` |
|
||||||
|
| Gap | `21px` | N/A |
|
||||||
|
|
||||||
|
> **Arrow Animation:** Handled by base `.bds-btn` class - line shrinks from left-to-right (shared behavior)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Focus State (Keyboard Navigation)
|
||||||
|
|
||||||
|
| Property | Value | SCSS Variable |
|
||||||
|
|----------|-------|---------------|
|
||||||
|
| **Text Color** | Green 500 `#078139` | `$green-500` |
|
||||||
|
| **Background** | Green 100 `#EAFCF1` | `$green-100` |
|
||||||
|
| **Border Color** | Green 500 `#078139` | `$green-500` |
|
||||||
|
| **Border Width** | `2px` | - |
|
||||||
|
| **Focus Ring** | Black `#141414`, 2px | `$bds-btn-primary-focus-border` |
|
||||||
|
|
||||||
|
> **Icon Color:** Inherits text color via `currentColor` (automatically becomes Green 500)
|
||||||
|
|
||||||
|
The focus state shows a **double border** effect:
|
||||||
|
1. Inner border: Green 500 (the button's stroke)
|
||||||
|
2. Outer border: Black (focus indicator ring)
|
||||||
|
|
||||||
|
**Desktop Padding & Gap:**
|
||||||
|
| Property | With Icon | Without Icon |
|
||||||
|
|----------|-----------|--------------|
|
||||||
|
| Padding | `6px 11px 6px 18px` | `6px 17px 6px 18px` |
|
||||||
|
| Gap | `22px` | N/A |
|
||||||
|
|
||||||
|
> **Note:** Padding is reduced by 2px on all sides to compensate for the additional focus ring border.
|
||||||
|
|
||||||
|
**Tablet/Mobile Padding & Gap (≤1023px):**
|
||||||
|
| Property | With Icon | Without Icon |
|
||||||
|
|----------|-----------|--------------|
|
||||||
|
| Padding | `6px 8px 6px 14px` | `6px 13px 6px 14px` |
|
||||||
|
| Gap | `21px` | N/A |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Active State (Being Pressed)
|
||||||
|
|
||||||
|
| Property | Value | SCSS Variable |
|
||||||
|
|----------|-------|---------------|
|
||||||
|
| **Text Color** | Green 400 `#0DAA3E` | `$green-400` |
|
||||||
|
| **Background** | Transparent | `transparent` |
|
||||||
|
| **Border Color** | Green 400 `#0DAA3E` | `$green-400` |
|
||||||
|
| **Border Width** | `2px` | - |
|
||||||
|
| **Transform** | `scale(0.98)` | - |
|
||||||
|
|
||||||
|
> **Icon Color:** Inherits text color via `currentColor` (returns to Green 400)
|
||||||
|
|
||||||
|
**Padding & Gap:** Returns to enabled state values
|
||||||
|
- Desktop: `8px 19px 8px 20px`, gap `16px`
|
||||||
|
- Tablet/Mobile: `8px 15px 8px 16px`, gap `16px`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. Disabled State
|
||||||
|
|
||||||
|
| Property | Value | SCSS Variable |
|
||||||
|
|----------|-------|---------------|
|
||||||
|
| **Text Color** | Neutral 400 `#8A919A` | `$gray-400` ¹ |
|
||||||
|
| **Background** | Transparent | `transparent` |
|
||||||
|
| **Border Color** | Neutral 400 `#8A919A` | `$gray-400` ¹ |
|
||||||
|
| **Border Width** | `2px` | - |
|
||||||
|
| **Cursor** | `not-allowed` | - |
|
||||||
|
| **Pointer Events** | `none` | - |
|
||||||
|
| **Icon** | Hidden (removed) | - |
|
||||||
|
|
||||||
|
> ¹ **Note:** The Figma design uses `#8A919A` for Neutral 400. The existing `_colors.scss` has `$gray-400: #A2A2A4`. Either use the existing variable for consistency or add a new token. Recommend using existing `$gray-400` for codebase consistency.
|
||||||
|
|
||||||
|
**Padding & Gap:** Same as enabled state
|
||||||
|
- Desktop: `8px 19px 8px 20px`, gap `16px`
|
||||||
|
- Tablet/Mobile: `8px 15px 8px 16px`, gap `16px`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Color Token Mapping
|
||||||
|
|
||||||
|
### Required Colors from `_colors.scss`
|
||||||
|
|
||||||
|
```scss
|
||||||
|
// Already available in styles/_colors.scss
|
||||||
|
$green-100: #EAFCF1; // Hover/Focus background
|
||||||
|
$green-400: #0DAA3E; // Enabled state (text, border, icon)
|
||||||
|
$green-500: #078139; // Hover/Focus state (text, border, icon)
|
||||||
|
$gray-400: #A2A2A4; // Disabled state (text, border) - closest match
|
||||||
|
```
|
||||||
|
|
||||||
|
### Recommended SCSS Variables for Secondary Button
|
||||||
|
|
||||||
|
```scss
|
||||||
|
// Colors - Secondary Button
|
||||||
|
$bds-btn-secondary-text: $green-400; // #0DAA3E - Enabled
|
||||||
|
$bds-btn-secondary-text-hover: $green-500; // #078139 - Hover/Focus
|
||||||
|
$bds-btn-secondary-border: $green-400; // #0DAA3E - Enabled
|
||||||
|
$bds-btn-secondary-border-hover: $green-500; // #078139 - Hover/Focus
|
||||||
|
$bds-btn-secondary-bg-hover: $green-100; // #EAFCF1 - Hover/Focus fill
|
||||||
|
$bds-btn-secondary-disabled-text: $gray-400; // Disabled text & border
|
||||||
|
$bds-btn-secondary-disabled-border: $gray-400; // Disabled border
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Structure
|
||||||
|
|
||||||
|
### CSS Class Names (BEM)
|
||||||
|
|
||||||
|
```
|
||||||
|
// SHARED (already exist in base .bds-btn - DO NOT DUPLICATE)
|
||||||
|
.bds-btn // Base button layout, typography, transitions
|
||||||
|
.bds-btn__label // Label element
|
||||||
|
.bds-btn__icon // Icon container (uses currentColor)
|
||||||
|
.bds-btn__icon-line // Arrow line + hover animation
|
||||||
|
.bds-btn__icon-chevron // Arrow chevron
|
||||||
|
.bds-btn--disabled // Disabled state modifier
|
||||||
|
.bds-btn--no-icon // No icon modifier
|
||||||
|
|
||||||
|
// VARIANT-SPECIFIC (add for secondary)
|
||||||
|
.bds-btn--secondary // Colors, borders, padding/gap values only
|
||||||
|
```
|
||||||
|
|
||||||
|
### Component Props
|
||||||
|
|
||||||
|
The existing `ButtonProps` interface supports the secondary variant:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
interface ButtonProps {
|
||||||
|
variant?: 'primary' | 'secondary'; // Add 'secondary' to union type
|
||||||
|
children: React.ReactNode;
|
||||||
|
onClick?: () => void;
|
||||||
|
disabled?: boolean;
|
||||||
|
type?: 'button' | 'submit' | 'reset';
|
||||||
|
className?: string;
|
||||||
|
showIcon?: boolean;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## SCSS Implementation Guide
|
||||||
|
|
||||||
|
> ⚠️ **Important:** Do NOT add any icon/arrow styles to `.bds-btn--secondary`. The icon inherits its color via `currentColor` and the hover animation is already handled in the base `.bds-btn` class.
|
||||||
|
|
||||||
|
### Design Tokens to Add
|
||||||
|
|
||||||
|
```scss
|
||||||
|
// =============================================================================
|
||||||
|
// Design Tokens - Secondary Button
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
// Colors - Secondary Button
|
||||||
|
$bds-btn-secondary-text: $green-400; // #0DAA3E
|
||||||
|
$bds-btn-secondary-text-hover: $green-500; // #078139
|
||||||
|
$bds-btn-secondary-bg: transparent;
|
||||||
|
$bds-btn-secondary-bg-hover: $green-100; // #EAFCF1
|
||||||
|
$bds-btn-secondary-border: $green-400; // #0DAA3E
|
||||||
|
$bds-btn-secondary-border-hover: $green-500; // #078139
|
||||||
|
$bds-btn-secondary-disabled-text: $gray-400; // Disabled state
|
||||||
|
$bds-btn-secondary-disabled-border: $gray-400; // Disabled border
|
||||||
|
```
|
||||||
|
|
||||||
|
### State Styles Structure
|
||||||
|
|
||||||
|
```scss
|
||||||
|
// =============================================================================
|
||||||
|
// Secondary Variant
|
||||||
|
// =============================================================================
|
||||||
|
// NOTE: Arrow icon animation is inherited from base .bds-btn class.
|
||||||
|
// The icon color automatically follows text color via currentColor.
|
||||||
|
// Only define: colors, backgrounds, borders, padding, and gap.
|
||||||
|
|
||||||
|
.bds-btn--secondary {
|
||||||
|
// Default/Enabled state
|
||||||
|
color: $bds-btn-secondary-text;
|
||||||
|
background-color: $bds-btn-secondary-bg;
|
||||||
|
border: 2px solid $bds-btn-secondary-border;
|
||||||
|
|
||||||
|
// Desktop padding and gap (≥1024px)
|
||||||
|
padding: 6px 17px 6px 18px; // Compensate for 2px border
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
// No icon - symmetric padding
|
||||||
|
&.bds-btn--no-icon {
|
||||||
|
padding: 6px 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Hover State
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
&:hover:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
|
color: $bds-btn-secondary-text-hover;
|
||||||
|
background-color: $bds-btn-secondary-bg-hover;
|
||||||
|
border-color: $bds-btn-secondary-border-hover;
|
||||||
|
padding: 6px 11px 6px 18px;
|
||||||
|
gap: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
|
color: $bds-btn-secondary-text-hover;
|
||||||
|
background-color: $bds-btn-secondary-bg-hover;
|
||||||
|
border-color: $bds-btn-secondary-border-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Focus State (keyboard navigation)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
|
color: $bds-btn-secondary-text-hover;
|
||||||
|
background-color: $bds-btn-secondary-bg-hover;
|
||||||
|
border-color: $bds-btn-secondary-border-hover;
|
||||||
|
outline: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||||
|
outline-offset: 0;
|
||||||
|
padding: 6px 11px 6px 18px;
|
||||||
|
gap: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
|
color: $bds-btn-secondary-text-hover;
|
||||||
|
background-color: $bds-btn-secondary-bg-hover;
|
||||||
|
border-color: $bds-btn-secondary-border-hover;
|
||||||
|
outline: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||||
|
outline-offset: 0;
|
||||||
|
padding: 6px 17px 6px 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Active State (being pressed)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
&:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: $bds-btn-secondary-text;
|
||||||
|
background-color: $bds-btn-secondary-bg;
|
||||||
|
border-color: $bds-btn-secondary-border;
|
||||||
|
transform: scale(0.98);
|
||||||
|
padding: 6px 17px 6px 18px;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Disabled State
|
||||||
|
// Note: Icon is hidden via component logic when disabled
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
&:disabled,
|
||||||
|
&.bds-btn--disabled {
|
||||||
|
color: $bds-btn-secondary-disabled-text;
|
||||||
|
background-color: transparent;
|
||||||
|
border-color: $bds-btn-secondary-disabled-border;
|
||||||
|
cursor: not-allowed;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Tablet & Mobile Responsive Styles (≤1023px)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
@media (max-width: 1023px) {
|
||||||
|
padding: 6px 13px 6px 14px;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
&.bds-btn--no-icon {
|
||||||
|
padding: 6px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
|
padding: 6px 8px 6px 14px;
|
||||||
|
gap: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
|
// Background and border color changes applied, padding stable
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
|
padding: 6px 8px 6px 14px;
|
||||||
|
gap: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
|
padding: 6px 13px 6px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
padding: 6px 13px 6px 14px;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Differences from Primary Button
|
||||||
|
|
||||||
|
| Aspect | Primary | Secondary |
|
||||||
|
|--------|---------|-----------|
|
||||||
|
| **Background (Enabled)** | Green 300 `#21E46B` | Transparent |
|
||||||
|
| **Background (Hover/Focus)** | Green 200 `#70EE97` | Green 100 `#EAFCF1` |
|
||||||
|
| **Border (Enabled)** | None | 2px Green 400 `#0DAA3E` |
|
||||||
|
| **Border (Hover/Focus)** | None (only focus ring) | 2px Green 500 `#078139` |
|
||||||
|
| **Text Color (Enabled)** | Neutral Black `#141414` | Green 400 `#0DAA3E` |
|
||||||
|
| **Text Color (Hover/Focus)** | Neutral Black `#141414` | Green 500 `#078139` |
|
||||||
|
| **Disabled Background** | Gray 200 `#E0E0E1` | Transparent |
|
||||||
|
| **Disabled Border** | None | 2px Gray 400 |
|
||||||
|
| **Focus Ring** | 2px Black border | 2px Black outline (additional) |
|
||||||
|
| **Arrow Icon** | ✅ Shared (base class) | ✅ Shared (base class) |
|
||||||
|
| **Arrow Animation** | ✅ Shared (base class) | ✅ Shared (base class) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Accessibility Notes
|
||||||
|
|
||||||
|
1. **Color Contrast:** Green 400/500 on white background meets WCAG AA requirements
|
||||||
|
2. **Focus Indicator:** Black outline provides clear keyboard navigation visibility
|
||||||
|
3. **Disabled State:** Reduced opacity icon + muted colors clearly indicate non-interactive state
|
||||||
|
4. **Icon:** `aria-hidden="true"` on arrow icon (decorative)
|
||||||
|
5. **Button:** `aria-disabled` attribute mirrors disabled prop
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Example
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// Secondary button with icon (default)
|
||||||
|
<Button variant="secondary" onClick={handleClick}>
|
||||||
|
Learn More
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
// Secondary button without icon
|
||||||
|
<Button variant="secondary" showIcon={false} onClick={handleClick}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
// Disabled secondary button
|
||||||
|
<Button variant="secondary" disabled>
|
||||||
|
Unavailable
|
||||||
|
</Button>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Checklist for Implementation
|
||||||
|
|
||||||
|
- [ ] Add `'secondary'` to variant union type in `ButtonProps`
|
||||||
|
- [ ] Add Secondary button SCSS variables to design tokens section
|
||||||
|
- [ ] Implement `.bds-btn--secondary` styles (colors, borders, padding/gap only)
|
||||||
|
- [ ] Add responsive styles for tablet/mobile breakpoint
|
||||||
|
- [ ] **DO NOT duplicate arrow icon or animation styles** (inherited from base)
|
||||||
|
- [ ] Verify arrow icon color changes automatically via `currentColor`
|
||||||
|
- [ ] Test hover, focus, active, disabled states
|
||||||
|
- [ ] Verify arrow icon animation works correctly (inherited behavior)
|
||||||
|
- [ ] Test with and without icon (`showIcon` prop)
|
||||||
|
- [ ] Verify color contrast meets WCAG requirements
|
||||||
|
- [ ] Test keyboard navigation (Tab + Enter/Space)
|
||||||
@@ -2,13 +2,16 @@
|
|||||||
// Brand Design System - Scalable button component
|
// Brand Design System - Scalable button component
|
||||||
//
|
//
|
||||||
// Naming Convention: BEM with 'bds' namespace
|
// Naming Convention: BEM with 'bds' namespace
|
||||||
// .bds-btn - Base button
|
// .bds-btn - Base button (shared layout, typography, icon animation)
|
||||||
// .bds-btn--primary - Primary variant modifier
|
// .bds-btn--primary - Primary variant (solid background)
|
||||||
// .bds-btn--secondary - (Future) Secondary variant
|
// .bds-btn--secondary - Secondary variant (outline style)
|
||||||
|
// .bds-btn--green - Green color theme (default)
|
||||||
|
// .bds-btn--black - Black color theme
|
||||||
// .bds-btn--tertiary - (Future) Tertiary variant
|
// .bds-btn--tertiary - (Future) Tertiary variant
|
||||||
// .bds-btn__label - Label element
|
// .bds-btn__label - Label element
|
||||||
// .bds-btn__icon - Icon element
|
// .bds-btn__icon - Icon element (inherits color via currentColor)
|
||||||
// .bds-btn--disabled - Disabled state modifier
|
// .bds-btn--disabled - Disabled state modifier
|
||||||
|
// .bds-btn--no-icon - No icon modifier
|
||||||
|
|
||||||
@import "../../../styles/colors";
|
@import "../../../styles/colors";
|
||||||
|
|
||||||
@@ -16,27 +19,58 @@
|
|||||||
// Design Tokens
|
// Design Tokens
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
// Colors - Primary Button
|
// Neutral Black (used across variants)
|
||||||
|
$bds-btn-neutral-black: #141414;
|
||||||
|
$bds-btn-neutral-black-80: rgba(20, 20, 20, 0.8); // 80% black for hover
|
||||||
|
$bds-btn-neutral-black-15: rgba(20, 20, 20, 0.15); // 15% black for secondary hover
|
||||||
|
|
||||||
|
// Colors - Green Primary Button
|
||||||
$bds-btn-primary-bg: $green-300; // #21E46B - Enabled
|
$bds-btn-primary-bg: $green-300; // #21E46B - Enabled
|
||||||
$bds-btn-primary-bg-hover: $green-200; // #70EE97 - Hover/Focus
|
$bds-btn-primary-bg-hover: $green-200; // #70EE97 - Hover/Focus
|
||||||
$bds-btn-primary-text: #141414; // Neutral Black
|
$bds-btn-primary-text: $bds-btn-neutral-black;
|
||||||
$bds-btn-primary-focus-border: #141414; // Black focus ring
|
$bds-btn-primary-focus-border: $bds-btn-neutral-black;
|
||||||
|
|
||||||
// Colors - Disabled State
|
// Colors - Black Primary Button
|
||||||
|
$bds-btn-primary-black-bg: $bds-btn-neutral-black;
|
||||||
|
$bds-btn-primary-black-bg-hover: $bds-btn-neutral-black-80;
|
||||||
|
$bds-btn-primary-black-text: $white;
|
||||||
|
|
||||||
|
// Colors - Disabled State (shared)
|
||||||
$bds-btn-disabled-bg: $gray-200; // #E0E0E1
|
$bds-btn-disabled-bg: $gray-200; // #E0E0E1
|
||||||
$bds-btn-disabled-text: $gray-500; // #838386
|
$bds-btn-disabled-text: $gray-500; // #838386
|
||||||
|
|
||||||
|
// Colors - Green Secondary Button
|
||||||
|
$bds-btn-secondary-text: $green-400; // #0DAA3E - Enabled
|
||||||
|
$bds-btn-secondary-text-hover: $green-500; // #078139 - Hover/Focus
|
||||||
|
$bds-btn-secondary-bg: transparent;
|
||||||
|
$bds-btn-secondary-bg-hover: $green-100; // #EAFCF1 - Hover/Focus fill
|
||||||
|
$bds-btn-secondary-border: $green-400; // #0DAA3E - Enabled
|
||||||
|
$bds-btn-secondary-border-hover: $green-500; // #078139 - Hover/Focus
|
||||||
|
$bds-btn-secondary-disabled-text: $gray-400; // Disabled text
|
||||||
|
$bds-btn-secondary-disabled-border: $gray-400; // Disabled border
|
||||||
|
|
||||||
|
// Colors - Black Secondary Button
|
||||||
|
$bds-btn-secondary-black-text: $bds-btn-neutral-black;
|
||||||
|
$bds-btn-secondary-black-bg-hover: $bds-btn-neutral-black-15;
|
||||||
|
$bds-btn-secondary-black-border: $bds-btn-neutral-black;
|
||||||
|
|
||||||
// Spacing
|
// Spacing
|
||||||
$bds-btn-border-radius: 100px;
|
$bds-btn-border-radius: 100px;
|
||||||
$bds-btn-focus-border-width: 2px;
|
$bds-btn-focus-border-width: 2px;
|
||||||
|
|
||||||
// Transitions
|
// Transitions
|
||||||
|
// Motion: Duration 150ms, Custom bezier for smooth in-out feel
|
||||||
$bds-btn-transition-duration: 150ms;
|
$bds-btn-transition-duration: 150ms;
|
||||||
$bds-btn-transition-timing: ease-in-out;
|
$bds-btn-transition-timing: cubic-bezier(0.98, 0.12, 0.12, 0.98);
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Base Button Styles
|
// Base Button Styles
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// SHARED HOVER ANIMATION:
|
||||||
|
// - Background fills from bottom-to-top using ::before pseudo-element
|
||||||
|
// - On unhover: background empties top-to-bottom
|
||||||
|
// - Each variant defines its own ::before background-color
|
||||||
|
|
||||||
.bds-btn {
|
.bds-btn {
|
||||||
// Layout
|
// Layout
|
||||||
@@ -44,6 +78,7 @@ $bds-btn-transition-timing: ease-in-out;
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
max-height: 40px;
|
max-height: 40px;
|
||||||
|
|
||||||
// Typography - Label R token
|
// Typography - Label R token
|
||||||
font-family: 'Booton', sans-serif;
|
font-family: 'Booton', sans-serif;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@@ -59,14 +94,55 @@ $bds-btn-transition-timing: ease-in-out;
|
|||||||
// Interaction
|
// Interaction
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
// Transitions
|
// Required for pseudo-element background animation (shared)
|
||||||
transition-property: background-color, border-color, transform, padding, gap;
|
position: relative;
|
||||||
transition-duration: $bds-btn-transition-duration;
|
overflow: hidden;
|
||||||
transition-timing-function: $bds-btn-transition-timing;
|
z-index: 1;
|
||||||
|
|
||||||
|
// Transitions (shared)
|
||||||
|
transition: color $bds-btn-transition-duration $bds-btn-transition-timing,
|
||||||
|
border-color $bds-btn-transition-duration $bds-btn-transition-timing,
|
||||||
|
padding $bds-btn-transition-duration $bds-btn-transition-timing,
|
||||||
|
gap $bds-btn-transition-duration $bds-btn-transition-timing,
|
||||||
|
transform $bds-btn-transition-duration $bds-btn-transition-timing;
|
||||||
|
|
||||||
|
// Background fill pseudo-element (shared structure)
|
||||||
|
// Each variant sets its own background-color
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: -1;
|
||||||
|
|
||||||
|
// Start scaled to 0 from bottom - fills bottom-to-top on hover
|
||||||
|
transform: scaleY(0);
|
||||||
|
transform-origin: bottom center;
|
||||||
|
transition: transform $bds-btn-transition-duration $bds-btn-transition-timing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hover/Focus state - animate background fill (shared)
|
||||||
|
&:hover:not(:disabled):not(.bds-btn--disabled),
|
||||||
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
&::before {
|
||||||
|
transform: scaleY(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Active state - reset background (shared)
|
||||||
|
&:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
&::before {
|
||||||
|
transform: scaleY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Label element
|
// Label element
|
||||||
&__label {
|
&__label {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Icon element (SVG container)
|
// Icon element (SVG container)
|
||||||
@@ -77,6 +153,8 @@ $bds-btn-transition-timing: ease-in-out;
|
|||||||
transition: opacity $bds-btn-transition-duration $bds-btn-transition-timing;
|
transition: opacity $bds-btn-transition-duration $bds-btn-transition-timing;
|
||||||
color: currentColor;
|
color: currentColor;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arrow horizontal line - shrinks on hover/focus
|
// Arrow horizontal line - shrinks on hover/focus
|
||||||
@@ -104,12 +182,18 @@ $bds-btn-transition-timing: ease-in-out;
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Primary Variant
|
// Primary Variant
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
// HOVER ANIMATION: Background fills bottom-to-top (Green 300 → Green 200)
|
||||||
|
|
||||||
.bds-btn--primary {
|
.bds-btn--primary {
|
||||||
// Default/Enabled state colors
|
// Default/Enabled state colors
|
||||||
color: $bds-btn-primary-text;
|
color: $bds-btn-primary-text;
|
||||||
background-color: $bds-btn-primary-bg;
|
background-color: $bds-btn-primary-bg;
|
||||||
|
|
||||||
|
// Set the hover background color for ::before pseudo-element
|
||||||
|
&::before {
|
||||||
|
background-color: $bds-btn-primary-bg-hover;
|
||||||
|
}
|
||||||
|
|
||||||
// Desktop padding and gap (default - ≥1024px)
|
// Desktop padding and gap (default - ≥1024px)
|
||||||
padding: 8px 19px 8px 20px;
|
padding: 8px 19px 8px 20px;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
@@ -123,51 +207,44 @@ $bds-btn-transition-timing: ease-in-out;
|
|||||||
// Hover State (with icon)
|
// Hover State (with icon)
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
&:hover:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
&:hover:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
background-color: $bds-btn-primary-bg-hover;
|
// Background animation handled by shared ::before pseudo-element
|
||||||
// Adjust padding to compensate for icon gap change (maintains button width)
|
|
||||||
padding: 8px 13px 8px 20px;
|
padding: 8px 13px 8px 20px;
|
||||||
gap: 22px;
|
gap: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hover State (no icon) - only change background, keep padding stable
|
// Hover State (no icon) - background animation only
|
||||||
&:hover:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
// (no padding/gap changes needed)
|
||||||
background-color: $bds-btn-primary-bg-hover;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Focus State (keyboard navigation) - with icon
|
// Focus State (keyboard navigation) - with icon
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
&:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
background-color: $bds-btn-primary-bg-hover;
|
outline: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||||
border: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
outline-offset: 2px;
|
||||||
outline: none;
|
padding: 8px 13px 8px 20px;
|
||||||
// Compensate for 2px border on all sides
|
|
||||||
padding: 6px 11px 6px 18px;
|
|
||||||
gap: 22px;
|
gap: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Focus State (no icon) - only change background and add border
|
// Focus State (no icon) - only add outline
|
||||||
&:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
background-color: $bds-btn-primary-bg-hover;
|
outline: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||||
border: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
outline-offset: 2px;
|
||||||
outline: none;
|
padding: 8px 20px;
|
||||||
// Compensate for 2px border but keep symmetric padding
|
|
||||||
padding: 6px 17px 6px 18px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Active State (being pressed)
|
// Active State (being pressed)
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
&:active:not(:disabled):not(.bds-btn--disabled) {
|
&:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
background-color: $bds-btn-primary-bg;
|
|
||||||
transform: scale(0.98);
|
|
||||||
// Maintains default padding and gap
|
// Maintains default padding and gap
|
||||||
padding: 8px 19px 8px 20px;
|
padding: 8px 19px 8px 20px;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
|
// Background reset handled by shared ::before in base class
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Disabled State
|
// Disabled State
|
||||||
|
// Note: Icon is hidden via component logic when disabled
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
&:disabled,
|
&:disabled,
|
||||||
&.bds-btn--disabled {
|
&.bds-btn--disabled {
|
||||||
@@ -176,8 +253,9 @@ $bds-btn-transition-timing: ease-in-out;
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
.bds-btn__icon {
|
// Disable background animation on disabled
|
||||||
opacity: 0.5;
|
&::before {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,20 +278,19 @@ $bds-btn-transition-timing: ease-in-out;
|
|||||||
gap: 21px;
|
gap: 21px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hover state - smaller screens (no icon)
|
|
||||||
&:hover:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
|
||||||
background-color: $bds-btn-primary-bg-hover;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Focus state - smaller screens (with icon)
|
// Focus state - smaller screens (with icon)
|
||||||
&:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
padding: 6px 8px 6px 14px;
|
outline: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||||
|
outline-offset: 2px;
|
||||||
|
padding: 8px 10px 8px 16px;
|
||||||
gap: 21px;
|
gap: 21px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Focus state - smaller screens (no icon)
|
// Focus state - smaller screens (no icon)
|
||||||
&:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
padding: 6px 13px 6px 14px;
|
outline: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||||
|
outline-offset: 2px;
|
||||||
|
padding: 8px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Active state - smaller screens (maintains default padding)
|
// Active state - smaller screens (maintains default padding)
|
||||||
@@ -224,15 +301,230 @@ $bds-btn-transition-timing: ease-in-out;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Secondary Variant
|
||||||
|
// =============================================================================
|
||||||
|
// HOVER ANIMATION: Background fills bottom-to-top (Transparent → Green 100)
|
||||||
|
// Text/arrow color fades from green-400 to green-500 via currentColor
|
||||||
|
// Animation structure inherited from base .bds-btn class
|
||||||
|
|
||||||
|
.bds-btn--secondary {
|
||||||
|
// Default/Enabled state
|
||||||
|
color: $bds-btn-secondary-text;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 2px solid $bds-btn-secondary-border;
|
||||||
|
|
||||||
|
// Set the hover background color for ::before pseudo-element
|
||||||
|
&::before {
|
||||||
|
background-color: $bds-btn-secondary-bg-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Desktop padding and gap (≥1024px) - compensate for 2px border
|
||||||
|
padding: 6px 17px 6px 18px;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
// No icon - symmetric padding
|
||||||
|
&.bds-btn--no-icon {
|
||||||
|
padding: 6px 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Hover State
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
&:hover:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
|
color: $bds-btn-secondary-text-hover;
|
||||||
|
border-color: $bds-btn-secondary-border-hover;
|
||||||
|
padding: 6px 11px 6px 18px;
|
||||||
|
gap: 22px;
|
||||||
|
// Background animation handled by shared ::before in base class
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
|
color: $bds-btn-secondary-text-hover;
|
||||||
|
border-color: $bds-btn-secondary-border-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Focus State (keyboard navigation)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
|
color: $bds-btn-secondary-text-hover;
|
||||||
|
border: none;
|
||||||
|
outline: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||||
|
outline-offset: 2px;
|
||||||
|
// Add 2px padding to compensate for removed border, maintain hover padding
|
||||||
|
padding: 6px 13px 6px 20px;
|
||||||
|
gap: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
|
color: $bds-btn-secondary-text-hover;
|
||||||
|
border: none;
|
||||||
|
outline: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||||
|
outline-offset: 2px;
|
||||||
|
// Add 2px padding to compensate for removed border
|
||||||
|
padding: 6px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Active State (being pressed)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
&:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: $bds-btn-secondary-text;
|
||||||
|
border-color: $bds-btn-secondary-border;
|
||||||
|
padding: 6px 17px 6px 18px;
|
||||||
|
gap: 16px;
|
||||||
|
// Background reset handled by shared ::before in base class
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Disabled State
|
||||||
|
// Note: Icon is hidden via component logic when disabled
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
&:disabled,
|
||||||
|
&.bds-btn--disabled {
|
||||||
|
color: $bds-btn-secondary-disabled-text;
|
||||||
|
background-color: transparent;
|
||||||
|
border-color: $bds-btn-secondary-disabled-border;
|
||||||
|
cursor: not-allowed;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
// Disable background animation on disabled
|
||||||
|
&::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Tablet & Mobile Responsive Styles (≤1023px)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
@media (max-width: 1023px) {
|
||||||
|
padding: 6px 13px 6px 14px;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
&.bds-btn--no-icon {
|
||||||
|
padding: 6px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
|
padding: 6px 8px 6px 14px;
|
||||||
|
gap: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
|
border: none;
|
||||||
|
outline: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||||
|
outline-offset: 2px;
|
||||||
|
// Add 2px padding to compensate for removed border, maintain hover padding
|
||||||
|
padding: 6px 10px 6px 16px;
|
||||||
|
gap: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
|
border: none;
|
||||||
|
outline: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||||
|
outline-offset: 2px;
|
||||||
|
// Add 2px padding to compensate for removed border
|
||||||
|
padding: 6px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
padding: 6px 13px 6px 14px;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Color Themes
|
||||||
|
// =============================================================================
|
||||||
|
// Green theme (.bds-btn--green) is the default - no overrides needed.
|
||||||
|
// Black theme (.bds-btn--black) overrides colors for both variants.
|
||||||
|
|
||||||
|
// Black theme - overrides colors for primary and secondary variants
|
||||||
|
.bds-btn--black {
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Black Primary Button
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
&.bds-btn--primary {
|
||||||
|
color: $bds-btn-primary-black-text;
|
||||||
|
background-color: $bds-btn-primary-black-bg;
|
||||||
|
|
||||||
|
// Set hover background for ::before pseudo-element
|
||||||
|
&::before {
|
||||||
|
background-color: $bds-btn-primary-black-bg-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hover state - background animates, colors stay same
|
||||||
|
&:hover:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: $bds-btn-primary-black-text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus state
|
||||||
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: $bds-btn-primary-black-text;
|
||||||
|
outline: $bds-btn-focus-border-width solid $bds-btn-neutral-black;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Active state
|
||||||
|
&:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: $bds-btn-primary-black-text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disabled state - same as green disabled
|
||||||
|
&:disabled,
|
||||||
|
&.bds-btn--disabled {
|
||||||
|
color: $bds-btn-disabled-text;
|
||||||
|
background-color: $bds-btn-disabled-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Black Secondary Button
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
&.bds-btn--secondary {
|
||||||
|
color: $bds-btn-secondary-black-text;
|
||||||
|
border-color: $bds-btn-secondary-black-border;
|
||||||
|
|
||||||
|
// Set hover background for ::before pseudo-element
|
||||||
|
&::before {
|
||||||
|
background-color: $bds-btn-secondary-black-bg-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hover state - text stays black, background fills with 15% black
|
||||||
|
&:hover:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: $bds-btn-secondary-black-text;
|
||||||
|
border-color: $bds-btn-secondary-black-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus state
|
||||||
|
&:focus-visible:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: $bds-btn-secondary-black-text;
|
||||||
|
border: none;
|
||||||
|
outline: $bds-btn-focus-border-width solid $bds-btn-neutral-black;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Active state
|
||||||
|
&:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: $bds-btn-secondary-black-text;
|
||||||
|
border-color: $bds-btn-secondary-black-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disabled state
|
||||||
|
&:disabled,
|
||||||
|
&.bds-btn--disabled {
|
||||||
|
color: $bds-btn-disabled-text;
|
||||||
|
border-color: $bds-btn-secondary-disabled-border;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Future Variants (Placeholder structure for scalability)
|
// Future Variants (Placeholder structure for scalability)
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
// .bds-btn--secondary {
|
|
||||||
// // Outline style: green stroke, transparent fill
|
|
||||||
// // States: enabled, hover, focus, active, disabled
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .bds-btn--tertiary {
|
// .bds-btn--tertiary {
|
||||||
// // Text-only style: green text, no border/fill
|
// // Text-only style: green text, no border/fill
|
||||||
// // States: enabled, hover (underline), focus, active, disabled
|
// // States: enabled, hover (underline), focus, active, disabled
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ import React from 'react';
|
|||||||
|
|
||||||
export interface ButtonProps {
|
export interface ButtonProps {
|
||||||
/** Button variant - determines visual style */
|
/** Button variant - determines visual style */
|
||||||
variant?: 'primary'; // Extensible: | 'secondary' | 'tertiary'
|
variant?: 'primary' | 'secondary';
|
||||||
|
/** Color theme - green (default) or black */
|
||||||
|
color?: 'green' | 'black';
|
||||||
/** Button content/label */
|
/** Button content/label */
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
/** Click handler */
|
/** Click handler */
|
||||||
@@ -59,13 +61,16 @@ const ArrowIcon: React.FC = () => (
|
|||||||
* BDS Button Component
|
* BDS Button Component
|
||||||
*
|
*
|
||||||
* A scalable button component following the XRPL Brand Design System.
|
* A scalable button component following the XRPL Brand Design System.
|
||||||
* Currently supports the Primary variant with plans for Secondary and Tertiary.
|
* Supports Primary and Secondary variants with green (default) or black color themes.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* <Button variant="primary" onClick={handleClick}>Get Started</Button>
|
* <Button variant="primary" onClick={handleClick}>Get Started</Button>
|
||||||
|
* <Button variant="secondary" onClick={handleClick}>Learn More</Button>
|
||||||
|
* <Button variant="primary" color="black" onClick={handleClick}>Dark Button</Button>
|
||||||
*/
|
*/
|
||||||
export const Button: React.FC<ButtonProps> = ({
|
export const Button: React.FC<ButtonProps> = ({
|
||||||
variant = 'primary',
|
variant = 'primary',
|
||||||
|
color = 'green',
|
||||||
children,
|
children,
|
||||||
onClick,
|
onClick,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
@@ -73,12 +78,16 @@ export const Button: React.FC<ButtonProps> = ({
|
|||||||
className = '',
|
className = '',
|
||||||
showIcon = true,
|
showIcon = true,
|
||||||
}) => {
|
}) => {
|
||||||
|
// Hide icon when disabled (per design spec)
|
||||||
|
const shouldShowIcon = showIcon && !disabled;
|
||||||
|
|
||||||
// Build class names using BEM with bds namespace
|
// Build class names using BEM with bds namespace
|
||||||
const classNames = [
|
const classNames = [
|
||||||
'bds-btn',
|
'bds-btn',
|
||||||
`bds-btn--${variant}`,
|
`bds-btn--${variant}`,
|
||||||
|
`bds-btn--${color}`,
|
||||||
disabled ? 'bds-btn--disabled' : '',
|
disabled ? 'bds-btn--disabled' : '',
|
||||||
!showIcon ? 'bds-btn--no-icon' : '',
|
!shouldShowIcon ? 'bds-btn--no-icon' : '',
|
||||||
className,
|
className,
|
||||||
]
|
]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
@@ -93,7 +102,7 @@ export const Button: React.FC<ButtonProps> = ({
|
|||||||
aria-disabled={disabled}
|
aria-disabled={disabled}
|
||||||
>
|
>
|
||||||
<span className="bds-btn__label">{children}</span>
|
<span className="bds-btn__label">{children}</span>
|
||||||
{showIcon && <ArrowIcon />}
|
{shouldShowIcon && <ArrowIcon />}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11159,29 +11159,52 @@ button[disabled=disabled] {
|
|||||||
border: none;
|
border: none;
|
||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition-property: background-color, border-color, transform, padding, gap;
|
position: relative;
|
||||||
transition-duration: 150ms;
|
overflow: hidden;
|
||||||
transition-timing-function: ease-in-out;
|
z-index: 1;
|
||||||
|
transition: color 150ms cubic-bezier(0.98, 0.12, 0.12, 0.98), border-color 150ms cubic-bezier(0.98, 0.12, 0.12, 0.98), padding 150ms cubic-bezier(0.98, 0.12, 0.12, 0.98), gap 150ms cubic-bezier(0.98, 0.12, 0.12, 0.98), transform 150ms cubic-bezier(0.98, 0.12, 0.12, 0.98);
|
||||||
|
}
|
||||||
|
.bds-btn::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: -1;
|
||||||
|
transform: scaleY(0);
|
||||||
|
transform-origin: bottom center;
|
||||||
|
transition: transform 150ms cubic-bezier(0.98, 0.12, 0.12, 0.98);
|
||||||
|
}
|
||||||
|
.bds-btn:hover:not(:disabled):not(.bds-btn--disabled)::before, .bds-btn:focus-visible:not(:disabled):not(.bds-btn--disabled)::before {
|
||||||
|
transform: scaleY(1);
|
||||||
|
}
|
||||||
|
.bds-btn:active:not(:disabled):not(.bds-btn--disabled)::before {
|
||||||
|
transform: scaleY(0);
|
||||||
}
|
}
|
||||||
.bds-btn__label {
|
.bds-btn__label {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.bds-btn__icon {
|
.bds-btn__icon {
|
||||||
width: 15px;
|
width: 15px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
transition: opacity 150ms ease-in-out;
|
transition: opacity 150ms cubic-bezier(0.98, 0.12, 0.12, 0.98);
|
||||||
color: currentColor;
|
color: currentColor;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.bds-btn__icon-line {
|
.bds-btn__icon-line {
|
||||||
transform-box: fill-box;
|
transform-box: fill-box;
|
||||||
transform-origin: right center;
|
transform-origin: right center;
|
||||||
transform: scaleX(1);
|
transform: scaleX(1);
|
||||||
transition: transform 150ms ease-in-out;
|
transition: transform 150ms cubic-bezier(0.98, 0.12, 0.12, 0.98);
|
||||||
}
|
}
|
||||||
.bds-btn__icon-chevron {
|
.bds-btn__icon-chevron {
|
||||||
transition: transform 150ms ease-in-out;
|
transition: transform 150ms cubic-bezier(0.98, 0.12, 0.12, 0.98);
|
||||||
}
|
}
|
||||||
.bds-btn:hover:not(:disabled):not(.bds-btn--disabled) .bds-btn__icon-line, .bds-btn:focus-visible:not(:disabled):not(.bds-btn--disabled) .bds-btn__icon-line {
|
.bds-btn:hover:not(:disabled):not(.bds-btn--disabled) .bds-btn__icon-line, .bds-btn:focus-visible:not(:disabled):not(.bds-btn--disabled) .bds-btn__icon-line {
|
||||||
transform: scaleX(0);
|
transform: scaleX(0);
|
||||||
@@ -11190,6 +11213,11 @@ button[disabled=disabled] {
|
|||||||
.bds-btn--primary {
|
.bds-btn--primary {
|
||||||
color: #141414;
|
color: #141414;
|
||||||
background-color: #21E46B;
|
background-color: #21E46B;
|
||||||
|
}
|
||||||
|
.bds-btn--primary::before {
|
||||||
|
background-color: #70EE97;
|
||||||
|
}
|
||||||
|
.bds-btn--primary {
|
||||||
padding: 8px 19px 8px 20px;
|
padding: 8px 19px 8px 20px;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
}
|
}
|
||||||
@@ -11197,29 +11225,21 @@ button[disabled=disabled] {
|
|||||||
padding: 8px 20px;
|
padding: 8px 20px;
|
||||||
}
|
}
|
||||||
.bds-btn--primary:hover:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
.bds-btn--primary:hover:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
background-color: #70EE97;
|
|
||||||
padding: 8px 13px 8px 20px;
|
padding: 8px 13px 8px 20px;
|
||||||
gap: 22px;
|
gap: 22px;
|
||||||
}
|
}
|
||||||
.bds-btn--primary:hover:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
|
||||||
background-color: #70EE97;
|
|
||||||
}
|
|
||||||
.bds-btn--primary:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
.bds-btn--primary:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
background-color: #70EE97;
|
outline: 2px solid #141414;
|
||||||
border: 2px solid #141414;
|
outline-offset: 2px;
|
||||||
outline: none;
|
padding: 8px 13px 8px 20px;
|
||||||
padding: 6px 11px 6px 18px;
|
|
||||||
gap: 22px;
|
gap: 22px;
|
||||||
}
|
}
|
||||||
.bds-btn--primary:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
.bds-btn--primary:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
background-color: #70EE97;
|
outline: 2px solid #141414;
|
||||||
border: 2px solid #141414;
|
outline-offset: 2px;
|
||||||
outline: none;
|
padding: 8px 20px;
|
||||||
padding: 6px 17px 6px 18px;
|
|
||||||
}
|
}
|
||||||
.bds-btn--primary:active:not(:disabled):not(.bds-btn--disabled) {
|
.bds-btn--primary:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
background-color: #21E46B;
|
|
||||||
transform: scale(0.98);
|
|
||||||
padding: 8px 19px 8px 20px;
|
padding: 8px 19px 8px 20px;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
}
|
}
|
||||||
@@ -11229,8 +11249,8 @@ button[disabled=disabled] {
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.bds-btn--primary:disabled .bds-btn__icon, .bds-btn--primary.bds-btn--disabled .bds-btn__icon {
|
.bds-btn--primary:disabled::before, .bds-btn--primary.bds-btn--disabled::before {
|
||||||
opacity: 0.5;
|
display: none;
|
||||||
}
|
}
|
||||||
@media (max-width: 1023px) {
|
@media (max-width: 1023px) {
|
||||||
.bds-btn--primary {
|
.bds-btn--primary {
|
||||||
@@ -11244,15 +11264,16 @@ button[disabled=disabled] {
|
|||||||
padding: 8px 10px 8px 16px;
|
padding: 8px 10px 8px 16px;
|
||||||
gap: 21px;
|
gap: 21px;
|
||||||
}
|
}
|
||||||
.bds-btn--primary:hover:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
|
||||||
background-color: #70EE97;
|
|
||||||
}
|
|
||||||
.bds-btn--primary:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
.bds-btn--primary:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
padding: 6px 8px 6px 14px;
|
outline: 2px solid #141414;
|
||||||
|
outline-offset: 2px;
|
||||||
|
padding: 8px 10px 8px 16px;
|
||||||
gap: 21px;
|
gap: 21px;
|
||||||
}
|
}
|
||||||
.bds-btn--primary:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
.bds-btn--primary:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
padding: 6px 13px 6px 14px;
|
outline: 2px solid #141414;
|
||||||
|
outline-offset: 2px;
|
||||||
|
padding: 8px 16px;
|
||||||
}
|
}
|
||||||
.bds-btn--primary:active:not(:disabled):not(.bds-btn--disabled) {
|
.bds-btn--primary:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
padding: 8px 15px 8px 16px;
|
padding: 8px 15px 8px 16px;
|
||||||
@@ -11260,6 +11281,141 @@ button[disabled=disabled] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bds-btn--secondary {
|
||||||
|
color: #0DAA3E;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 2px solid #0DAA3E;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary::before {
|
||||||
|
background-color: #EAFCF1;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary {
|
||||||
|
padding: 6px 17px 6px 18px;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary.bds-btn--no-icon {
|
||||||
|
padding: 6px 18px;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary:hover:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
|
color: #078139;
|
||||||
|
border-color: #078139;
|
||||||
|
padding: 6px 11px 6px 18px;
|
||||||
|
gap: 22px;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary:hover:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
|
color: #078139;
|
||||||
|
border-color: #078139;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
|
color: #078139;
|
||||||
|
border: none;
|
||||||
|
outline: 2px solid #141414;
|
||||||
|
outline-offset: 2px;
|
||||||
|
padding: 6px 13px 6px 20px;
|
||||||
|
gap: 22px;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
|
color: #078139;
|
||||||
|
border: none;
|
||||||
|
outline: 2px solid #141414;
|
||||||
|
outline-offset: 2px;
|
||||||
|
padding: 6px 20px;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: #0DAA3E;
|
||||||
|
border-color: #0DAA3E;
|
||||||
|
padding: 6px 17px 6px 18px;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary:disabled, .bds-btn--secondary.bds-btn--disabled {
|
||||||
|
color: #A2A2A4;
|
||||||
|
background-color: transparent;
|
||||||
|
border-color: #A2A2A4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary:disabled::before, .bds-btn--secondary.bds-btn--disabled::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
@media (max-width: 1023px) {
|
||||||
|
.bds-btn--secondary {
|
||||||
|
padding: 6px 13px 6px 14px;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary.bds-btn--no-icon {
|
||||||
|
padding: 6px 14px;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary:hover:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
|
padding: 6px 8px 6px 14px;
|
||||||
|
gap: 21px;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||||
|
border: none;
|
||||||
|
outline: 2px solid #141414;
|
||||||
|
outline-offset: 2px;
|
||||||
|
padding: 6px 10px 6px 16px;
|
||||||
|
gap: 21px;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||||
|
border: none;
|
||||||
|
outline: 2px solid #141414;
|
||||||
|
outline-offset: 2px;
|
||||||
|
padding: 6px 16px;
|
||||||
|
}
|
||||||
|
.bds-btn--secondary:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
padding: 6px 13px 6px 14px;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bds-btn--black.bds-btn--primary {
|
||||||
|
color: #FFFFFF;
|
||||||
|
background-color: #141414;
|
||||||
|
}
|
||||||
|
.bds-btn--black.bds-btn--primary::before {
|
||||||
|
background-color: rgba(20, 20, 20, 0.8);
|
||||||
|
}
|
||||||
|
.bds-btn--black.bds-btn--primary:hover:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
.bds-btn--black.bds-btn--primary:focus-visible:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: #FFFFFF;
|
||||||
|
outline: 2px solid #141414;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
.bds-btn--black.bds-btn--primary:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
.bds-btn--black.bds-btn--primary:disabled, .bds-btn--black.bds-btn--primary.bds-btn--disabled {
|
||||||
|
color: #838386;
|
||||||
|
background-color: #E0E0E1;
|
||||||
|
}
|
||||||
|
.bds-btn--black.bds-btn--secondary {
|
||||||
|
color: #141414;
|
||||||
|
border-color: #141414;
|
||||||
|
}
|
||||||
|
.bds-btn--black.bds-btn--secondary::before {
|
||||||
|
background-color: rgba(20, 20, 20, 0.15);
|
||||||
|
}
|
||||||
|
.bds-btn--black.bds-btn--secondary:hover:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: #141414;
|
||||||
|
border-color: #141414;
|
||||||
|
}
|
||||||
|
.bds-btn--black.bds-btn--secondary:focus-visible:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: #141414;
|
||||||
|
border: none;
|
||||||
|
outline: 2px solid #141414;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
.bds-btn--black.bds-btn--secondary:active:not(:disabled):not(.bds-btn--disabled) {
|
||||||
|
color: #141414;
|
||||||
|
border-color: #141414;
|
||||||
|
}
|
||||||
|
.bds-btn--black.bds-btn--secondary:disabled, .bds-btn--black.bds-btn--secondary.bds-btn--disabled {
|
||||||
|
color: #838386;
|
||||||
|
border-color: #A2A2A4;
|
||||||
|
}
|
||||||
|
|
||||||
/* TABLE STYLING */
|
/* TABLE STYLING */
|
||||||
article table {
|
article table {
|
||||||
clear: right;
|
clear: right;
|
||||||
|
|||||||
Reference in New Issue
Block a user