initial
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import { html } from '@design.estate/dees-element';
|
||||
import { injectCssVariables } from '../../00variables.js';
|
||||
|
||||
export const demoFunc = () => {
|
||||
injectCssVariables();
|
||||
return html`
|
||||
<style>
|
||||
.demo-section {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.demo-section h3 {
|
||||
margin: 0 0 1rem 0;
|
||||
font-size: 0.875rem;
|
||||
color: var(--dees-muted-foreground);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
.demo-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.75rem;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="demo-section">
|
||||
<h3>Variants</h3>
|
||||
<div class="demo-row">
|
||||
<dees-mobile-button variant="default">Default</dees-mobile-button>
|
||||
<dees-mobile-button variant="primary">Primary</dees-mobile-button>
|
||||
<dees-mobile-button variant="secondary">Secondary</dees-mobile-button>
|
||||
<dees-mobile-button variant="outline">Outline</dees-mobile-button>
|
||||
<dees-mobile-button variant="ghost">Ghost</dees-mobile-button>
|
||||
<dees-mobile-button variant="destructive">Destructive</dees-mobile-button>
|
||||
<dees-mobile-button variant="link">Link</dees-mobile-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="demo-section">
|
||||
<h3>Sizes</h3>
|
||||
<div class="demo-row">
|
||||
<dees-mobile-button size="sm">Small</dees-mobile-button>
|
||||
<dees-mobile-button size="md">Medium</dees-mobile-button>
|
||||
<dees-mobile-button size="lg">Large</dees-mobile-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="demo-section">
|
||||
<h3>States</h3>
|
||||
<div class="demo-row">
|
||||
<dees-mobile-button>Normal</dees-mobile-button>
|
||||
<dees-mobile-button disabled>Disabled</dees-mobile-button>
|
||||
<dees-mobile-button loading>Loading</dees-mobile-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="demo-section">
|
||||
<h3>Icon Buttons</h3>
|
||||
<div class="demo-row">
|
||||
<dees-mobile-button icon size="sm">
|
||||
<dees-mobile-icon icon="plus" size="16"></dees-mobile-icon>
|
||||
</dees-mobile-button>
|
||||
<dees-mobile-button icon>
|
||||
<dees-mobile-icon icon="settings" size="18"></dees-mobile-icon>
|
||||
</dees-mobile-button>
|
||||
<dees-mobile-button icon size="lg">
|
||||
<dees-mobile-icon icon="menu" size="20"></dees-mobile-icon>
|
||||
</dees-mobile-button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
@@ -0,0 +1,224 @@
|
||||
import {
|
||||
DeesElement,
|
||||
css,
|
||||
cssManager,
|
||||
customElement,
|
||||
html,
|
||||
property,
|
||||
type TemplateResult,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import { mobileComponentStyles } from '../../00componentstyles.js';
|
||||
import { demoFunc } from './dees-mobile-button.demo.js';
|
||||
|
||||
export type ButtonVariant = 'default' | 'primary' | 'secondary' | 'outline' | 'ghost' | 'destructive' | 'link';
|
||||
export type ButtonSize = 'sm' | 'md' | 'lg';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'dees-mobile-button': DeesMobileButton;
|
||||
}
|
||||
}
|
||||
|
||||
@customElement('dees-mobile-button')
|
||||
export class DeesMobileButton extends DeesElement {
|
||||
public static demo = demoFunc;
|
||||
|
||||
@property({ type: String })
|
||||
accessor variant: ButtonVariant = 'default';
|
||||
|
||||
@property({ type: String })
|
||||
accessor size: ButtonSize = 'md';
|
||||
|
||||
@property({ type: Boolean })
|
||||
accessor disabled: boolean = false;
|
||||
|
||||
@property({ type: Boolean })
|
||||
accessor loading: boolean = false;
|
||||
|
||||
@property({ type: Boolean, reflect: true })
|
||||
accessor icon: boolean = false;
|
||||
|
||||
@property({ type: String })
|
||||
accessor type: 'button' | 'submit' | 'reset' = 'button';
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
mobileComponentStyles,
|
||||
css`
|
||||
:host {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
border-radius: calc(var(--dees-radius, 0.5rem) - 2px);
|
||||
cursor: pointer;
|
||||
transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
outline: none;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button:focus-visible {
|
||||
outline: 2px solid var(--dees-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
button:active:not(:disabled) {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Sizes */
|
||||
button.sm {
|
||||
height: 2rem;
|
||||
padding: 0 0.75rem;
|
||||
font-size: 0.75rem;
|
||||
border-radius: calc(var(--dees-radius, 0.5rem) - 4px);
|
||||
}
|
||||
|
||||
button.md {
|
||||
height: 2.25rem;
|
||||
padding: 0 1rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
button.lg {
|
||||
height: 2.75rem;
|
||||
padding: 0 2rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* Variants - using bdTheme for bright/dark support */
|
||||
button.default,
|
||||
button.primary {
|
||||
background: #3b82f6;
|
||||
color: #ffffff;
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
button.default:not(:disabled):hover,
|
||||
button.primary:not(:disabled):hover {
|
||||
background: #2563eb;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
button.secondary {
|
||||
background: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
|
||||
color: ${cssManager.bdTheme('#18181b', '#fafafa')};
|
||||
}
|
||||
|
||||
button.secondary:not(:disabled):hover {
|
||||
background: ${cssManager.bdTheme('#e4e4e7', '#3f3f46')};
|
||||
}
|
||||
|
||||
button.outline {
|
||||
background: transparent;
|
||||
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
|
||||
border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#3f3f46')};
|
||||
}
|
||||
|
||||
button.outline:not(:disabled):hover {
|
||||
background: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
|
||||
border-color: ${cssManager.bdTheme('#d4d4d8', '#52525b')};
|
||||
}
|
||||
|
||||
button.ghost {
|
||||
background-color: transparent;
|
||||
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
|
||||
}
|
||||
|
||||
button.ghost:not(:disabled):hover {
|
||||
background: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
|
||||
}
|
||||
|
||||
button.destructive {
|
||||
background: #dc2626;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
button.destructive:not(:disabled):hover {
|
||||
background: #b91c1c;
|
||||
}
|
||||
|
||||
button.link {
|
||||
background: transparent;
|
||||
color: #3b82f6;
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 4px;
|
||||
padding: 0;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
button.link:not(:disabled):hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Loading state */
|
||||
.spinner {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border: 2px solid transparent;
|
||||
border-top-color: currentColor;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.8s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Icon-only button */
|
||||
:host([icon]) button {
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:host([icon]) button.sm {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
:host([icon]) button.lg {
|
||||
width: 2.75rem;
|
||||
height: 2.75rem;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
private handleClick(e: MouseEvent) {
|
||||
if (this.disabled || this.loading) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public render(): TemplateResult {
|
||||
return html`
|
||||
<button
|
||||
type=${this.type}
|
||||
class=${`${this.variant} ${this.size}`}
|
||||
?disabled=${this.disabled || this.loading}
|
||||
@click=${this.handleClick}
|
||||
>
|
||||
${this.loading ? html`<span class="spinner"></span>` : ''}
|
||||
<slot></slot>
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
}
|
||||
1
ts_web/elements/00group-ui/dees-mobile-button/index.ts
Normal file
1
ts_web/elements/00group-ui/dees-mobile-button/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './dees-mobile-button.js';
|
||||
Reference in New Issue
Block a user