Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions apps/demo/src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@
flex-wrap: wrap;
}

&__button-grid {
display: grid;
grid-template-columns: repeat(4, minmax(140px, max-content));
gap: 1rem;
align-items: center;
}

&__switches,
&__checkboxes {
display: flex;
Expand Down Expand Up @@ -87,4 +94,43 @@
margin: 0;
}
}

&__select-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 2rem;
}

&__select-column {
display: flex;
flex-direction: column;
gap: 1rem;
}

&__select-item {
max-width: 220px;
}
}

.is-demo-hover.mdk-button--variant-primary {
background: linear-gradient(
0deg,
var(--mdk-button-primary-bg-hover-overlay) 0%,
var(--mdk-button-primary-bg-hover-overlay) 100%
),
var(--mdk-button-primary-bg);
color: var(--mdk-button-primary-text-hover);
}

.is-demo-hover.mdk-button--variant-secondary {
border-color: var(--mdk-button-secondary-border-hover);
}

.is-demo-hover.mdk-button--variant-danger {
opacity: 0.9;
}

.is-demo-hover.mdk-button--variant-outline {
background: hsl(var(--accent));
color: hsl(var(--accent-foreground));
}
116 changes: 104 additions & 12 deletions apps/demo/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,36 @@ import {
DialogHeader,
DialogTitle,
DialogTrigger,
Dropdown,
Label,
Select,
Switch,
} from '@mining-sdk/core'

import './App.scss'

function App(): JSX.Element {
const selectOptions = [
{ value: 'item-1', label: 'Item 1' },
{ value: 'item-2', label: 'Item 2' },
{ value: 'item-3', label: 'Item 3' },
{ value: 'item-4', label: 'Item 4' },
]

const dropdownItems = [
{
key: 'group-1',
type: 'group' as const,
label: 'Items',
children: [
{ key: 'item-1', label: 'Item 1' },
{ key: 'item-2', label: 'Item 2' },
{ key: 'item-3', label: 'Item 3' },
{ key: 'item-4', label: 'Item 4' },
],
},
]

return (
<div className="demo-app">
<h1 className="demo-app__title">@mining-sdk/core Component Demo</h1>
Expand All @@ -39,18 +62,87 @@ function App(): JSX.Element {
{/* Buttons */}
<section className="demo-section">
<h2 className="demo-section__title">Buttons</h2>
<div className="demo-section__buttons">
<Button variant="default">Default</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="outline">Outline</Button>
<div className="demo-section__button-grid">
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
<Button variant="danger">Danger</Button>
<Button variant="outline">Outline</Button>

<Button variant="primary" disabled>
Primary
</Button>
<Button variant="secondary" disabled>
Secondary
</Button>
<Button variant="danger" disabled>
Danger
</Button>
<Button variant="outline" disabled>
Outline
</Button>

<Button className="is-demo-hover" variant="primary">
Primary
</Button>
<Button className="is-demo-hover" variant="secondary">
Secondary
</Button>
<Button className="is-demo-hover" variant="danger">
Danger
</Button>
<Button className="is-demo-hover" variant="outline">
Outline
</Button>
</div>
<div className="demo-section__button-sizes">
<Button size="sm">Small</Button>
<Button size="default">Default</Button>
<Button size="lg">Large</Button>
</section>

{/* Select & Dropdown */}
<section className="demo-section">
<h2 className="demo-section__title">Select & Dropdown</h2>
<div className="demo-section__select-grid">
<div className="demo-section__select-column">
<h3>States</h3>
<div className="demo-section__select-item">
<Select placeholder="Dropdown" options={selectOptions} />
</div>
<div className="demo-section__select-item">
<Select placeholder="Dropdown" options={selectOptions} disabled />
</div>
<div className="demo-section__select-item">
<Select placeholder="Dropdown" options={selectOptions} value="item-4" />
</div>
</div>

<div className="demo-section__select-column">
<h3>Tags</h3>
<div className="demo-section__select-item">
<Select
mode="tags"
placeholder="Search"
tokenSeparators={[',']}
options={selectOptions}
value={['item-1', 'item-3']}
/>
</div>
<div className="demo-section__select-item">
<Select
mode="tags"
placeholder="Add tags"
tokenSeparators={[',']}
options={selectOptions}
/>
</div>
</div>

<div className="demo-section__select-column">
<h3>Dropdown</h3>
<Dropdown menu={{ items: dropdownItems }} placement="bottomLeft">
<Button variant="secondary">Dropdown</Button>
</Dropdown>
<Dropdown menu={{ items: dropdownItems }} placement="bottomLeft" open>
<Button variant="secondary">Dropdown (Open)</Button>
</Dropdown>
</div>
</div>
</section>

Expand All @@ -73,7 +165,7 @@ function App(): JSX.Element {
</div>
<DialogFooter>
<Button variant="outline">Cancel</Button>
<Button>Save changes</Button>
<Button variant="primary">Save changes</Button>
</DialogFooter>
</DialogContent>
</Dialog>
Expand All @@ -84,7 +176,7 @@ function App(): JSX.Element {
<h2 className="demo-section__title">Alert Dialog</h2>
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="destructive">Delete Account</Button>
<Button variant="danger">Delete Account</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
Expand Down
8 changes: 4 additions & 4 deletions packages/core/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,16 @@ function MyComponent() {
import { Button } from '@mining-sdk/core'

// Variants
<Button variant="default">Default</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="primary">Primary</Button>
<Button variant="danger">Danger</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>

// Sizes
<Button size="sm">Small</Button>
<Button size="default">Default</Button>
<Button size="md">Default</Button>
<Button size="lg">Large</Button>
<Button size="icon">🔥</Button>
```
Expand Down Expand Up @@ -169,7 +169,7 @@ function AlertDialogDemo() {
return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="destructive">Delete</Button>
<Button variant="danger">Delete</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
Expand Down
89 changes: 81 additions & 8 deletions packages/core/src/components/button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,102 @@ import * as React from 'react'

import { cn } from '../../utils'

export type ButtonVariant = 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'
export type ButtonSize = 'default' | 'sm' | 'lg' | 'icon'

export type ButtonVariant = 'primary' | 'secondary' | 'danger' | 'outline' | 'ghost' | 'link'
export type ButtonSize = 'sm' | 'md' | 'lg' | 'icon'
export type ButtonIconPosition = 'left' | 'right'
export type ButtonAntdSize = 'small' | 'middle' | 'large'
export type ButtonProps = {
variant?: ButtonVariant
size?: ButtonSize
size?: ButtonSize | ButtonAntdSize
loading?: boolean
icon?: React.ReactNode
iconPosition?: ButtonIconPosition
fullWidth?: boolean
block?: boolean
} & React.ButtonHTMLAttributes<HTMLButtonElement>

const sizeMap: Record<ButtonSize | ButtonAntdSize, ButtonSize> = {
sm: 'sm',
small: 'sm',
md: 'md',
middle: 'md',
lg: 'lg',
large: 'lg',
icon: 'icon',
}

function sizeToSize(size?: ButtonSize | ButtonAntdSize): ButtonSize {
return size ? sizeMap[size] : 'md'
}

/**
* Button component with multiple variants and sizes
*
* @example
* ```tsx
* <Button variant="default" size="lg">Click me</Button>
* <Button variant="primary" size="lg">Click me</Button>
* <Button variant="outline">Outlined</Button>
* <Button variant="ghost" size="sm">Small Ghost</Button>
* ```
*/
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant = 'default', size = 'default', ...props }, ref) => {
const classes = cn('mdk-button', `mdk-button--${variant}`, `mdk-button--${size}`, className)
(
{
className,
variant,
size = 'md',
loading,
icon,
iconPosition = 'left',
fullWidth,
block,
disabled,
type: nativeType,
children,
...props
},
ref,
) => {
const resolvedVariant = variant ?? 'secondary'
const resolvedSize = sizeToSize(size)
const resolvedHtmlType = nativeType ?? 'button'
const isIconOnly = Boolean(icon) && !children

const classes = cn(
'mdk-button',
`mdk-button--variant-${resolvedVariant}`,
`mdk-button--size-${resolvedSize}`,
{
'mdk-button--full-width': fullWidth || block,
'mdk-button--loading': loading,
'mdk-button--icon-only': isIconOnly,
},
className,
)

return <button className={classes} ref={ref} {...props} />
return (
<button
className={classes}
ref={ref}
type={resolvedHtmlType}
aria-busy={loading || undefined}
disabled={disabled || loading}
{...props}
>
{loading && <span className="mdk-button__spinner" aria-hidden="true" />}
{icon && iconPosition === 'left' && (
<span className="mdk-button__icon" aria-hidden="true">
{icon}
</span>
)}
{children && <span className="mdk-button__label">{children}</span>}
{icon && iconPosition === 'right' && (
<span className="mdk-button__icon" aria-hidden="true">
{icon}
</span>
)}
</button>
)
},
)
Button.displayName = 'Button'
Expand Down
Loading