@orochibraru/ui 1.0.3 → 1.0.4-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -55,6 +55,9 @@ spinner, switch, table, tabs, textarea, toggle, toggle-group, tooltip.
55
55
  `input` turns password managers off on fields that don't set `autocomplete`, so
56
56
  a search box never gets a login suggestion.
57
57
 
58
+ `button` takes `loading`: it disables the button and shows a spinner in place of
59
+ its label, keeping its width, so a pending submit can't be clicked twice.
60
+
58
61
  ## Components
59
62
 
60
63
  Under `@orochibraru/ui/components/<name>`: one import, data in. Where a
@@ -269,9 +272,9 @@ packages `dist/` and runs publint.
269
272
 
270
273
  New upstream components come from the shadcn-svelte CLI (`components.json` is
271
274
  set up), followed by `node_modules/.bin/tailwint --fix` on the new files. The
272
- CLI overwrites any customised primitive a new one depends on (drawer, input and
273
- sonner carry the apps' changes): copy those aside before `add --overwrite` and
274
- put them back after.
275
+ CLI overwrites any customised primitive a new one depends on (button, drawer,
276
+ input and sonner carry the apps' changes): copy those aside before
277
+ `add --overwrite` and put them back after.
275
278
 
276
279
  Dependencies use caret ranges, unlike the apps' exact pins, so a consuming app
277
280
  dedupes `bits-ui` and friends with its own copy instead of bundling two.
@@ -5,6 +5,7 @@
5
5
  } from "svelte/elements";
6
6
  import { tv, type VariantProps } from "tailwind-variants";
7
7
 
8
+ import { Spinner } from "../spinner/index.js";
8
9
  import { cn, type WithElementRef } from "../../../utils.js";
9
10
 
10
11
  export const buttonVariants = tv({
@@ -50,6 +51,7 @@
50
51
  WithElementRef<HTMLAnchorAttributes> & {
51
52
  variant?: ButtonVariant;
52
53
  size?: ButtonSize;
54
+ loading?: boolean;
53
55
  };
54
56
  </script>
55
57
 
@@ -62,33 +64,55 @@
62
64
  href = undefined,
63
65
  type = "button",
64
66
  disabled,
67
+ loading = false,
65
68
  children,
66
69
  ...restProps
67
70
  }: ButtonProps = $props();
71
+
72
+ const inert = $derived(disabled || loading);
68
73
  </script>
69
74
 
75
+ {#snippet content()}
76
+ {#if loading}
77
+ <span class="invisible contents">{@render children?.()}</span>
78
+ <Spinner class="absolute inset-0 m-auto" />
79
+ {:else}
80
+ {@render children?.()}
81
+ {/if}
82
+ {/snippet}
83
+
70
84
  {#if href}
71
85
  <a
72
86
  bind:this={ref}
73
87
  data-slot="button"
74
- class={cn(buttonVariants({ variant, size }), className)}
75
- href={disabled ? undefined : href}
76
- aria-disabled={disabled}
77
- role={disabled ? "link" : undefined}
78
- tabindex={disabled ? -1 : undefined}
88
+ class={cn(
89
+ buttonVariants({ variant, size }),
90
+ loading && "relative",
91
+ className,
92
+ )}
93
+ href={inert ? undefined : href}
94
+ aria-disabled={inert}
95
+ aria-busy={loading || undefined}
96
+ role={inert ? "link" : undefined}
97
+ tabindex={inert ? -1 : undefined}
79
98
  {...restProps}
80
99
  >
81
- {@render children?.()}
100
+ {@render content()}
82
101
  </a>
83
102
  {:else}
84
103
  <button
85
104
  bind:this={ref}
86
105
  data-slot="button"
87
- class={cn(buttonVariants({ variant, size }), className)}
106
+ class={cn(
107
+ buttonVariants({ variant, size }),
108
+ loading && "relative",
109
+ className,
110
+ )}
88
111
  {type}
89
- {disabled}
112
+ disabled={inert}
113
+ aria-busy={loading || undefined}
90
114
  {...restProps}
91
115
  >
92
- {@render children?.()}
116
+ {@render content()}
93
117
  </button>
94
118
  {/if}
@@ -64,6 +64,7 @@ export type ButtonSize = VariantProps<typeof buttonVariants>["size"];
64
64
  export type ButtonProps = WithElementRef<HTMLButtonAttributes> & WithElementRef<HTMLAnchorAttributes> & {
65
65
  variant?: ButtonVariant;
66
66
  size?: ButtonSize;
67
+ loading?: boolean;
67
68
  };
68
69
  declare const Button: import("svelte").Component<ButtonProps, {}, "ref">;
69
70
  type Button = ReturnType<typeof Button>;