Skip to content

Commit

Permalink
Refactors Svelte Buttons to no longer use label, isIconLeft, isIconRi…
Browse files Browse the repository at this point in the history
…ght and just renders the entire slot and lets the consumer decide what they want there
  • Loading branch information
roblevintennis committed Sep 18, 2020
1 parent 12edfa1 commit c18eb72
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 188 deletions.
216 changes: 91 additions & 125 deletions agnosticui-svelte/src/__snapshots__/Storyshots.test.js.snap

Large diffs are not rendered by default.

30 changes: 3 additions & 27 deletions agnosticui-svelte/src/stories/Button.stories.js
@@ -1,10 +1,10 @@
import Button from './Button.svelte';
import ButtonSlot from './ButtonSlot.svelte';

export default {
title: 'Button',
component: Button,
component: ButtonSlot,
argTypes: {
label: { control: 'text' },
mode: { control: 'text' },
css: { control: 'text' },
isBordered: { control: 'boolean' },
Expand All @@ -21,7 +21,7 @@ export default {
};

const Template = ({ onClick, ...args }) => ({
Component: Button,
Component: ButtonSlot,
props: args,
on: {
click: onClick,
Expand All @@ -30,35 +30,30 @@ const Template = ({ onClick, ...args }) => ({

export const Primary = Template.bind({});
Primary.args = {
label: 'Button',
mode: 'primary',
};

export const PrimaryBordered = Template.bind({});
PrimaryBordered.args = {
label: 'Primary Bordered',
mode: 'primary',
isBordered: true,
};

export const PrimaryRounded = Template.bind({});
PrimaryRounded.args = {
label: 'Primary Rounded',
mode: 'primary',
isRounded: true,
};

export const PrimaryRoundedRaised = Template.bind({});
PrimaryRoundedRaised.args = {
label: 'Primary Rounded',
mode: 'primary',
isRounded: true,
isRaised: true,
};

export const PrimaryBorderedRounded = Template.bind({});
PrimaryBorderedRounded.args = {
label: 'Primary Borded Rounded',
mode: 'primary',
isBordered: true,
isRounded: true,
Expand All @@ -67,120 +62,101 @@ PrimaryBorderedRounded.args = {
export const PrimaryBlock = Template.bind({});
PrimaryBlock.args = {
mode: 'primary',
label: 'Block (aka Stacked)',
isBlock: true,
};

export const Secondary = Template.bind({});
Secondary.args = {
label: 'Secondary',
mode: 'secondary',
};

export const SecondaryBordered = Template.bind({});
SecondaryBordered.args = {
label: 'Secondary Bordered',
mode: 'secondary',
isBordered: true,
};

export const SecondaryRounded = Template.bind({});
SecondaryRounded.args = {
label: 'Secondary Rounded',
mode: 'secondary',
isRounded: true,
};

export const SecondaryRoundedRaised = Template.bind({});
SecondaryRoundedRaised.args = {
label: 'Secondary Rounded',
mode: 'secondary',
isRounded: true,
isRaised: true,
};

export const SecondaryBorderedRounded = Template.bind({});
SecondaryBorderedRounded.args = {
label: 'Secondary Borded Rounded',
mode: 'secondary',
isBordered: true,
isRounded: true,
};

export const Default = Template.bind({});
Default.args = {
label: 'Default',
};

export const DefaultRaised = Template.bind({});
DefaultRaised.args = {
label: 'Default Raised',
isRaised: true,
};

export const DefaultBordered = Template.bind({});
DefaultBordered.args = {
label: 'Default Bordered',
isBordered: true,
};

export const DefaultRounded = Template.bind({});
DefaultRounded.args = {
label: 'Default Rounded',
isRounded: true,
};

export const DefaultBorderedRounded = Template.bind({});
DefaultBorderedRounded.args = {
label: 'Default Bordered Rounded',
isBordered: true,
isRounded: true,
};

export const Disabled = Template.bind({});
Disabled.args = {
label: 'Disabled',
isDisabled: true,
};

export const Large = Template.bind({});
Large.args = {
size: 'large',
label: 'Large',
};

export const Small = Template.bind({});
Small.args = {
size: 'small',
label: 'Small',
};

export const ButtonTypeSubmit = Template.bind({});
ButtonTypeSubmit.args = {
label: 'Button Type Attribute Set To Submit',
type: 'submit',
};

export const ButtonTypeReset = Template.bind({});
ButtonTypeReset.args = {
label: 'Button Type Attribute Set To Reset',
type: 'reset',
};

export const ButtonOverrides = Template.bind({});
ButtonOverrides.args = {
label: 'Custom CSS Override',
css: 'my-custom-css-klass',
};

export const ButtonBlank = Template.bind({});
ButtonBlank.args = {
label: 'Cancel',
isBlank: true,
};

export const ButtonBase = Template.bind({});
ButtonBase.args = {
label: 'Button Base Only (no skin)',
isSkinned: false,
};
18 changes: 3 additions & 15 deletions agnosticui-svelte/src/stories/Button.svelte
@@ -1,7 +1,6 @@
<script>
import { createEventDispatcher } from "svelte";
export let mode = "";
export let label = "";
export let size = "";
export let isBordered = false;
export let isBlock = false;
Expand All @@ -10,8 +9,6 @@
export let isRaised = false;
export let isRounded = false;
export let isSkinned = true;
export let isIconLeft = false;
export let isIconRight = false;
/**
* This prop is an escape hatch for global CSS overrides. Likely, the most useful reason to
* leverage this is to add custom responsive media query code. Note that you'll likely need
Expand Down Expand Up @@ -41,12 +38,10 @@
isRounded ? "btn-rounded" : "",
isDisabled ? "disabled" : "",
isRaised ? "btn-raised" : "",
isIconLeft ? "btn-icon-left" : "",
isIconRight ? "btn-icon-right" : "",
isBlank ? "btn-blank" : "",
css ? `${css}` : ""
css ? `${css}` : "",
];
klasses = klasses.filter(klass => klass.length);
klasses = klasses.filter((klass) => klass.length);
klasses = klasses.join(" ");
export let onClick = null;
Expand Down Expand Up @@ -604,12 +599,5 @@ to leak through. So we leverage that so we don't have to do fancy regex when cop
</style>

<button {type} class={klasses} on:click={handleClick}>
<!-- TODO -- these should really better use named slots so we can remove the isIconLeft/isIconRight boolean variables -->
{#if isIconLeft}
<slot />
{/if}
{label}
{#if isIconRight}
<slot />
{/if}
<slot />
</button>
19 changes: 17 additions & 2 deletions agnosticui-svelte/src/stories/Button.test.js
@@ -1,14 +1,29 @@
import '@testing-library/jest-dom/extend-expect'
import { render, fireEvent } from '@testing-library/svelte'
import SlotTest from "./SlotTest.svelte";
import Button from './Button.svelte'

// https://svelte-recipes.netlify.app/testing/#testing-slots
test("it should render slotted content", () => {
const { getByTestId, getByText } = render(SlotTest, {
props: { Component: Button },
});
const slotz = getByTestId("slot");
expect(slotz.innerHTML).toBe("Go");
const button = getByText('Go')
expect(button.innerHTML).toBe("Go");
});

test('onClick fires', async () => {
let state = 'original'
const clickHandler = () => {
state = 'click event fired'
}
const { getByText } = render(Button, { onClick: clickHandler, label: 'Go' })
const button = getByText('Go')

const { getByRole } = render(Button, {
onClick: clickHandler,
})
const button = getByRole("button");

// Note that using await when firing events unique to svelte--have to
// wait for next `tick` so Svelte flushes all pending state changes.
Expand Down
30 changes: 15 additions & 15 deletions agnosticui-svelte/src/stories/ButtonGroupTests.svelte
Expand Up @@ -4,32 +4,32 @@
</script>

<ButtonGroup>
<Button label="one" />
<Button label="two" />
<Button label="three" />
<Button>One</Button>
<Button>Two</Button>
<Button>Three</Button>
</ButtonGroup>

<ButtonGroup>
<Button label="one" mode="primary" />
<Button label="two" mode="primary" />
<Button label="three" mode="primary" />
<Button mode="primary">One</Button>
<Button mode="primary">Two</Button>
<Button mode="primary">Three</Button>
</ButtonGroup>

<ButtonGroup>
<Button label="one" mode="secondary" />
<Button label="two" mode="secondary" />
<Button label="three" mode="secondary" />
<Button mode="secondary">One</Button>
<Button mode="secondary">Two</Button>
<Button mode="secondary">Three</Button>
</ButtonGroup>

<div style="margin-bottom: 40px;" />
<ButtonGroup>
<Button label="one" mode="primary" isBordered />
<Button label="two" mode="primary" isBordered />
<Button label="three" mode="primary" isBordered />
<Button mode="primary" isBordered>One</Button>
<Button mode="primary" isBordered>Two</Button>
<Button mode="primary" isBordered>Three</Button>
</ButtonGroup>

<ButtonGroup>
<Button label="one" mode="secondary" isBordered />
<Button label="two" mode="secondary" isBordered />
<Button label="three" mode="secondary" isBordered />
<Button mode="secondary" isBordered>One</Button>
<Button mode="secondary" isBordered>Two</Button>
<Button mode="secondary" isBordered>Three</Button>
</ButtonGroup>
10 changes: 8 additions & 2 deletions agnosticui-svelte/src/stories/ButtonIconLeft.svelte
Expand Up @@ -2,8 +2,14 @@
import Button from "./Button.svelte";
</script>

<Button label="Download" isRounded={true} mode="primary" isIconLeft={true}>
<svg
<style>
svg {
margin-left: 8px;
}
</style>

<Button isRounded={true} mode="primary" isIconLeft={true}>
Download <svg
class="btn-icon"
viewBox="0 0 16 16"
version="1.1"
Expand Down
10 changes: 8 additions & 2 deletions agnosticui-svelte/src/stories/ButtonIconRight.svelte
Expand Up @@ -2,7 +2,13 @@
import Button from "./Button.svelte";
</script>

<Button label="Call" isRounded={true} mode="primary" isIconRight={true}>
<style>
svg {
margin-right: 8px;
}
</style>

<Button isRounded={true} mode="primary" isIconRight={true}>
<!-- NOTE -- no class="btn-icon" on this SVG? This is to prove we support either .btn-icon or svg element.
The background is if we want to use <i class="fa fa-type btn-icon"> it will still work even though not an SVG. -->
<svg
Expand All @@ -20,5 +26,5 @@
1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39
0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57
3.57.11.35.03.74-.25 1.02l-2.2 2.2z" />
</svg>
</svg> Call
</Button>
38 changes: 38 additions & 0 deletions agnosticui-svelte/src/stories/ButtonSlot.svelte
@@ -0,0 +1,38 @@
<script>
// https://github.com/storybookjs/storybook/issues/8443
import Button from "./Button.svelte";
// Unfortunately, these have to be duplicated from Button :(
export let mode = "";
export let size = "";
export let isBordered = false;
export let isBlock = false;
export let isBlank = false;
export let isDisabled = false;
export let isRaised = false;
export let isRounded = false;
export let isSkinned = true;
export let css = "";
export let type = "button";
</script>

<style>
span {
margin: 0;
padding: 0;
}
</style>

<Button
{mode}
{size}
{isBordered}
{isBlock}
{isBlank}
{isDisabled}
{isRaised}
{isRounded}
{isSkinned}
{css}
{type}>
<span>Go</span>
</Button>
7 changes: 7 additions & 0 deletions agnosticui-svelte/src/stories/SlotTest.svelte
@@ -0,0 +1,7 @@
<script>
export let Component;
</script>

<svelte:component this={Component}>
<h1 data-testid="slot">Go</h1>
</svelte:component>

0 comments on commit c18eb72

Please sign in to comment.