Skip to content

Commit

Permalink
fix(button): add onClick, handleClick, and new props
Browse files Browse the repository at this point in the history
  • Loading branch information
goodwinchris committed Dec 8, 2022
1 parent 4f60977 commit 9fee1c7
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 34 deletions.
32 changes: 28 additions & 4 deletions libs/core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,23 @@ export namespace Components {
* Displays icon before text when icon string matches an icon name
*/
"icon"?: string;
/**
* Provides button with a submittable name
*/
"name"?: string;
/**
* Provides button with a type todo: make sure there is info in the story
* @defaultValue button
*/
"type"?: 'button' | 'reset' | 'submit';
/**
* Provides button with a submittable value
*/
"value"?: string;
/**
* Sets button variant styles as outlined in Figma documentation
* @defaultValue primary
*/
"variant"?: 'primary' | 'secondary' | 'accent' | 'disclosure' | 'destructive';
"variant"?: 'secondary' | 'accent' | 'disclosure' | 'destructive';
}
interface SageLink {
/**
Expand Down Expand Up @@ -107,11 +119,23 @@ declare namespace LocalJSX {
* Displays icon before text when icon string matches an icon name
*/
"icon"?: string;
/**
* Provides button with a submittable name
*/
"name"?: string;
/**
* Provides button with a type todo: make sure there is info in the story
* @defaultValue button
*/
"type"?: 'button' | 'reset' | 'submit';
/**
* Provides button with a submittable value
*/
"value"?: string;
/**
* Sets button variant styles as outlined in Figma documentation
* @defaultValue primary
*/
"variant"?: 'primary' | 'secondary' | 'accent' | 'disclosure' | 'destructive';
"variant"?: 'secondary' | 'accent' | 'disclosure' | 'destructive';
}
interface SageLink {
/**
Expand Down
13 changes: 8 additions & 5 deletions libs/core/src/components/sage-button/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@

## Properties

| Property | Attribute | Description | Type | Default |
| ---------- | ---------- | --------------------------------------------------------------- | ----------------------------------------------------------------------- | ----------- |
| `disabled` | `disabled` | Toggles disabled state of button | `boolean` | `false` |
| `icon` | `icon` | Displays icon before text when icon string matches an icon name | `string` | `null` |
| `variant` | `variant` | Sets button variant styles as outlined in Figma documentation | `"accent" \| "destructive" \| "disclosure" \| "primary" \| "secondary"` | `'primary'` |
| Property | Attribute | Description | Type | Default |
| ---------- | ---------- | ----------------------------------------------------------------------- | ---------------------------------------------------------- | ----------- |
| `disabled` | `disabled` | Toggles disabled state of button | `boolean` | `false` |
| `icon` | `icon` | Displays icon before text when icon string matches an icon name | `string` | `null` |
| `name` | `name` | Provides button with a submittable name | `string` | `undefined` |
| `type` | `type` | Provides button with a type todo: make sure there is info in the story | `"button" \| "reset" \| "submit"` | `'button'` |
| `value` | `value` | Provides button with a submittable value | `string` | `undefined` |
| `variant` | `variant` | Sets button variant styles as outlined in Figma documentation | `"accent" \| "destructive" \| "disclosure" \| "secondary"` | `undefined` |


----------------------------------------------
Expand Down
56 changes: 50 additions & 6 deletions libs/core/src/components/sage-button/sage-button.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { Component, Host, h, Prop } from '@stencil/core';
import { Component, Element, Host, h, Prop } from '@stencil/core';
import { hasShadowDom } from '../../utils/utils';

@Component({
tag: 'sage-button',
styleUrl: 'sage-button.scss',
shadow: true,
})
export class SageButton {
@Element() el: HTMLSageButtonElement;

/**
* Sets button variant styles as outlined in Figma documentation
* @defaultValue primary
*/
@Prop() variant?: 'primary' | 'secondary' | 'accent' | 'disclosure' | 'destructive' = 'primary';
*/
@Prop() variant?: 'secondary' | 'accent' | 'disclosure' | 'destructive';

/**
* Displays icon before text when icon string matches an icon name
Expand All @@ -22,6 +24,48 @@ export class SageButton {
* @defaultValue false
*/
@Prop() disabled? = false;

/**
* Provides button with a submittable name
*/
@Prop() name?: string;

/**
* Provides button with a submittable value
*/
@Prop() value?: string;

/**
* Provides button with a type
* todo: make sure there is info in the story
* @defaultValue button
*/
@Prop() type?: 'button' | 'reset' | 'submit' = 'button';


// todo build out e2e test to confirm form submission
private handleClick = (ev: Event) => {
if (this.type === 'button') {
// If button clicked IS NOT associated with a form
if (hasShadowDom(this.el)) {
const form = this.el.closest('form')
if (form) {
ev.preventDefault()

const fakeButton = document.createElement('button')
fakeButton.type = this.type
fakeButton.style.display = 'none'
form.appendChild(fakeButton)
fakeButton.click()
fakeButton.remove()
}
}
} else {
// If button clicked IS associated with a form
}
}

private buttonClassNames = `sage-button` + (this.variant && ` sage-button--${this.variant}`);

render() {
const trashIcon = (
Expand All @@ -33,8 +77,8 @@ export class SageButton {
);

return (
<Host aria-disabled={this.disabled ? 'true' : null}>
<button class={`sage-button sage-button--${this.variant}`} disabled={this.disabled}>
<Host variant={this.variant} aria-disabled={this.disabled ? 'true' : null} onClick={this.handleClick}>
<button class={this.buttonClassNames} disabled={this.disabled} type={this.type} name={this.name} value={this.value} >
{this.icon == 'trashIcon' && trashIcon}
<slot />
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { extractArgTypes } from '@pxtrn/storybook-addon-docs-stencil';

<Meta title="Example/Atoms/sage-button" component="sage-button" argTypes={extractArgTypes('sage-button')} />

export const Template = (args) => html` <sage-button variant=${args.variant} icon=${args.icon} disabled=${args.disabled}>${args.slot}</sage-button> `;
export const Template = (args) =>
html` <sage-button value=${args.value} variant=${args.variant} name=${args.name} icon=${args.icon} disabled=${args.disabled} type=${args.type}> ${args.slot} </sage-button> `;

# sage-button

Expand All @@ -23,8 +24,10 @@ A button component to generate all versions of `sage-button` as outlined in [Fig
</td>
</tr>
<tr>
<td>To trigger on-page interactivity</td>
<td>To send a user to another URL</td>
<td>
To trigger on-page interactivity <br /> To submit a form
</td>
<td>To send a user to another URL or anchor</td>
</tr>
</table>

Expand All @@ -34,72 +37,74 @@ A button component to generate all versions of `sage-button` as outlined in [Fig

## Variant

### Primary
### Default (Primary)

<Canvas>
<Story name="Primary" args={{ variant: 'primary', icon: '', disabled: false, slot: 'Default' }}>
<Story name="Primary" args={{ icon: '', disabled: false, slot: 'Default', type: 'button' }}>
{Template.bind()}
</Story>
<Story name="PrimaryDisabled" args={{ variant: 'primary', icon: '', disabled: true, slot: 'Disabled' }}>
<Story name="PrimaryDisabled" args={{ icon: '', disabled: true, slot: 'Disabled', type: 'button' }}>
{Template.bind()}
</Story>
<Story name="PrimaryIcon" args={{ variant: 'primary', icon: 'trashIcon', disabled: false, slot: 'Icon' }}>
<Story name="PrimaryIcon" args={{ icon: 'trashIcon', disabled: false, slot: 'Icon', type: 'submit' }}>
{Template.bind()}
</Story>
</Canvas>

### Secondary

// Todo define variants

<Canvas>
<Story name="Secondary" args={{ variant: 'secondary', icon: '', disabled: false, slot: 'Default' }}>
<Story name="Secondary" args={{ variant: 'secondary', icon: '', disabled: false, slot: 'Default', type: 'button' }}>
{Template.bind()}
</Story>
<Story name="SecondaryDisabled" args={{ variant: 'secondary', icon: '', disabled: true, slot: 'Disabled' }}>
<Story name="SecondaryDisabled" args={{ variant: 'secondary', icon: '', disabled: true, slot: 'Disabled', type: 'button' }}>
{Template.bind()}
</Story>
<Story name="SecondaryIcon" args={{ variant: 'secondary', icon: 'trashIcon', disabled: false, slot: 'Icon' }}>
<Story name="SecondaryIcon" args={{ variant: 'secondary', icon: 'trashIcon', disabled: false, slot: 'Icon', type: 'button' }}>
{Template.bind()}
</Story>
</Canvas>

### Accent

<Canvas>
<Story name="Accent" args={{ variant: 'accent', icon: '', disabled: false, slot: 'Default' }}>
<Story name="Accent" args={{ variant: 'accent', icon: '', disabled: false, slot: 'Default', type: 'button' }}>
{Template.bind()}
</Story>
<Story name="AccentDisabled" args={{ variant: 'accent', icon: '', disabled: true, slot: 'Disabled' }}>
<Story name="AccentDisabled" args={{ variant: 'accent', icon: '', disabled: true, slot: 'Disabled', type: 'button' }}>
{Template.bind()}
</Story>
<Story name="AccentIcon" args={{ variant: 'accent', icon: 'trashIcon', disabled: false, slot: 'Icon' }}>
<Story name="AccentIcon" args={{ variant: 'accent', icon: 'trashIcon', disabled: false, slot: 'Icon', type: 'button' }}>
{Template.bind()}
</Story>
</Canvas>

### Disclosure

<Canvas>
<Story name="Disclosure" args={{ variant: 'disclosure', icon: '', disabled: false, slot: 'Default' }}>
<Story name="Disclosure" args={{ variant: 'disclosure', icon: '', disabled: false, slot: 'Default', type: 'button' }}>
{Template.bind()}
</Story>
<Story name="DisclosureDisabled" args={{ variant: 'disclosure', icon: '', disabled: true, slot: 'Disabled' }}>
<Story name="DisclosureDisabled" args={{ variant: 'disclosure', icon: '', disabled: true, slot: 'Disabled', type: 'button' }}>
{Template.bind()}
</Story>
<Story name="DisclosureIcon" args={{ variant: 'disclosure', icon: 'trashIcon', disabled: false, slot: 'Icon' }}>
<Story name="DisclosureIcon" args={{ variant: 'disclosure', icon: 'trashIcon', disabled: false, slot: 'Icon', type: 'button' }}>
{Template.bind()}
</Story>
</Canvas>

### Destructive

<Canvas>
<Story name="Destructive" args={{ variant: 'destructive', icon: '', disabled: false, slot: 'Default' }}>
<Story name="Destructive" args={{ variant: 'destructive', icon: '', disabled: false, slot: 'Default', type: 'button' }}>
{Template.bind()}
</Story>
<Story name="DestructiveDisabled" args={{ variant: 'destructive', icon: '', disabled: true, slot: 'Disabled' }}>
<Story name="DestructiveDisabled" args={{ variant: 'destructive', icon: '', disabled: true, slot: 'Disabled', type: 'button' }}>
{Template.bind()}
</Story>
<Story name="DestructiveIcon" args={{ variant: 'destructive', icon: 'trashIcon', disabled: false, slot: 'Icon' }}>
<Story name="DestructiveIcon" args={{ variant: 'destructive', icon: 'trashIcon', disabled: false, slot: 'Icon', type: 'button' }}>
{Template.bind()}
</Story>
</Canvas>
Expand Down
4 changes: 4 additions & 0 deletions libs/core/src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export function format(first: string, middle: string, last: string): string {
return (first || '') + (middle ? ` ${middle}` : '') + (last ? ` ${last}` : '');
}

export const hasShadowDom = (el: HTMLElement) => {
return !!el.shadowRoot && !!(el as any).attachShadow
}

0 comments on commit 9fee1c7

Please sign in to comment.