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 { 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 = {
|
||||
seo: {
|
||||
@@ -11,19 +11,11 @@ export const frontmatter = {
|
||||
|
||||
export default function ButtonShowcase() {
|
||||
const [clickCount, setClickCount] = React.useState(0);
|
||||
const [isLoading, setIsLoading] = React.useState(false);
|
||||
|
||||
const handleClick = () => {
|
||||
setClickCount((prev) => prev + 1);
|
||||
};
|
||||
|
||||
const handleAsyncClick = async () => {
|
||||
setIsLoading(true);
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
setIsLoading(false);
|
||||
setClickCount((prev) => prev + 1);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="landing">
|
||||
<section className="container-new py-26">
|
||||
@@ -96,16 +88,96 @@ export default function ButtonShowcase() {
|
||||
<Button variant="primary" onClick={handleClick} className="me-4 mb-4">
|
||||
Hover Me
|
||||
</Button>
|
||||
<Button variant="primary" onClick={handleClick} className="me-4 mb-4">
|
||||
<Button variant="primary" onClick={handleClick} className="mb-4">
|
||||
Focus Me (Tab)
|
||||
</Button>
|
||||
<Button variant="primary" onClick={handleClick} className="mb-4">
|
||||
Active State (Click)
|
||||
</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">
|
||||
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>
|
||||
</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="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 */}
|
||||
<section className="container-new py-26">
|
||||
<div className="d-flex flex-column-reverse">
|
||||
@@ -149,23 +221,6 @@ export default function ButtonShowcase() {
|
||||
</form>
|
||||
</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 */}
|
||||
<section className="container-new py-26">
|
||||
<div className="d-flex flex-column-reverse">
|
||||
@@ -252,11 +307,16 @@ export default function ButtonShowcase() {
|
||||
<pre style={{ margin: 0, overflow: 'auto' }}>
|
||||
<code>{`import { Button } from 'shared/components/Button';
|
||||
|
||||
// Basic usage
|
||||
// Basic usage (green theme - default)
|
||||
<Button variant="primary" onClick={handleClick}>
|
||||
Get Started
|
||||
</Button>
|
||||
|
||||
// Black color theme
|
||||
<Button variant="primary" color="black" onClick={handleClick}>
|
||||
Dark Button
|
||||
</Button>
|
||||
|
||||
// Disabled state
|
||||
<Button variant="primary" disabled>
|
||||
Submit
|
||||
@@ -305,49 +365,90 @@ export default function ButtonShowcase() {
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<div className="mt-10">
|
||||
<h5 className="mb-4">State Colors</h5>
|
||||
<table className="table" style={{ width: '100%' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>State</th>
|
||||
<th>Text Color</th>
|
||||
<th>Background Color</th>
|
||||
<th>Border</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Enabled</td>
|
||||
<td>#141414 (Neutral Black)</td>
|
||||
<td>#21E46B (Green 300)</td>
|
||||
<td>None</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hover</td>
|
||||
<td>#141414 (Neutral Black)</td>
|
||||
<td>#70EE97 (Green 200)</td>
|
||||
<td>None</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Focus</td>
|
||||
<td>#141414 (Neutral Black)</td>
|
||||
<td>#70EE97 (Green 200)</td>
|
||||
<td>2px solid #141414</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Active</td>
|
||||
<td>#141414 (Neutral Black)</td>
|
||||
<td>#21E46B (Green 300)</td>
|
||||
<td>None</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Disabled</td>
|
||||
<td>#838386 (Gray 500)</td>
|
||||
<td>#E0E0E1 (Gray 200)</td>
|
||||
<td>None</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<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 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' }}>#141414 (Neutral Black)</div>
|
||||
<div style={{ padding: '12px' }}>#21E46B (Green 300)</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' }}>#141414 (Neutral Black)</div>
|
||||
<div style={{ padding: '12px' }}>#70EE97 (Green 200)</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' }}>#141414 (Neutral Black)</div>
|
||||
<div style={{ padding: '12px' }}>#70EE97 (Green 200)</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' }}>#141414 (Neutral Black)</div>
|
||||
<div style={{ padding: '12px' }}>#21E46B (Green 300)</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 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>
|
||||
</section>
|
||||
</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 { 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 = {
|
||||
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
|
||||
//
|
||||
// Naming Convention: BEM with 'bds' namespace
|
||||
// .bds-btn - Base button
|
||||
// .bds-btn--primary - Primary variant modifier
|
||||
// .bds-btn--secondary - (Future) Secondary variant
|
||||
// .bds-btn - Base button (shared layout, typography, icon animation)
|
||||
// .bds-btn--primary - Primary variant (solid background)
|
||||
// .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__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--no-icon - No icon modifier
|
||||
|
||||
@import "../../../styles/colors";
|
||||
|
||||
@@ -16,27 +19,58 @@
|
||||
// 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-hover: $green-200; // #70EE97 - Hover/Focus
|
||||
$bds-btn-primary-text: #141414; // Neutral Black
|
||||
$bds-btn-primary-focus-border: #141414; // Black focus ring
|
||||
$bds-btn-primary-text: $bds-btn-neutral-black;
|
||||
$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-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
|
||||
$bds-btn-border-radius: 100px;
|
||||
$bds-btn-focus-border-width: 2px;
|
||||
|
||||
// Transitions
|
||||
// Motion: Duration 150ms, Custom bezier for smooth in-out feel
|
||||
$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
|
||||
// =============================================================================
|
||||
//
|
||||
// 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 {
|
||||
// Layout
|
||||
@@ -44,6 +78,7 @@ $bds-btn-transition-timing: ease-in-out;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
max-height: 40px;
|
||||
|
||||
// Typography - Label R token
|
||||
font-family: 'Booton', sans-serif;
|
||||
font-size: 16px;
|
||||
@@ -59,14 +94,55 @@ $bds-btn-transition-timing: ease-in-out;
|
||||
// Interaction
|
||||
cursor: pointer;
|
||||
|
||||
// Transitions
|
||||
transition-property: background-color, border-color, transform, padding, gap;
|
||||
transition-duration: $bds-btn-transition-duration;
|
||||
transition-timing-function: $bds-btn-transition-timing;
|
||||
// Required for pseudo-element background animation (shared)
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
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 {
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
// 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;
|
||||
color: currentColor;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
// Arrow horizontal line - shrinks on hover/focus
|
||||
@@ -104,12 +182,18 @@ $bds-btn-transition-timing: ease-in-out;
|
||||
// =============================================================================
|
||||
// Primary Variant
|
||||
// =============================================================================
|
||||
// HOVER ANIMATION: Background fills bottom-to-top (Green 300 → Green 200)
|
||||
|
||||
.bds-btn--primary {
|
||||
// Default/Enabled state colors
|
||||
color: $bds-btn-primary-text;
|
||||
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)
|
||||
padding: 8px 19px 8px 20px;
|
||||
gap: 16px;
|
||||
@@ -123,51 +207,44 @@ $bds-btn-transition-timing: ease-in-out;
|
||||
// Hover State (with icon)
|
||||
// ---------------------------------------------------------------------------
|
||||
&:hover:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||
background-color: $bds-btn-primary-bg-hover;
|
||||
// Adjust padding to compensate for icon gap change (maintains button width)
|
||||
// Background animation handled by shared ::before pseudo-element
|
||||
padding: 8px 13px 8px 20px;
|
||||
gap: 22px;
|
||||
}
|
||||
|
||||
// Hover State (no icon) - only change background, keep padding stable
|
||||
&:hover:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||
background-color: $bds-btn-primary-bg-hover;
|
||||
}
|
||||
// Hover State (no icon) - background animation only
|
||||
// (no padding/gap changes needed)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Focus State (keyboard navigation) - with icon
|
||||
// ---------------------------------------------------------------------------
|
||||
&:focus-visible:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||
background-color: $bds-btn-primary-bg-hover;
|
||||
border: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||
outline: none;
|
||||
// Compensate for 2px border on all sides
|
||||
padding: 6px 11px 6px 18px;
|
||||
outline: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||
outline-offset: 2px;
|
||||
padding: 8px 13px 8px 20px;
|
||||
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 {
|
||||
background-color: $bds-btn-primary-bg-hover;
|
||||
border: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||
outline: none;
|
||||
// Compensate for 2px border but keep symmetric padding
|
||||
padding: 6px 17px 6px 18px;
|
||||
outline: $bds-btn-focus-border-width solid $bds-btn-primary-focus-border;
|
||||
outline-offset: 2px;
|
||||
padding: 8px 20px;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Active State (being pressed)
|
||||
// ---------------------------------------------------------------------------
|
||||
&:active:not(:disabled):not(.bds-btn--disabled) {
|
||||
background-color: $bds-btn-primary-bg;
|
||||
transform: scale(0.98);
|
||||
// Maintains default padding and gap
|
||||
padding: 8px 19px 8px 20px;
|
||||
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 {
|
||||
@@ -176,8 +253,9 @@ $bds-btn-transition-timing: ease-in-out;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
|
||||
.bds-btn__icon {
|
||||
opacity: 0.5;
|
||||
// Disable background animation on disabled
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,20 +278,19 @@ $bds-btn-transition-timing: ease-in-out;
|
||||
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-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;
|
||||
}
|
||||
|
||||
// Focus state - smaller screens (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)
|
||||
@@ -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)
|
||||
// =============================================================================
|
||||
|
||||
// .bds-btn--secondary {
|
||||
// // Outline style: green stroke, transparent fill
|
||||
// // States: enabled, hover, focus, active, disabled
|
||||
// }
|
||||
|
||||
// .bds-btn--tertiary {
|
||||
// // Text-only style: green text, no border/fill
|
||||
// // States: enabled, hover (underline), focus, active, disabled
|
||||
|
||||
@@ -2,7 +2,9 @@ import React from 'react';
|
||||
|
||||
export interface ButtonProps {
|
||||
/** 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 */
|
||||
children: React.ReactNode;
|
||||
/** Click handler */
|
||||
@@ -59,13 +61,16 @@ const ArrowIcon: React.FC = () => (
|
||||
* BDS Button Component
|
||||
*
|
||||
* 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
|
||||
* <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> = ({
|
||||
variant = 'primary',
|
||||
color = 'green',
|
||||
children,
|
||||
onClick,
|
||||
disabled = false,
|
||||
@@ -73,12 +78,16 @@ export const Button: React.FC<ButtonProps> = ({
|
||||
className = '',
|
||||
showIcon = true,
|
||||
}) => {
|
||||
// Hide icon when disabled (per design spec)
|
||||
const shouldShowIcon = showIcon && !disabled;
|
||||
|
||||
// Build class names using BEM with bds namespace
|
||||
const classNames = [
|
||||
'bds-btn',
|
||||
`bds-btn--${variant}`,
|
||||
`bds-btn--${color}`,
|
||||
disabled ? 'bds-btn--disabled' : '',
|
||||
!showIcon ? 'bds-btn--no-icon' : '',
|
||||
!shouldShowIcon ? 'bds-btn--no-icon' : '',
|
||||
className,
|
||||
]
|
||||
.filter(Boolean)
|
||||
@@ -93,7 +102,7 @@ export const Button: React.FC<ButtonProps> = ({
|
||||
aria-disabled={disabled}
|
||||
>
|
||||
<span className="bds-btn__label">{children}</span>
|
||||
{showIcon && <ArrowIcon />}
|
||||
{shouldShowIcon && <ArrowIcon />}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -11159,29 +11159,52 @@ button[disabled=disabled] {
|
||||
border: none;
|
||||
border-radius: 100px;
|
||||
cursor: pointer;
|
||||
transition-property: background-color, border-color, transform, padding, gap;
|
||||
transition-duration: 150ms;
|
||||
transition-timing-function: ease-in-out;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
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 {
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.bds-btn__icon {
|
||||
width: 15px;
|
||||
height: 14px;
|
||||
flex-shrink: 0;
|
||||
transition: opacity 150ms ease-in-out;
|
||||
transition: opacity 150ms cubic-bezier(0.98, 0.12, 0.12, 0.98);
|
||||
color: currentColor;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.bds-btn__icon-line {
|
||||
transform-box: fill-box;
|
||||
transform-origin: right center;
|
||||
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 {
|
||||
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 {
|
||||
transform: scaleX(0);
|
||||
@@ -11190,6 +11213,11 @@ button[disabled=disabled] {
|
||||
.bds-btn--primary {
|
||||
color: #141414;
|
||||
background-color: #21E46B;
|
||||
}
|
||||
.bds-btn--primary::before {
|
||||
background-color: #70EE97;
|
||||
}
|
||||
.bds-btn--primary {
|
||||
padding: 8px 19px 8px 20px;
|
||||
gap: 16px;
|
||||
}
|
||||
@@ -11197,29 +11225,21 @@ button[disabled=disabled] {
|
||||
padding: 8px 20px;
|
||||
}
|
||||
.bds-btn--primary:hover:not(:disabled):not(.bds-btn--disabled):not(.bds-btn--no-icon) {
|
||||
background-color: #70EE97;
|
||||
padding: 8px 13px 8px 20px;
|
||||
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) {
|
||||
background-color: #70EE97;
|
||||
border: 2px solid #141414;
|
||||
outline: none;
|
||||
padding: 6px 11px 6px 18px;
|
||||
outline: 2px solid #141414;
|
||||
outline-offset: 2px;
|
||||
padding: 8px 13px 8px 20px;
|
||||
gap: 22px;
|
||||
}
|
||||
.bds-btn--primary:focus-visible:not(:disabled):not(.bds-btn--disabled).bds-btn--no-icon {
|
||||
background-color: #70EE97;
|
||||
border: 2px solid #141414;
|
||||
outline: none;
|
||||
padding: 6px 17px 6px 18px;
|
||||
outline: 2px solid #141414;
|
||||
outline-offset: 2px;
|
||||
padding: 8px 20px;
|
||||
}
|
||||
.bds-btn--primary:active:not(:disabled):not(.bds-btn--disabled) {
|
||||
background-color: #21E46B;
|
||||
transform: scale(0.98);
|
||||
padding: 8px 19px 8px 20px;
|
||||
gap: 16px;
|
||||
}
|
||||
@@ -11229,8 +11249,8 @@ button[disabled=disabled] {
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
.bds-btn--primary:disabled .bds-btn__icon, .bds-btn--primary.bds-btn--disabled .bds-btn__icon {
|
||||
opacity: 0.5;
|
||||
.bds-btn--primary:disabled::before, .bds-btn--primary.bds-btn--disabled::before {
|
||||
display: none;
|
||||
}
|
||||
@media (max-width: 1023px) {
|
||||
.bds-btn--primary {
|
||||
@@ -11244,15 +11264,16 @@ button[disabled=disabled] {
|
||||
padding: 8px 10px 8px 16px;
|
||||
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) {
|
||||
padding: 6px 8px 6px 14px;
|
||||
outline: 2px solid #141414;
|
||||
outline-offset: 2px;
|
||||
padding: 8px 10px 8px 16px;
|
||||
gap: 21px;
|
||||
}
|
||||
.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) {
|
||||
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 */
|
||||
article table {
|
||||
clear: right;
|
||||
|
||||
Reference in New Issue
Block a user