mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-09-11 12:25:42 +03:00
redo buttons component
This commit is contained in:
parent
7f9d53822d
commit
de015d2f8c
@ -1,112 +1,139 @@
|
||||
<script lang="ts">
|
||||
import { Meta, Story } from '@storybook/addon-svelte-csf';
|
||||
import { IconHome } from '../icons';
|
||||
|
||||
import Button from './Button.svelte';
|
||||
|
||||
let count = 0;
|
||||
const heights = ['basic', 'small'] as const;
|
||||
const widths = ['basic', 'long'] as const;
|
||||
</script>
|
||||
|
||||
<Meta title="GitButler/Button" component={Button} />
|
||||
|
||||
<Story name="Basic">
|
||||
<Button on:click={() => count++}>
|
||||
You clicked: {count}
|
||||
</Button>
|
||||
<Story name="Basic Button">
|
||||
<div class="flex gap-6">
|
||||
{#each widths as width}
|
||||
{#each heights as height}
|
||||
<div class="flex flex-col gap-2">
|
||||
{#each [true, false] as filled}
|
||||
<div class="flex gap-2">
|
||||
{#each [false, true] as disabled}
|
||||
<Button role="basic" {filled} {disabled} {height} {width}>Label</Button>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
<Story name="Basic With Icon">
|
||||
<Button on:click={() => count++}>
|
||||
<svelte:fragment slot="icon">
|
||||
<IconHome />
|
||||
</svelte:fragment>
|
||||
You clicked: {count}
|
||||
</Button>
|
||||
<Story name="Primary Button">
|
||||
<div class="flex gap-6">
|
||||
{#each widths as width}
|
||||
{#each heights as height}
|
||||
<div class="flex flex-col gap-2">
|
||||
{#each [true, false] as filled}
|
||||
<div class="flex gap-2">
|
||||
{#each [false, true] as disabled}
|
||||
<Button role="primary" {filled} {disabled} {height} {width}>Label</Button>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
<Story name="Small With Icon">
|
||||
<Button on:click={() => count++} small>
|
||||
<svelte:fragment slot="icon">
|
||||
<IconHome />
|
||||
</svelte:fragment>
|
||||
You clicked: {count}
|
||||
</Button>
|
||||
<Story name="Destructive Button">
|
||||
<div class="flex gap-6">
|
||||
{#each widths as width}
|
||||
{#each heights as height}
|
||||
<div class="flex flex-col gap-2">
|
||||
{#each [true, false] as filled}
|
||||
<div class="flex gap-2">
|
||||
{#each [false, true] as disabled}
|
||||
<Button role="destructive" {filled} {disabled} {height} {width}>Label</Button>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
<Story name="Outlined icon">
|
||||
<Button on:click={() => count++} outlined>
|
||||
<svelte:fragment slot="icon">
|
||||
<IconHome />
|
||||
</svelte:fragment>
|
||||
</Button>
|
||||
<Story name="Basic Link">
|
||||
<div class="flex gap-6">
|
||||
{#each widths as width}
|
||||
{#each heights as height}
|
||||
<div class="flex flex-col gap-2">
|
||||
{#each [true, false] as filled}
|
||||
<div class="flex gap-2">
|
||||
{#each [false, true] as disabled}
|
||||
<Button
|
||||
href="https://gitbutler.com"
|
||||
role="basic"
|
||||
{filled}
|
||||
{disabled}
|
||||
{height}
|
||||
{width}>Label</Button
|
||||
>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
<Story name="Wide With Icon">
|
||||
<Button on:click={() => count++} wide>
|
||||
<svelte:fragment slot="icon">
|
||||
<IconHome />
|
||||
</svelte:fragment>
|
||||
You clicked: {count}
|
||||
</Button>
|
||||
<Story name="Primary Link">
|
||||
<div class="flex gap-6">
|
||||
{#each widths as width}
|
||||
{#each heights as height}
|
||||
<div class="flex flex-col gap-2">
|
||||
{#each [true, false] as filled}
|
||||
<div class="flex gap-2">
|
||||
{#each [false, true] as disabled}
|
||||
<Button
|
||||
href="https://gitbutler.com"
|
||||
role="primary"
|
||||
{filled}
|
||||
{disabled}
|
||||
{height}
|
||||
{width}>Label</Button
|
||||
>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
<Story name="Basic Outlined">
|
||||
<Button on:click={() => count++} outlined>
|
||||
You clicked: {count}
|
||||
</Button>
|
||||
</Story>
|
||||
|
||||
<Story name="Basic Small">
|
||||
<Button on:click={() => count++} small>
|
||||
You clicked: {count}
|
||||
</Button>
|
||||
</Story>
|
||||
|
||||
<Story name="Basic Outlined Small">
|
||||
<Button on:click={() => count++} small outlined>
|
||||
You clicked: {count}
|
||||
</Button>
|
||||
</Story>
|
||||
|
||||
<Story name="Primary">
|
||||
<Button on:click={() => count++} primary>
|
||||
You clicked: {count}
|
||||
</Button>
|
||||
</Story>
|
||||
|
||||
<Story name="Primary Small">
|
||||
<Button on:click={() => count++} primary small>
|
||||
You clicked: {count}
|
||||
</Button>
|
||||
</Story>
|
||||
|
||||
<Story name="Primary Wide">
|
||||
<Button on:click={() => count++} primary wide>
|
||||
You clicked: {count}
|
||||
</Button>
|
||||
</Story>
|
||||
|
||||
<Story name="Primary Small Wide">
|
||||
<Button on:click={() => count++} primary wide small>
|
||||
You clicked: {count}
|
||||
</Button>
|
||||
</Story>
|
||||
|
||||
<Story name="Primary Outlined Small">
|
||||
<Button on:click={() => count++} primary outlined small>
|
||||
You clicked: {count}
|
||||
</Button>
|
||||
</Story>
|
||||
|
||||
<Story name="Link">
|
||||
<Button href="https://gitbutler.com">Go to https://gitbutler.com</Button>
|
||||
</Story>
|
||||
|
||||
<Story name="Link with icon">
|
||||
<Button href="https://gitbutler.com">
|
||||
<svelte:fragment slot="icon">
|
||||
<IconHome />
|
||||
</svelte:fragment>
|
||||
Go to https://gitbutler.com
|
||||
</Button>
|
||||
<Story name="Destructive Link">
|
||||
<div class="flex gap-6">
|
||||
{#each widths as width}
|
||||
{#each heights as height}
|
||||
<div class="flex flex-col gap-2">
|
||||
{#each [true, false] as filled}
|
||||
<div class="flex gap-2">
|
||||
{#each [false, true] as disabled}
|
||||
<Button
|
||||
href="https://gitbutler.com"
|
||||
role="destructive"
|
||||
{filled}
|
||||
{disabled}
|
||||
{height}
|
||||
{width}>Label</Button
|
||||
>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
</Story>
|
||||
|
@ -1,49 +1,25 @@
|
||||
<script lang="ts">
|
||||
export let primary = false;
|
||||
export let outlined = false;
|
||||
export let role: 'basic' | 'primary' | 'destructive' = 'basic';
|
||||
export let filled = true;
|
||||
const outlined = true;
|
||||
export let disabled = false;
|
||||
export let small = false;
|
||||
export let wide = false;
|
||||
export let height: 'basic' | 'small' = 'basic';
|
||||
export let width: 'basic' | 'long' = 'basic';
|
||||
export let type: 'button' | 'submit' = 'button';
|
||||
export let href: string | undefined = undefined;
|
||||
</script>
|
||||
|
||||
<!--
|
||||
@component
|
||||
This is the only button we should be using in the app.
|
||||
It emits a click event like any self respecting button should.
|
||||
|
||||
It takes the following required props:
|
||||
|
||||
And the following optional props:
|
||||
- `primary` - boolean - whether the button should be primary or not
|
||||
- `outlined` - boolean - whether the button should be outlined or not
|
||||
- `small` - boolean - whether the button should be small or not
|
||||
- `href` - string - if this is set, the button will be a link instead of a button
|
||||
- `type` - string - the type of button, defaults to `button`
|
||||
- `disabled` - boolean - whether the button is disabled or not
|
||||
|
||||
- Usage:
|
||||
```tsx
|
||||
<Button {...props} on:click={yourFunction} >
|
||||
label
|
||||
</Button>
|
||||
```
|
||||
-->
|
||||
|
||||
{#if href}
|
||||
<a
|
||||
{href}
|
||||
class="btn-base"
|
||||
class:btn-disabled={disabled}
|
||||
class:btn-primary-outline={primary && outlined}
|
||||
class:btn-primary={primary && !outlined}
|
||||
class:btn-basic-outline={!primary && outlined}
|
||||
class:btn-basic={!primary && !outlined}
|
||||
class:btn-height-small={small}
|
||||
class:btn-height-normal={!small}
|
||||
class:btn-width-normal={wide}
|
||||
class:btn-width-small={!wide}
|
||||
class="{role} flex w-fit items-center justify-center gap-2 whitespace-nowrap rounded border text-base font-medium text-zinc-50 transition ease-in-out"
|
||||
class:small={height === 'small'}
|
||||
class:long={width === 'long'}
|
||||
class:filled
|
||||
class:outlined
|
||||
{type}
|
||||
on:click
|
||||
class:disabled
|
||||
>
|
||||
{#if $$slots.icon}
|
||||
<div class="icon">
|
||||
@ -54,18 +30,15 @@ And the following optional props:
|
||||
</a>
|
||||
{:else}
|
||||
<button
|
||||
class="{role} flex w-fit items-center justify-center gap-2 whitespace-nowrap rounded border text-base font-medium text-zinc-50 transition ease-in-out"
|
||||
class:small={height === 'small'}
|
||||
class:long={width === 'long'}
|
||||
class:filled
|
||||
class:outlined
|
||||
{disabled}
|
||||
{type}
|
||||
on:click
|
||||
class="btn-base"
|
||||
class:btn-disabled={disabled}
|
||||
class:btn-primary-outline={primary && outlined}
|
||||
class:btn-primary={primary && !outlined}
|
||||
class:btn-basic-outline={!primary && outlined}
|
||||
class:btn-basic={!primary && !outlined}
|
||||
class:btn-height-small={small}
|
||||
class:btn-height-normal={!small}
|
||||
class:btn-width-normal={wide}
|
||||
class:btn-width-small={!wide}
|
||||
class:disabled
|
||||
>
|
||||
{#if $$slots.icon}
|
||||
<div class="icon">
|
||||
@ -77,74 +50,61 @@ And the following optional props:
|
||||
{/if}
|
||||
|
||||
<style lang="postcss">
|
||||
.icon {
|
||||
@apply h-4 w-4 text-zinc-50;
|
||||
.disabled {
|
||||
@apply pointer-events-none opacity-40;
|
||||
}
|
||||
|
||||
.btn-base {
|
||||
@apply flex w-fit items-center justify-center gap-2 whitespace-nowrap rounded text-base text-zinc-50 shadow transition ease-in-out;
|
||||
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.3);
|
||||
border-left: 1px solid rgba(255, 255, 255, 0);
|
||||
border-right: 1px solid rgba(255, 255, 255, 0);
|
||||
text-shadow: 0px 2px #00000021;
|
||||
.filled,
|
||||
.outlined {
|
||||
@apply px-[16px] py-[10px];
|
||||
}
|
||||
|
||||
.btn-disabled {
|
||||
@apply opacity-40;
|
||||
pointer-events: none;
|
||||
.filled.small,
|
||||
.outlined.small {
|
||||
@apply py-[4px];
|
||||
}
|
||||
|
||||
/* Primary */
|
||||
.btn-primary {
|
||||
background: #3662e3;
|
||||
}
|
||||
.btn-primary:hover {
|
||||
background: #1c48c9;
|
||||
@apply transition ease-in-out;
|
||||
}
|
||||
.btn-primary-outline {
|
||||
background: rgba(28, 72, 201, 0);
|
||||
border: 1px solid #3662e3;
|
||||
@apply transition ease-in-out;
|
||||
}
|
||||
.btn-primary-outline:hover {
|
||||
background: rgba(28, 72, 201, 0.3);
|
||||
border: 1px solid #3662e3;
|
||||
@apply transition ease-in-out;
|
||||
.filled.long,
|
||||
.outlined.long {
|
||||
@apply px-[42px];
|
||||
}
|
||||
|
||||
/* Basic */
|
||||
.btn-basic {
|
||||
background: #71717a;
|
||||
@apply transition ease-in-out;
|
||||
.basic {
|
||||
@apply border-zinc-500;
|
||||
}
|
||||
.btn-basic:hover {
|
||||
@apply border-zinc-600 bg-zinc-600;
|
||||
.basic:hover {
|
||||
@apply bg-[#FFFFFF1A]/10;
|
||||
}
|
||||
.btn-basic-outline {
|
||||
background: rgba(113, 113, 122, 0);
|
||||
border: 1px solid #71717a;
|
||||
@apply transition ease-in-out;
|
||||
.basic.filled {
|
||||
@apply border-transparent bg-zinc-500;
|
||||
}
|
||||
.btn-basic-outline:hover {
|
||||
background: rgba(113, 113, 122, 0.4);
|
||||
border: 1px solid #71717a;
|
||||
@apply transition ease-in-out;
|
||||
.basic.filled:hover {
|
||||
@apply bg-zinc-600;
|
||||
}
|
||||
|
||||
/* Size */
|
||||
.btn-height-normal {
|
||||
@apply py-2;
|
||||
.primary {
|
||||
@apply border-[#3662E3];
|
||||
}
|
||||
.btn-height-small {
|
||||
@apply py-1;
|
||||
.primary:hover {
|
||||
@apply bg-[#1C48C94D]/30;
|
||||
}
|
||||
.btn-width-normal {
|
||||
@apply px-[42.75px];
|
||||
.primary.filled {
|
||||
@apply border-transparent bg-blue-600;
|
||||
}
|
||||
.btn-width-small {
|
||||
@apply px-[16px];
|
||||
.primary.filled:hover {
|
||||
@apply bg-[#1C48C9];
|
||||
}
|
||||
|
||||
.destructive {
|
||||
@apply border-[#E33636];
|
||||
}
|
||||
.destructive:hover {
|
||||
@apply bg-[#E336364D]/30;
|
||||
}
|
||||
.destructive.filled {
|
||||
@apply border-transparent bg-[#E33636];
|
||||
}
|
||||
.destructive.filled:hover {
|
||||
@apply bg-[#C91C1C];
|
||||
}
|
||||
</style>
|
||||
|
@ -13,7 +13,13 @@
|
||||
</Story>
|
||||
|
||||
<Story name="Two buttons wide">
|
||||
<ButtonGroup leftLabel="Cancel" rightLabel="Submit" wide leftAction={noop} rightAction={noop} />
|
||||
<ButtonGroup
|
||||
leftLabel="Cancel"
|
||||
rightLabel="Submit"
|
||||
width="long"
|
||||
leftAction={noop}
|
||||
rightAction={noop}
|
||||
/>
|
||||
</Story>
|
||||
|
||||
<Story name="Three buttons">
|
||||
@ -31,7 +37,7 @@
|
||||
leftLabel="Cancel"
|
||||
rightLabel="Submit"
|
||||
middleLabel="Middle"
|
||||
wide
|
||||
width="long"
|
||||
leftAction={noop}
|
||||
rightAction={noop}
|
||||
/>
|
||||
|
@ -7,28 +7,28 @@
|
||||
export let rightAction: () => void;
|
||||
export let middleLabel: string | undefined = undefined;
|
||||
export let middleAction: (() => void) | undefined = undefined;
|
||||
export let wide = false;
|
||||
export let width: 'basic' | 'long' = 'basic';
|
||||
</script>
|
||||
|
||||
{#if !middleLabel}
|
||||
<div class="btn-group">
|
||||
<Button on:click={leftAction} outlined={true} {wide}>
|
||||
<Button on:click={leftAction} {width}>
|
||||
{leftLabel}
|
||||
</Button>
|
||||
<Button on:click={rightAction} primary={true} outlined={false} {wide}>
|
||||
<Button on:click={rightAction} role="primary" {width}>
|
||||
{rightLabel}
|
||||
</Button>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="btn-group btn-group--segmented">
|
||||
<button class="joined-base rounded-l-lg border-l border-t border-b" on:click={leftAction}>
|
||||
<span class="my-2 {wide ? 'mx-[31.5px]' : 'mx-[16px]'}">{leftLabel}</span>
|
||||
<span class="my-2 {width === 'long' ? 'mx-[31.5px]' : 'mx-[16px]'}">{leftLabel}</span>
|
||||
</button>
|
||||
<button class="joined-base border" on:click={middleAction}>
|
||||
<span class="my-2 {wide ? 'mx-[31.5px]' : 'mx-[16px]'}">{middleLabel}</span>
|
||||
<span class="my-2 {width === 'long' ? 'mx-[31.5px]' : 'mx-[16px]'}">{middleLabel}</span>
|
||||
</button>
|
||||
<button class="joined-base rounded-r-lg border-r border-t border-b" on:click={rightAction}>
|
||||
<span class="my-2 {wide ? 'mx-[31.5px]' : 'mx-[16px]'}">{rightLabel}</span>
|
||||
<span class="my-2 {width === 'long' ? 'mx-[31.5px]' : 'mx-[16px]'}">{rightLabel}</span>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -160,7 +160,9 @@
|
||||
</div>
|
||||
<div>
|
||||
<Tooltip label="Adds a git repository on your computer to GitButler">
|
||||
<Button primary on:click={onAddLocalRepositoryClick}>Track a New Project</Button>
|
||||
<Button role="primary" on:click={onAddLocalRepositoryClick}
|
||||
>Track a New Project</Button
|
||||
>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -152,7 +152,7 @@
|
||||
</span>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<Button primary href="/projects/{$project?.id}/commit">Commit changes</Button>
|
||||
<Button role="primary" href="/projects/{$project?.id}/commit">Commit changes</Button>
|
||||
</div>
|
||||
|
||||
{#if $statuses.length === 0}
|
||||
|
@ -195,7 +195,11 @@
|
||||
<span>Comitting...</span>
|
||||
</div>
|
||||
{:else}
|
||||
<Button disabled={!isCommitEnabled || isGeneratingCommitMessage} primary type="submit">
|
||||
<Button
|
||||
disabled={!isCommitEnabled || isGeneratingCommitMessage}
|
||||
role="primary"
|
||||
type="submit"
|
||||
>
|
||||
Commit changes
|
||||
</Button>
|
||||
{/if}
|
||||
|
@ -193,7 +193,7 @@
|
||||
<span>Updating...</span>
|
||||
</div>
|
||||
{:else}
|
||||
<Button primary type="submit">Update profile</Button>
|
||||
<Button role="primary" type="submit">Update profile</Button>
|
||||
{/if}
|
||||
</footer>
|
||||
</form>
|
||||
|
@ -104,7 +104,7 @@
|
||||
<span>Updating...</span>
|
||||
</div>
|
||||
{:else}
|
||||
<Button primary type="submit">Update profile</Button>
|
||||
<Button role="primary" type="submit">Update profile</Button>
|
||||
{/if}
|
||||
</footer>
|
||||
</fields>
|
||||
|
Loading…
Reference in New Issue
Block a user