replace google material icons with phosphor icons
This commit is contained in:
@@ -13,12 +13,6 @@
|
|||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Material Design Icons -->
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
|
|
||||||
%sveltekit.head%
|
%sveltekit.head%
|
||||||
</head>
|
</head>
|
||||||
<body data-sveltekit-preload-data="hover">
|
<body data-sveltekit-preload-data="hover">
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
import type { Snippet } from 'svelte';
|
import type { Snippet } from 'svelte';
|
||||||
import type { ClassValue, HTMLButtonAttributes, MouseEventHandler } from 'svelte/elements';
|
import type { ClassValue, HTMLButtonAttributes, MouseEventHandler } from 'svelte/elements';
|
||||||
import Spinner from './Spinner.svelte';
|
import Spinner from './Spinner.svelte';
|
||||||
|
import type { IconComponentProps } from 'phosphor-svelte';
|
||||||
|
import { defaultIconProps, type IconDef } from './util';
|
||||||
|
|
||||||
interface Props extends Omit<HTMLButtonAttributes, 'class'> {
|
interface Props extends Omit<HTMLButtonAttributes, 'class'> {
|
||||||
icon?: string;
|
icon?: IconDef;
|
||||||
animate?: boolean;
|
animate?: boolean;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
class?: ClassValue | null | undefined;
|
class?: ClassValue | null | undefined;
|
||||||
@@ -25,7 +27,13 @@
|
|||||||
...others
|
...others
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
let iconElement = $state<HTMLSpanElement | null>(null);
|
type SVGInHTML = HTMLElement & SVGElement;
|
||||||
|
let iconElement = $state<SVGInHTML | null>(null);
|
||||||
|
$effect(() => {
|
||||||
|
if (icon && ref) {
|
||||||
|
iconElement = ref.querySelector('svg') as SVGInHTML | null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const handleButtonClick: MouseEventHandler<HTMLButtonElement> = (event) => {
|
const handleButtonClick: MouseEventHandler<HTMLButtonElement> = (event) => {
|
||||||
if (animate) {
|
if (animate) {
|
||||||
@@ -41,8 +49,11 @@
|
|||||||
const triggerAnimation = (className: string) => {
|
const triggerAnimation = (className: string) => {
|
||||||
if (icon && iconElement) {
|
if (icon && iconElement) {
|
||||||
iconElement.classList.remove(className);
|
iconElement.classList.remove(className);
|
||||||
void iconElement.offsetWidth;
|
|
||||||
iconElement.classList.add(className);
|
// make sure we have DOM reflow
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
iconElement?.classList.add(className);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -76,7 +87,7 @@
|
|||||||
{type}
|
{type}
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
class={[
|
class={[
|
||||||
'button group relative flex gap-3 overflow-hidden rounded-sm px-5',
|
'button group relative flex items-center gap-3 overflow-hidden rounded-sm px-5',
|
||||||
'text-sui-background cursor-pointer py-3 font-medium transition-colors',
|
'text-sui-background cursor-pointer py-3 font-medium transition-colors',
|
||||||
!loading ? ' bg-sui-primary hover:bg-sui-secondary' : 'bg-sui-primary/50 cursor-not-allowed ',
|
!loading ? ' bg-sui-primary hover:bg-sui-secondary' : 'bg-sui-primary/50 cursor-not-allowed ',
|
||||||
classValue
|
classValue
|
||||||
@@ -87,7 +98,7 @@
|
|||||||
{@render children()}
|
{@render children()}
|
||||||
|
|
||||||
{#if icon && !loading}
|
{#if icon && !loading}
|
||||||
<span class="material-symbols-outlined" bind:this={iconElement}>{icon}</span>
|
<icon.component {...icon.props || defaultIconProps} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if loading}
|
{#if loading}
|
||||||
@@ -140,12 +151,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(button span.animate) {
|
:global(button svg.animate) {
|
||||||
animation-name: loop;
|
animation-name: loop;
|
||||||
animation-duration: 0.5s;
|
animation-duration: 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(button span.bounce) {
|
:global(button svg.bounce) {
|
||||||
animation-name: bounce;
|
animation-name: bounce;
|
||||||
animation-duration: 180ms;
|
animation-duration: 180ms;
|
||||||
animation-timing-function: ease-in-out;
|
animation-timing-function: ease-in-out;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
import { validate } from '@svelte-toolkit/validate';
|
import { validate } from '@svelte-toolkit/validate';
|
||||||
import { generateIdentifier } from './util';
|
import { generateIdentifier } from './util';
|
||||||
import type { ClassValue } from 'svelte/elements';
|
import type { ClassValue } from 'svelte/elements';
|
||||||
|
import { Check, Minus } from 'phosphor-svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
name?: string;
|
name?: string;
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
let id = $derived(generateIdentifier('checkbox', name));
|
let id = $derived(generateIdentifier('checkbox', name));
|
||||||
|
|
||||||
let valid = $state(true);
|
let valid = $state(true);
|
||||||
|
let Icon = $derived(value === 'indeterminate' ? Minus : value ? Check : undefined);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class={['flex items-center', classValue]}>
|
<div class={['flex items-center', classValue]}>
|
||||||
@@ -69,10 +71,8 @@
|
|||||||
onchange?.(value);
|
onchange?.(value);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{#if value === 'indeterminate'}
|
{#if Icon}
|
||||||
<span class="material-symbols-outlined">remove</span>
|
<Icon weight="bold" size="1.1em"></Icon>
|
||||||
{:else if value === true}
|
|
||||||
<span class="material-symbols-outlined">check</span>
|
|
||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Snippet } from 'svelte';
|
import type { Snippet } from 'svelte';
|
||||||
import type { ClassValue, MouseEventHandler } from 'svelte/elements';
|
import type { ClassValue, MouseEventHandler } from 'svelte/elements';
|
||||||
|
import { defaultIconProps, type IconDef } from './util';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
icon?: string;
|
icon?: IconDef;
|
||||||
iconPosition?: 'left' | 'right';
|
iconPosition?: 'left' | 'right';
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
class?: ClassValue | null | undefined;
|
class?: ClassValue | null | undefined;
|
||||||
@@ -22,7 +23,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#snippet iconSnippet()}
|
{#snippet iconSnippet()}
|
||||||
<span class="material-symbols-outlined">{icon}</span>
|
{#if icon}
|
||||||
|
<icon.component {...icon.props || defaultIconProps} />
|
||||||
|
{/if}
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
| false
|
| false
|
||||||
| {
|
| {
|
||||||
text: string;
|
text: string;
|
||||||
icon: string;
|
icon: IconDef;
|
||||||
onclick?: MouseEventHandler<HTMLButtonElement>;
|
onclick?: MouseEventHandler<HTMLButtonElement>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -40,6 +40,8 @@
|
|||||||
import { tweened } from 'svelte/motion';
|
import { tweened } from 'svelte/motion';
|
||||||
import { fade, fly } from 'svelte/transition';
|
import { fade, fly } from 'svelte/transition';
|
||||||
import { validateForm } from '@svelte-toolkit/validate';
|
import { validateForm } from '@svelte-toolkit/validate';
|
||||||
|
import { ArrowLeft, Check } from 'phosphor-svelte';
|
||||||
|
import type { IconDef } from './util';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
pages,
|
pages,
|
||||||
@@ -321,7 +323,7 @@
|
|||||||
{#if i >= index}
|
{#if i >= index}
|
||||||
<span class="mb-[0.0625rem]">{i + 1}</span>
|
<span class="mb-[0.0625rem]">{i + 1}</span>
|
||||||
{:else}
|
{:else}
|
||||||
<span class="material-symbols-outlined mt-0.5 text-2xl">check_small</span>
|
<Check class="mt-0.5" size="1.5rem" weight="bold" />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
@@ -339,7 +341,7 @@
|
|||||||
onclick={() => (index -= 1)}
|
onclick={() => (index -= 1)}
|
||||||
transition:fly={{ x: -200, duration: 200 }}
|
transition:fly={{ x: -200, duration: 200 }}
|
||||||
>
|
>
|
||||||
<span class="material-symbols-outlined text-base">arrow_back</span>
|
<ArrowLeft />
|
||||||
Back
|
Back
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
import type { IconComponentProps } from 'phosphor-svelte';
|
||||||
|
import type { Component } from 'svelte';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IconDef is an object that represents an icon element from the phosphor library, alongside an optional set of typed properties.
|
||||||
|
*/
|
||||||
|
export type IconDef = {
|
||||||
|
component: Component;
|
||||||
|
props?: IconComponentProps;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a set of default properties for icons used in the application.
|
||||||
|
*/
|
||||||
|
export const defaultIconProps: IconComponentProps = {
|
||||||
|
size: '1.2rem',
|
||||||
|
weight: 'bold'
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MaybeGetter is a type that can either be a value of type T or a function that returns a value of type T.
|
* MaybeGetter is a type that can either be a value of type T or a function that returns a value of type T.
|
||||||
* This is useful for cases where you might want to pass a value directly or a function that computes the
|
* This is useful for cases where you might want to pass a value directly or a function that computes the
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
import {
|
import {
|
||||||
ArrowUUpLeft,
|
ArrowUUpLeft,
|
||||||
ArrowUUpRight,
|
ArrowUUpRight,
|
||||||
|
Plus,
|
||||||
TextB,
|
TextB,
|
||||||
TextItalic,
|
TextItalic,
|
||||||
TextStrikethrough,
|
TextStrikethrough,
|
||||||
@@ -51,12 +52,14 @@
|
|||||||
<div class="component">
|
<div class="component">
|
||||||
<p class="title">Button, Frameless Button, & Link</p>
|
<p class="title">Button, Frameless Button, & Link</p>
|
||||||
<div class="flex gap-4">
|
<div class="flex gap-4">
|
||||||
<Button icon="add" loading={false} onclick={() => alert('Button clicked!')}>Click Me</Button>
|
<Button icon={{ component: Plus }} loading={false} onclick={() => alert('Button clicked!')}
|
||||||
<Button icon="add" loading={true} onclick={() => alert('Button clicked!')}
|
>Click Me</Button
|
||||||
|
>
|
||||||
|
<Button icon={{ component: Plus }} loading={true} onclick={() => alert('Button clicked!')}
|
||||||
>Loading Button</Button
|
>Loading Button</Button
|
||||||
>
|
>
|
||||||
|
|
||||||
<FramelessButton icon="add">Click Me</FramelessButton>
|
<FramelessButton icon={{ component: Plus }}>Click Me</FramelessButton>
|
||||||
|
|
||||||
<Link href="https://svelte.dev">Visit Svelte</Link>
|
<Link href="https://svelte.dev">Visit Svelte</Link>
|
||||||
|
|
||||||
@@ -136,7 +139,7 @@
|
|||||||
<DateInput bind:value={dateInputValue} />
|
<DateInput bind:value={dateInputValue} />
|
||||||
<div class="shrink-0">
|
<div class="shrink-0">
|
||||||
<Button
|
<Button
|
||||||
icon="add"
|
icon={{ component: Plus }}
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
dateInputValue = new Date();
|
dateInputValue = new Date();
|
||||||
console.log('Dateinput value set to:', dateInputValue);
|
console.log('Dateinput value set to:', dateInputValue);
|
||||||
|
|||||||
Reference in New Issue
Block a user