-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
274 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
<script lang="ts"> | ||
import { IconButton, Card, CardBody, CardHeader, CardTitle } from '@immich/ui'; | ||
import type { Color, Shape, Size } from '@immich/ui'; | ||
import { mdiMagnify } from '@mdi/js'; | ||
const colors: Color[] = ['primary', 'secondary', 'success', 'danger', 'warning', 'info']; | ||
const sizes: Size[] = ['tiny', 'small', 'medium', 'large', 'giant']; | ||
const shapes: Shape[] = ['rectangle', 'semi-round', 'round']; | ||
const icon = mdiMagnify; | ||
</script> | ||
|
||
<div class="flex flex-col gap-4"> | ||
<Card> | ||
<CardHeader> | ||
<CardTitle>Shapes</CardTitle> | ||
</CardHeader> | ||
<CardBody> | ||
<div class="flex flex-wrap gap-4"> | ||
{#each shapes as shape} | ||
<IconButton {icon} {shape} /> | ||
{/each} | ||
</div> | ||
</CardBody> | ||
</Card> | ||
|
||
<Card> | ||
<CardHeader> | ||
<CardTitle>Colors</CardTitle> | ||
</CardHeader> | ||
<CardBody> | ||
<div class="flex flex-wrap gap-4"> | ||
{#each colors as color} | ||
<IconButton {icon} {color}></IconButton> | ||
{/each} | ||
</div> | ||
</CardBody> | ||
</Card> | ||
|
||
<Card> | ||
<CardHeader> | ||
<CardTitle>Outline</CardTitle> | ||
</CardHeader> | ||
<CardBody> | ||
<div class="flex flex-wrap gap-4"> | ||
{#each colors as color} | ||
<IconButton {icon} variant="outline" {color}></IconButton> | ||
{/each} | ||
</div> | ||
</CardBody> | ||
</Card> | ||
|
||
<Card> | ||
<CardHeader> | ||
<CardTitle>Ghost</CardTitle> | ||
</CardHeader> | ||
<CardBody> | ||
<div class="flex flex-wrap gap-4"> | ||
{#each colors as color} | ||
<IconButton {icon} variant="ghost" {color}></IconButton> | ||
{/each} | ||
</div> | ||
</CardBody> | ||
</Card> | ||
|
||
<Card> | ||
<CardHeader> | ||
<CardTitle>Hero</CardTitle> | ||
</CardHeader> | ||
<CardBody> | ||
<div class="flex flex-wrap gap-4"> | ||
{#each colors as color} | ||
<IconButton {icon} variant="hero" {color}></IconButton> | ||
{/each} | ||
</div> | ||
</CardBody> | ||
</Card> | ||
|
||
<Card> | ||
<CardHeader> | ||
<CardTitle>Disabled</CardTitle> | ||
</CardHeader> | ||
<CardBody> | ||
<div class="flex flex-wrap gap-4"> | ||
{#each colors as color} | ||
<IconButton {icon} {color} disabled></IconButton> | ||
{/each} | ||
</div> | ||
</CardBody> | ||
</Card> | ||
|
||
<Card> | ||
<CardHeader> | ||
<CardTitle>Sizes</CardTitle> | ||
</CardHeader> | ||
<CardBody> | ||
<div class="flex flex-wrap gap-4"> | ||
{#each sizes as size} | ||
<div> | ||
<IconButton {icon} {size}></IconButton> | ||
</div> | ||
{/each} | ||
</div> | ||
</CardBody> | ||
</Card> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,127 +1,8 @@ | ||
<script lang="ts"> | ||
import type { Color, Shape, Size } from '$lib/types.js'; | ||
import { cleanClass } from '$lib/utils.js'; | ||
import { Button as ButtonPrimitive } from 'bits-ui'; | ||
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements'; | ||
import { tv } from 'tailwind-variants'; | ||
import InternalButton from '$lib/internal/InternalButton.svelte'; | ||
import type { ButtonProps } from '$lib/types.js'; | ||
type ButtonVariant = 'filled' | 'outline' | 'ghost' | 'hero'; | ||
type ButtonProps = { | ||
class?: string; | ||
color?: Color; | ||
size?: Size; | ||
shape?: Shape; | ||
variant?: ButtonVariant; | ||
fullWidth?: boolean; | ||
} & (({ href?: never } & HTMLButtonAttributes) | ({ href: string } & HTMLAnchorAttributes)); | ||
const asOverride = (variant: ButtonVariant, colors: Record<Color, string>) => | ||
(Object.keys(colors) as Color[]).map((color) => ({ variant, color, class: colors[color] })); | ||
const colorPlaceholder = { | ||
primary: '', | ||
secondary: '', | ||
success: '', | ||
danger: '', | ||
warning: '', | ||
info: '', | ||
}; | ||
const variantPlaceholder = { | ||
outline: '', | ||
filled: '', | ||
ghost: '', | ||
hero: '', | ||
}; | ||
const buttonVariants = tv({ | ||
base: 'ring-offset-background focus-visible:ring-ring flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50', | ||
variants: { | ||
shape: { | ||
rectangle: 'rounded-none', | ||
'semi-round': 'rounded-xl', | ||
round: 'rounded-full', | ||
}, | ||
size: { | ||
tiny: 'px-2 py-1 text-xs', | ||
small: 'px-2 py-1 text-sm', | ||
medium: 'px-4 py-2 text-md', | ||
large: 'px-4 py-2 text-lg', | ||
giant: 'px-8 py-4 text-xl', | ||
}, | ||
fullWidth: { | ||
true: 'w-full', | ||
}, | ||
color: colorPlaceholder, | ||
variant: variantPlaceholder, | ||
}, | ||
compoundVariants: [ | ||
...asOverride('filled', { | ||
primary: 'bg-primary text-light hover:bg-primary/80', | ||
secondary: 'bg-dark text-light hover:bg-dark/80', | ||
success: 'bg-success text-light hover:bg-success/80', | ||
danger: 'bg-danger text-light hover:bg-danger/80', | ||
warning: 'bg-warning text-light hover:bg-warning/80', | ||
info: 'bg-info text-light hover:bg-info/80', | ||
}), | ||
...asOverride('outline', { | ||
primary: 'bg-primary/10 text-primary border border-primary hover:bg-primary/20', | ||
secondary: 'bg-dark/10 text-dark border border-dark hover:bg-dark/20', | ||
success: 'bg-success/10 text-success border border-success hover:bg-success/20', | ||
danger: 'bg-danger/10 text-danger border border-danger hover:bg-danger/20', | ||
warning: 'bg-warning/10 text-warning border border-warning hover:bg-warning/20', | ||
info: 'bg-info/10 text-info border border-info hover:bg-info/20', | ||
}), | ||
...asOverride('ghost', { | ||
primary: 'text-primary hover:bg-primary/10', | ||
secondary: 'text-dark hover:bg-dark/10', | ||
success: 'text-success hover:bg-success/10', | ||
danger: 'text-danger hover:bg-danger/10', | ||
warning: 'text-warning hover:bg-warning/10', | ||
info: 'text-info hover:bg-info/10', | ||
}), | ||
...asOverride('hero', { | ||
primary: 'bg-gradient-to-tr from-primary to-primary/60 text-light hover:bg-primary', | ||
secondary: 'bg-gradient-to-tr from-dark to-dark/60 text-light hover:bg-dark', | ||
success: 'bg-gradient-to-tr from-success to-success/60 text-light hover:bg-success', | ||
danger: 'bg-gradient-to-tr from-danger to-danger/60 text-light hover:bg-danger', | ||
warning: 'bg-gradient-to-tr from-warning to-warning/60 text-light hover:bg-warning', | ||
info: 'bg-gradient-to-tr from-info to-info/60 text-light hover:bg-info', | ||
}), | ||
], | ||
}); | ||
const { | ||
type = 'button', | ||
href, | ||
variant = 'filled', | ||
color = 'primary', | ||
shape = 'semi-round', | ||
size = 'medium', | ||
fullWidth = false, | ||
class: className = '', | ||
children, | ||
...restProps | ||
}: ButtonProps = $props(); | ||
const classList = $derived( | ||
cleanClass(buttonVariants({ variant, color, shape, size, fullWidth }), className), | ||
); | ||
const props: ButtonProps = $props(); | ||
</script> | ||
|
||
{#if href} | ||
<a {href} class={classList} {...restProps as HTMLAnchorAttributes}> | ||
{@render children?.()} | ||
</a> | ||
{:else} | ||
<ButtonPrimitive.Root | ||
class={classList} | ||
type={type as HTMLButtonAttributes['type']} | ||
{...restProps as HTMLButtonAttributes} | ||
> | ||
{@render children?.()} | ||
</ButtonPrimitive.Root> | ||
{/if} | ||
<InternalButton {...props} /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<script lang="ts"> | ||
import InternalButton from '$lib/internal/InternalButton.svelte'; | ||
import { Icon } from '$lib/components/index.js'; | ||
import type { IconButtonProps } from '$lib/types.js'; | ||
const { icon, ...buttonProps }: IconButtonProps = $props(); | ||
</script> | ||
|
||
<InternalButton icon {...buttonProps}> | ||
<Icon path={icon}></Icon> | ||
</InternalButton> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.