fix(web): avoid nesting buttons inside links (#11425)

This commit is contained in:
Michel Heusschen
2024-07-29 16:36:10 +02:00
committed by GitHub
parent 7bb7f63d57
commit 2e059bfbfd
15 changed files with 216 additions and 96 deletions

View File

@@ -1,18 +1,48 @@
<script lang="ts" context="module">
import type { HTMLButtonAttributes, HTMLLinkAttributes } from 'svelte/elements';
export type Color = 'transparent' | 'light' | 'dark' | 'gray' | 'primary' | 'opaque';
export type Padding = '1' | '2' | '3';
type BaseProps = {
icon: string;
title: string;
class?: string;
color?: Color;
padding?: Padding;
size?: string;
hideMobile?: true;
buttonSize?: string;
viewBox?: string;
};
export type ButtonProps = HTMLButtonAttributes &
BaseProps & {
href?: never;
};
export type LinkProps = HTMLLinkAttributes &
BaseProps & {
type?: never;
};
export type Props = ButtonProps | LinkProps;
</script>
<script lang="ts">
import Icon from '$lib/components/elements/icon.svelte';
export let type: 'button' | 'submit' | 'reset' = 'button';
type $$Props = Props;
export let type: $$Props['type'] = 'button';
export let href: $$Props['href'] = undefined;
export let icon: string;
export let color: Color = 'transparent';
export let title: string;
/**
* The padding of the button, used by the `p-{padding}` Tailwind CSS class.
*/
export let padding = '3';
export let padding: Padding = '3';
/**
* Size of the button, used for a CSS value.
*/
@@ -23,12 +53,6 @@
* viewBox attribute for the SVG icon.
*/
export let viewBox: string | undefined = undefined;
export let id: string | undefined = undefined;
export let ariaHasPopup: boolean | undefined = undefined;
export let ariaExpanded: boolean | undefined = undefined;
export let ariaControls: string | undefined = undefined;
export let tabindex: number | undefined = undefined;
export let disabled: boolean | undefined = undefined;
/**
* Override the default styling of the button for specific use cases, such as the icon color.
@@ -46,24 +70,28 @@
'bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 hover:dark:bg-immich-dark-primary/80 text-white dark:text-immich-dark-gray',
};
const paddingClasses: Record<Padding, string> = {
'1': 'p-1',
'2': 'p-2',
'3': 'p-3',
};
$: colorClass = colorClasses[color];
$: mobileClass = hideMobile ? 'hidden sm:flex' : '';
$: paddingClass = `p-${padding}`;
$: paddingClass = paddingClasses[padding];
</script>
<button
{id}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<svelte:element
this={href ? 'a' : 'button'}
type={href ? undefined : type}
{title}
{type}
{tabindex}
{disabled}
{href}
style:width={buttonSize ? buttonSize + 'px' : ''}
style:height={buttonSize ? buttonSize + 'px' : ''}
class="flex place-content-center place-items-center rounded-full {colorClass} {paddingClass} transition-all disabled:cursor-default hover:dark:text-immich-dark-gray {className} {mobileClass}"
aria-haspopup={ariaHasPopup}
aria-expanded={ariaExpanded}
aria-controls={ariaControls}
on:click
{...$$restProps}
>
<Icon path={icon} {size} ariaLabel={title} {viewBox} color="currentColor" />
</button>
</svelte:element>