From ef4270278867f336e37fc61b25cde03caced30e1 Mon Sep 17 00:00:00 2001 From: Sal Date: Tue, 25 Nov 2025 10:18:09 -0500 Subject: [PATCH 01/44] shine changes in classic --- .../input_textarea/input_textarea.less | 30 ++++--------------- packages/stacks-docs/_data/inputs.json | 16 ++-------- 2 files changed, 9 insertions(+), 37 deletions(-) diff --git a/packages/stacks-classic/lib/components/input_textarea/input_textarea.less b/packages/stacks-classic/lib/components/input_textarea/input_textarea.less index b023847389..b2d9aca845 100644 --- a/packages/stacks-classic/lib/components/input_textarea/input_textarea.less +++ b/packages/stacks-classic/lib/components/input_textarea/input_textarea.less @@ -8,7 +8,7 @@ --_in-fs: var(--fs-body1); --_in-o: unset; --_in-px: 0.7em; - --_in-py: 0.6em; + --_in-py: var(--su8); --_in-placeholder-fc: var(--black-300); // CONTEXTUAL STYLES @@ -56,29 +56,19 @@ // Sizes &&__sm { .size-styles(sm; in; @styles: fs); + --_in-py: calc(var(--su6) - var(--su1)); // 5px } - &&__md { + &&__lg { @supports (-webkit-overflow-scrolling: touch) { --_in-fs: calc(var(--su-static16) + var(--su-static1)); // 17px --_in-py: 0.4em; } .size-styles(md; in; @styles: br, fs); + --_in-py: calc(var(--su8) + var(--su1)); // 9px } - - &&__lg { - .size-styles(lg; in; @styles: br, fs); - --_in-px: 0.6em; - --_in-py: 0.45em; - } - - &&__xl { - .size-styles(xl; in; @styles: br, fs); - --_in-px: 0.5em; - --_in-py: 0.4em; - } - + // CHILD ELEMENTS .webkit-autofill(); @@ -112,7 +102,7 @@ font-size: var(--_in-fs); opacity: var(--_in-o); padding: var(--_in-py) var(--_in-px) var(--_in-py) var(--_in-pl, var(--_in-px)); - + line-height: var(--lh-md); -webkit-appearance: none; // Removes shadows we don't want in mobile Safari font-family: inherit; margin: 0; // A guard against Core's default margins @@ -123,10 +113,6 @@ .input-states({ padding-right: var(--su32); }); - - &&__md { - --_in-py: 0.5em; - } } .s-textarea { @@ -134,10 +120,6 @@ padding-right: var(--su48); }); - &&__md { - --_in-py: 0.72em; - } - ~ .s-input-icon { right: 1.5em; top: 1.5em; diff --git a/packages/stacks-docs/_data/inputs.json b/packages/stacks-docs/_data/inputs.json index 4eaf7b1c18..b0456905de 100644 --- a/packages/stacks-docs/_data/inputs.json +++ b/packages/stacks-docs/_data/inputs.json @@ -71,28 +71,18 @@ "sizes": [ { "name": "Small", - "size": "12px", + "size": "13px", "class": "s-input__sm" }, { "name": "Default", - "size": "13px", + "size": "14px", "class": "N/A" }, - { - "name": "Medium", - "size": "17px", - "class": "s-input__md" - }, { "name": "Large", - "size": "21px", + "size": "18px", "class": "s-input__lg" - }, - { - "name": "Extra Large", - "size": "27px", - "class": "s-input__xl" } ] }, From 29ad4f5b428f381c6cc8985faf484078462d7169 Mon Sep 17 00:00:00 2001 From: Sal Date: Tue, 25 Nov 2025 10:38:29 -0500 Subject: [PATCH 02/44] svelte updates --- .../src/components/TextInput/TextInput.stories.svelte | 2 +- .../stacks-svelte/src/components/TextInput/TextInput.svelte | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/stacks-svelte/src/components/TextInput/TextInput.stories.svelte b/packages/stacks-svelte/src/components/TextInput/TextInput.stories.svelte index e3d0b9f183..ef6f39a782 100644 --- a/packages/stacks-svelte/src/components/TextInput/TextInput.stories.svelte +++ b/packages/stacks-svelte/src/components/TextInput/TextInput.stories.svelte @@ -4,7 +4,7 @@ import type { FillSide, Size, State, Type } from "./TextInput.svelte"; const TextInputFillSides: FillSide[] = ["prepend", "append"]; - const TextInputSizes: Size[] = ["", "sm", "md", "lg", "xl"]; + const TextInputSizes: Size[] = ["", "sm", "lg"]; const TextInputTypes: Type[] = [ "credit-card", "date", diff --git a/packages/stacks-svelte/src/components/TextInput/TextInput.svelte b/packages/stacks-svelte/src/components/TextInput/TextInput.svelte index 66fd467a27..2821e23dd1 100644 --- a/packages/stacks-svelte/src/components/TextInput/TextInput.svelte +++ b/packages/stacks-svelte/src/components/TextInput/TextInput.svelte @@ -1,6 +1,6 @@ + + + + +
+ {#each [false, true] as hideLabel (hideLabel)} +
+ +
+ {/each} +
+
+ + +
+
+ +
+
+ +
+
+
diff --git a/packages/stacks-svelte/src/components/TextArea/TextArea.svelte b/packages/stacks-svelte/src/components/TextArea/TextArea.svelte new file mode 100644 index 0000000000..4aaa2690d2 --- /dev/null +++ b/packages/stacks-svelte/src/components/TextArea/TextArea.svelte @@ -0,0 +1,187 @@ + + + + +
+ + + {#if $$slots.description} + +

+ +

+ {/if} + +
+
+ - @Svg.Check.With("s-input-icon") + @Svg.Checkmark.With("s-input-icon")

Thanks for providing a description.

From d3acbc2fe344bc354e49e901b67c02ea7929c9ce Mon Sep 17 00:00:00 2001 From: Sal Date: Wed, 26 Nov 2025 15:52:49 -0500 Subject: [PATCH 22/44] Create afraid-cheetahs-fetch.md --- .changeset/afraid-cheetahs-fetch.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/afraid-cheetahs-fetch.md diff --git a/.changeset/afraid-cheetahs-fetch.md b/.changeset/afraid-cheetahs-fetch.md new file mode 100644 index 0000000000..66734ec499 --- /dev/null +++ b/.changeset/afraid-cheetahs-fetch.md @@ -0,0 +1,10 @@ +--- +"@stackoverflow/stacks": minor +"@stackoverflow/stacks-svelte": minor +--- + +feat(textarea): new SHINE styles and Svelte component + +BREAKING CHANGES: +* `s-input__md` removed +* `s-input__xl` removed From 0bc83748e86de42e60f1790e3eec4dd403327fe1 Mon Sep 17 00:00:00 2001 From: Sal Date: Wed, 26 Nov 2025 16:26:28 -0500 Subject: [PATCH 23/44] expose textarea component --- packages/stacks-svelte/src/components/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/stacks-svelte/src/components/index.ts b/packages/stacks-svelte/src/components/index.ts index 16863861a4..e551216bc9 100644 --- a/packages/stacks-svelte/src/components/index.ts +++ b/packages/stacks-svelte/src/components/index.ts @@ -28,6 +28,7 @@ export { default as SelectItem } from "./Select/SelectItem.svelte"; export { default as Skeleton } from "./Skeleton/Skeleton.svelte"; export { default as Spinner } from "./Spinner/Spinner.svelte"; export { default as Tag } from "./Tag/Tag.svelte"; +export { default as TextArea } from "./TextArea/TextArea.svelte"; export { default as TextInput } from "./TextInput/TextInput.svelte"; export { default as Toaster, showToast, hideToast } from "./Toast/Toast.svelte"; export { default as UserCard } from "./UserCard/UserCard.svelte"; From 3f51599dc881c3a2642166782a5609a90f17506e Mon Sep 17 00:00:00 2001 From: Sal Date: Wed, 26 Nov 2025 16:28:18 -0500 Subject: [PATCH 24/44] lint --- .../src/components/TextArea/TextArea.stories.svelte | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/stacks-svelte/src/components/TextArea/TextArea.stories.svelte b/packages/stacks-svelte/src/components/TextArea/TextArea.stories.svelte index e46effc97b..3b8ed574f6 100644 --- a/packages/stacks-svelte/src/components/TextArea/TextArea.stories.svelte +++ b/packages/stacks-svelte/src/components/TextArea/TextArea.stories.svelte @@ -31,7 +31,15 @@ }); - +
From 7c9d70d2079288f9674dc8896b5e09d6a7edc510 Mon Sep 17 00:00:00 2001 From: Sal Date: Tue, 2 Dec 2025 09:47:41 -0500 Subject: [PATCH 25/44] PR feedback --- .changeset/lemon-coins-chew.md | 1 + packages/stacks-docs/_data/site-navigation.json | 3 ++- .../src/components/TextInput/TextInput.svelte | 13 ------------- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/.changeset/lemon-coins-chew.md b/.changeset/lemon-coins-chew.md index 76717e5504..cf001c66e4 100644 --- a/.changeset/lemon-coins-chew.md +++ b/.changeset/lemon-coins-chew.md @@ -9,3 +9,4 @@ BREAKING CHANGES: * `s-input__md` removed * `s-input__xl` removed * Nested input styles slightly updated +* `optional` and `i18nOptionalText` attributes removed from TextInput Svelte component diff --git a/packages/stacks-docs/_data/site-navigation.json b/packages/stacks-docs/_data/site-navigation.json index a34129e250..787a002741 100644 --- a/packages/stacks-docs/_data/site-navigation.json +++ b/packages/stacks-docs/_data/site-navigation.json @@ -181,7 +181,8 @@ }, { "title": "Inputs", - "url": "/product/components/inputs/" + "url": "/product/components/inputs/", + "new": true }, { "title": "Labels", diff --git a/packages/stacks-svelte/src/components/TextInput/TextInput.svelte b/packages/stacks-svelte/src/components/TextInput/TextInput.svelte index 2821e23dd1..3e945f9224 100644 --- a/packages/stacks-svelte/src/components/TextInput/TextInput.svelte +++ b/packages/stacks-svelte/src/components/TextInput/TextInput.svelte @@ -65,12 +65,6 @@ */ export let name: string | undefined = undefined; - /** - * Shows optional label status - * @type {boolean} - */ - export let optional: boolean = false; - /** * Placeholder text for the input * @type {string} @@ -114,11 +108,6 @@ let className = ""; export { className as class }; - /** - * Localized translation for the optional label status text - */ - export let i18nOptionalText: string | undefined = undefined; - /** * Localized translation for the required label status text */ @@ -154,8 +143,6 @@ {size} {required} {i18nRequiredText} - {optional} - {i18nOptionalText} > {label} From 529c43178f747ea533eec00dca36eefe4dd87985 Mon Sep 17 00:00:00 2001 From: Sal Date: Tue, 2 Dec 2025 09:56:41 -0500 Subject: [PATCH 26/44] fix tests --- .../components/TextInput/TextInput.test.ts | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/packages/stacks-svelte/src/components/TextInput/TextInput.test.ts b/packages/stacks-svelte/src/components/TextInput/TextInput.test.ts index 727c48a568..2959e1db05 100644 --- a/packages/stacks-svelte/src/components/TextInput/TextInput.test.ts +++ b/packages/stacks-svelte/src/components/TextInput/TextInput.test.ts @@ -89,15 +89,6 @@ describe("TextInput", () => { ); }); - it('should render the "optional" label status', () => { - render(TextInput, { - id: "example-input", - label: "example label", - optional: true, - }); - expect(screen.getByText("Optional")).to.have.class("s-label--status"); - }); - it('should render the "required" label status', () => { render(TextInput, { id: "example-input", @@ -339,14 +330,4 @@ describe("TextInput", () => { const requiredSymbol = screen.getByText("*"); expect(requiredSymbol).to.have.attr("title", "Obbligatorio"); }); - - it("should localize the optional label status text when dedicated prop is specified", () => { - render(TextInput, { - id: "example-input", - label: "example label", - optional: true, - i18nOptionalText: "Facoltativo", - }); - expect(screen.getByText("Facoltativo")).to.exist; - }); }); From fd3dda7b636d6911dbf7555e456396e5a00f8d5e Mon Sep 17 00:00:00 2001 From: Sal Date: Tue, 2 Dec 2025 10:03:10 -0500 Subject: [PATCH 27/44] fix min-height --- .../lib/components/input_textarea/input_textarea.less | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/stacks-classic/lib/components/input_textarea/input_textarea.less b/packages/stacks-classic/lib/components/input_textarea/input_textarea.less index bc0a404eae..ca7e77b65c 100644 --- a/packages/stacks-classic/lib/components/input_textarea/input_textarea.less +++ b/packages/stacks-classic/lib/components/input_textarea/input_textarea.less @@ -13,7 +13,7 @@ --_in-px: calc(var(--su12) - var(--su1)); // 11px --_in-py: var(--su8); --_in-placeholder-fc: var(--black-300); - --_in-min-h: unset; + --_te-hmn: unset; } .s-input, @@ -89,7 +89,7 @@ font-size: var(--_in-fs); line-height: var(--_in-lh); padding: var(--_in-py) var(--_in-px) var(--_in-py) var(--_in-pl, var(--_in-px)); - + min-height: var(--_te-hmn); align-items: center; border-radius: var(--br-md); display: flex; @@ -128,14 +128,14 @@ }); --_in-py: var(--su8); - --_in-min-h: calc(var(--su32) + var(--su4)); // 36px + --_te-hmn: calc(var(--su32) + var(--su4)); // 36px &&__sm { - --_in-min-h: calc(var(--su32) - var(--su4)); // 28px + --_te-hmn: calc(var(--su32) - var(--su4)); // 28px } &&__lg { - --_in-min-h: calc(var(--su48) - var(--su4)); // 44px + --_te-hmn: calc(var(--su48) - var(--su4)); // 44px } ~ .s-input-icon { From 2e1d46d5b0a268e71d89d381d62a33d549dff898 Mon Sep 17 00:00:00 2001 From: Sal Date: Tue, 2 Dec 2025 10:03:27 -0500 Subject: [PATCH 28/44] add *new* label in navigation --- packages/stacks-docs/_data/site-navigation.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/stacks-docs/_data/site-navigation.json b/packages/stacks-docs/_data/site-navigation.json index 787a002741..9025e7277c 100644 --- a/packages/stacks-docs/_data/site-navigation.json +++ b/packages/stacks-docs/_data/site-navigation.json @@ -195,7 +195,8 @@ }, { "title": "Textarea", - "url": "/product/components/textarea/" + "url": "/product/components/textarea/", + "new": true } ] }, From c00d05601390a30c55654c1b584bdf92f7ecb930 Mon Sep 17 00:00:00 2001 From: Sal Date: Tue, 2 Dec 2025 10:24:41 -0500 Subject: [PATCH 29/44] add accessibility section --- packages/stacks-docs/product/components/textarea.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/stacks-docs/product/components/textarea.html b/packages/stacks-docs/product/components/textarea.html index c56ed34f50..99c67c97e2 100644 --- a/packages/stacks-docs/product/components/textarea.html +++ b/packages/stacks-docs/product/components/textarea.html @@ -28,6 +28,14 @@
+
+ {% header "h2", "Accessibility" %} +

+ It is recommended to follow the same accessibility guidance as the Input component. + Including marking Textarea's as required via the .s-required-symbol class. +

+
+
{% header "h2", "Validation states" %}

Validation states provides the user feedback based on their interaction (or lack of interaction) with a textarea. These styles are applied by applying the appropriate class to the wrapping parent container.

From 80b5944a41ae33fed93d6a23d43e436cda065907 Mon Sep 17 00:00:00 2001 From: Sal Date: Tue, 2 Dec 2025 10:38:27 -0500 Subject: [PATCH 30/44] remove `optiona`l props per pr feedback --- .../src/components/TextArea/TextArea.svelte | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/packages/stacks-svelte/src/components/TextArea/TextArea.svelte b/packages/stacks-svelte/src/components/TextArea/TextArea.svelte index 4aaa2690d2..b2f99acea0 100644 --- a/packages/stacks-svelte/src/components/TextArea/TextArea.svelte +++ b/packages/stacks-svelte/src/components/TextArea/TextArea.svelte @@ -42,12 +42,6 @@ */ export let name: string | undefined = undefined; - /** - * Shows optional label status - * @type {boolean} - */ - export let optional: boolean = false; - /** * Placeholder text for the input * @type {string} @@ -85,11 +79,6 @@ let className = ""; export { className as class }; - /** - * Localized translation for the optional label status text - */ - export let i18nOptionalText: string | undefined = undefined; - /** * Localized translation for the required label status text */ @@ -125,8 +114,6 @@ {size} {required} {i18nRequiredText} - {optional} - {i18nOptionalText} > {label} From 27683cfddfaa6d8d169d6a19e31e16b351aaa5a7 Mon Sep 17 00:00:00 2001 From: Sal Date: Tue, 2 Dec 2025 10:45:32 -0500 Subject: [PATCH 31/44] remove superfluous wrapper div --- .../src/components/TextArea/TextArea.svelte | 74 +++++++++---------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/packages/stacks-svelte/src/components/TextArea/TextArea.svelte b/packages/stacks-svelte/src/components/TextArea/TextArea.svelte index b2f99acea0..dcf5fb3e99 100644 --- a/packages/stacks-svelte/src/components/TextArea/TextArea.svelte +++ b/packages/stacks-svelte/src/components/TextArea/TextArea.svelte @@ -125,44 +125,42 @@

{/if} -
-
- +
{% endhighlight %}
- +
- +
@@ -55,7 +55,7 @@ {% assign state = item.validation %} {% for class in state %} - {{ class.class }} + {{ class.class }} {{ class.applies }} {{ class.description }} @@ -70,22 +70,22 @@
{% highlight html %}
- +
- + @Svg.Alert.With("s-input-icon")
-

Consider entering a description to help us better help you.

+

Consider entering a description to help us better help you.

{% endhighlight %}
- +
- + {% icon "Alert", "s-input-icon" %}
-

Consider entering a description to help us better help you.

+

Consider entering a description to help us better help you.

@@ -94,22 +94,22 @@
{% highlight html %}
- +
- + @Svg.AlertCircle.With("s-input-icon")
-

A description must be provided.

+

A description must be provided.

{% endhighlight %}
- +
- + {% icon "AlertCircle", "s-input-icon" %}
-

A description must be provided.

+

A description must be provided.

@@ -118,22 +118,22 @@
{% highlight html %}
- +
- + @Svg.Checkmark.With("s-input-icon")
-

Thanks for providing a description.

+

Thanks for providing a description.

{% endhighlight %}
- +
- + {% icon "Check", "s-input-icon" %}
-

Thanks for providing a description.

+

Thanks for providing a description.

From 683e040abbc3fda5882eb0c0cd5fe6edb8c70ef7 Mon Sep 17 00:00:00 2001 From: Sal Date: Tue, 2 Dec 2025 13:06:40 -0500 Subject: [PATCH 36/44] upgrade textinput & textarea to Svelte 5 style --- .../TextArea/TextArea.stories.svelte | 37 ++- .../src/components/TextArea/TextArea.svelte | 188 +++++++------- .../TextInput/TextInput.stories.svelte | 47 ++-- .../src/components/TextInput/TextInput.svelte | 234 ++++++++++-------- 4 files changed, 274 insertions(+), 232 deletions(-) diff --git a/packages/stacks-svelte/src/components/TextArea/TextArea.stories.svelte b/packages/stacks-svelte/src/components/TextArea/TextArea.stories.svelte index 3b8ed574f6..bd60274376 100644 --- a/packages/stacks-svelte/src/components/TextArea/TextArea.stories.svelte +++ b/packages/stacks-svelte/src/components/TextArea/TextArea.stories.svelte @@ -81,7 +81,9 @@ label={`${state || "default"} input`} {state} > - {state || "default"} message + {#snippet message()} + {state || "default"} message + {/snippet}
{/each} @@ -90,21 +92,17 @@
-
-
@@ -135,20 +133,21 @@
- + +

The examples below show all the snippets this component supports.

-
-
diff --git a/packages/stacks-svelte/src/components/TextArea/TextArea.svelte b/packages/stacks-svelte/src/components/TextArea/TextArea.svelte index e5c317598c..c39634e094 100644 --- a/packages/stacks-svelte/src/components/TextArea/TextArea.svelte +++ b/packages/stacks-svelte/src/components/TextArea/TextArea.svelte @@ -12,79 +12,97 @@ IconCheckmark, } from "@stackoverflow/stacks-icons-legacy/icons"; - /** - * `id` attribute of the text input - * @type {string} - */ - export let id: string; - - /** - * The label associated with the input - * @type {string} - */ - export let label: string; - - /** - * Sets the disabled state of the input - * @type {boolean} - */ - export let disabled: boolean = false; - - /** - * The visiblity of the label element - * @type {boolean} - */ - export let hideLabel: boolean = false; - - /** - * Name attribute of the textarea - * @type {string | undefined} - */ - export let name: string | undefined = undefined; - - /** - * Placeholder text for the input - * @type {string} - */ - export let placeholder: string = ""; - - /** - * Sets the readonly state of the input - * @type {boolean} - */ - export let readonly: boolean = false; - - /** - * Make the input required and show required label status - * @type {boolean} - */ - export let required: boolean = false; - - /** - * The size of the text input - * @type {"" | "sm" | "lg"} Size - */ - export let size: Size = ""; - - /** - * The size of the text input - * @type {"" | "error" | "success" | "warning"} State - */ - export let state: State = ""; - - /** - * Additional CSS classes added to the underlying HTML input element - * @type {string} - */ - let className = ""; - export { className as class }; - - /** - * Localized translation for the required label status text - */ - export let i18nRequiredText: string | undefined = undefined; - - $: classes = getClasses(className, size); + interface Props { + /** + * `id` attribute of the text input + * @type {string} + */ + id: string; + /** + * The label associated with the input + * @type {string} + */ + label: string; + /** + * Sets the disabled state of the input + * @type {boolean} + */ + disabled?: boolean; + /** + * The visiblity of the label element + * @type {boolean} + */ + hideLabel?: boolean; + /** + * Name attribute of the textarea + * @type {string | undefined} + */ + name?: string | undefined; + /** + * Placeholder text for the input + * @type {string} + */ + placeholder?: string; + /** + * Sets the readonly state of the input + * @type {boolean} + */ + readonly?: boolean; + /** + * Make the input required and show required label status + * @type {boolean} + */ + required?: boolean; + /** + * The size of the text input + * @type {"" | "sm" | "lg"} Size + */ + size?: Size; + /** + * The size of the text input + * @type {"" | "error" | "success" | "warning"} State + */ + state?: State; + + /** + * Additional CSS classes added to the underlying HTML input element + * @type {string} + */ + class?: string; + /** + * Localized translation for the required label status text + */ + i18nRequiredText?: string | undefined; + + /** + * Optional description snippet rendered between the label and input. + */ + description?: import('svelte').Snippet; + + /** + * Optional message snippet rendered after the input. + */ + message?: import('svelte').Snippet; + } + + let { + id, + label, + disabled = false, + hideLabel = false, + name = undefined, + placeholder = "", + readonly = false, + required = false, + size = "", + state = "", + class: className = "", + i18nRequiredText = undefined, + description, + message, + ...rest + }: Props = $props(); + const getClasses = (className: string, size: Size) => { const base = "s-textarea"; @@ -100,6 +118,7 @@ return classes; }; + let classes = $derived(getClasses(className, size));
- {#if $$slots.description} + {#if description}

- + {@render description()}

{/if}
{#if state}
@@ -163,10 +175,10 @@ {/if}
- {#if $$slots.message} + {#if message}

- + {@render message()}

{/if}
diff --git a/packages/stacks-svelte/src/components/TextInput/TextInput.stories.svelte b/packages/stacks-svelte/src/components/TextInput/TextInput.stories.svelte index ef6f39a782..7ea9a8d6cd 100644 --- a/packages/stacks-svelte/src/components/TextInput/TextInput.stories.svelte +++ b/packages/stacks-svelte/src/components/TextInput/TextInput.stories.svelte @@ -66,7 +66,9 @@ label="{fillSide}ed fill" {fillSide} > - {fillSide}ed fill + {#snippet fill()} + {fillSide}ed fill + {/snippet}
{/each} @@ -113,7 +115,9 @@ label={`${state || "default"} input`} {state} > - {state || "default"} message + {#snippet message()} + {state || "default"} message + {/snippet} {/each} @@ -122,21 +126,17 @@
-
- -
+ > + {#snippet description()} + this input has been marked required. + {/snippet} +
@@ -182,25 +182,28 @@
- + +

The examples below show all the snippets this component supports.

- - - This TextInput includes a description slot. - + + {#snippet description()} + This TextInput includes a description snippet. + {/snippet}
- - - This TextInput includes a message slot. - + + {#snippet message()} + This TextInput includes a message snippet. + {/snippet}
- - https:// + + {#snippet fill()} + https:// + {/snippet}
diff --git a/packages/stacks-svelte/src/components/TextInput/TextInput.svelte b/packages/stacks-svelte/src/components/TextInput/TextInput.svelte index 3e945f9224..7cb231036c 100644 --- a/packages/stacks-svelte/src/components/TextInput/TextInput.svelte +++ b/packages/stacks-svelte/src/components/TextInput/TextInput.svelte @@ -29,91 +29,125 @@ IconSearch, } from "@stackoverflow/stacks-icons-legacy/icons"; - /** - * `id` attribute of the text input - * @type {string} - */ - export let id: string; - - /** - * The label associated with the input - * @type {string} - */ - export let label: string; - - /** - * Sets the disabled state of the input - * @type {boolean} - */ - export let disabled: boolean = false; - - /** - * The visiblity of the label element - * @type {boolean} - */ - export let hideLabel: boolean = false; - - /** - * Where to place the input fill element - * @type {"prepend" | "append"} FillSide - */ - export let fillSide: FillSide = "prepend"; - - /** - * Name attribute of the input - * @type {string | undefined} - */ - export let name: string | undefined = undefined; - - /** - * Placeholder text for the input - * @type {string} - */ - export let placeholder: string = ""; - - /** - * Sets the readonly state of the input - * @type {boolean} - */ - export let readonly: boolean = false; - - /** - * Make the input required and show required label status - * @type {boolean} - */ - export let required: boolean = false; - - /** - * The size of the text input - * @type {"" | "sm" | "lg"} Size - */ - export let size: Size = ""; - - /** - * The size of the text input - * @type {"" | "error" | "success" | "warning"} State - */ - export let state: State = ""; - - /** - * The type of the text input - * @type {"credit-card" | "date" | "datetime-local" | "email" | "month" | "number" | "password" | "search" | "tel" | "text" | "time" | "url" | "week"} - */ - export let type: Type = "text"; - - /** - * Additional CSS classes added to the underlying HTML input element - * @type {string} - */ - let className = ""; - export { className as class }; - - /** - * Localized translation for the required label status text - */ - export let i18nRequiredText: string | undefined = undefined; - - $: classes = getClasses(className, size); + interface Props { + /** + * `id` attribute of the text input + * @type {string} + */ + id: string; + + /** + * The label associated with the input + * @type {string} + */ + label: string; + + /** + * Sets the disabled state of the input + * @type {boolean} + */ + disabled?: boolean; + + /** + * The visiblity of the label element + * @type {boolean} + */ + hideLabel?: boolean; + + /** + * Where to place the input fill element + * @type {"prepend" | "append"} FillSide + */ + fillSide?: FillSide; + + /** + * Name attribute of the input + * @type {string | undefined} + */ + name?: string | undefined; + /** + * Placeholder text for the input + * @type {string} + */ + placeholder?: string; + + /** + * Sets the readonly state of the input + * @type {boolean} + */ + readonly?: boolean; + + /** + * Make the input required and show required label status + * @type {boolean} + */ + required?: boolean; + + /** + * The size of the text input + * @type {"" | "sm" | "lg"} Size + */ + size?: Size; + + /** + * The size of the text input + * @type {"" | "error" | "success" | "warning"} State + */ + state?: State; + + /** + * The type of the text input + * @type {"credit-card" | "date" | "datetime-local" | "email" | "month" | "number" | "password" | "search" | "tel" | "text" | "time" | "url" | "week"} + */ + type?: Type; + + /** + * Additional CSS classes added to the underlying HTML input element + * @type {string} + */ + class?: string; + + /** + * Localized translation for the required label status text + */ + i18nRequiredText?: string | undefined; + + /** + * Optional description snippet rendered between the label and input. + */ + description?: import("svelte").Snippet; + + /** + * Optional fill snippet rendered either before or after the input based on the value of `fillSide`. + */ + fill?: import("svelte").Snippet; + + /** + * Optional message snippet rendered after the input. + */ + message?: import("svelte").Snippet; + } + + let { + id, + label, + disabled = false, + hideLabel = false, + fillSide = "prepend", + name = undefined, + placeholder = "", + readonly = false, + required = false, + size = "", + state = "", + type = "text", + class: className = "", + i18nRequiredText = undefined, + description, + fill, + message, + ...rest + }: Props = $props(); const getClasses = (className: string, size: Size) => { const base = "s-input"; @@ -129,6 +163,7 @@ return classes; }; + let classes = $derived(getClasses(className, size));
- {#if $$slots.description} + {#if description}

- + {@render description()}

{/if}
- {#if $$slots.fill} + {#if fill}
- + {@render fill()}
{/if} @@ -184,31 +219,24 @@ {#if state} @@ -225,10 +253,10 @@
- {#if $$slots.message} + {#if message}

- + {@render message()}

{/if} From b51bb78b8d50202ce8fc12d55f90571bfbd140f1 Mon Sep 17 00:00:00 2001 From: Sal Date: Tue, 2 Dec 2025 13:13:19 -0500 Subject: [PATCH 37/44] lint --- .../components/TextArea/TextArea.stories.svelte | 9 ++++++--- .../src/components/TextArea/TextArea.svelte | 9 ++++----- .../TextInput/TextInput.stories.svelte | 17 ++++++++++------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/packages/stacks-svelte/src/components/TextArea/TextArea.stories.svelte b/packages/stacks-svelte/src/components/TextArea/TextArea.stories.svelte index bd60274376..2483f88fe4 100644 --- a/packages/stacks-svelte/src/components/TextArea/TextArea.stories.svelte +++ b/packages/stacks-svelte/src/components/TextArea/TextArea.stories.svelte @@ -82,7 +82,7 @@ {state} > {#snippet message()} - {state || "default"} message + {state || "default"} message {/snippet} @@ -100,7 +100,7 @@ required > {#snippet description()} - this input has been marked required. + this input has been marked required. {/snippet} @@ -137,7 +137,10 @@

The examples below show all the snippets this component supports.

- + > {#if state}
diff --git a/packages/stacks-svelte/src/components/TextInput/TextInput.stories.svelte b/packages/stacks-svelte/src/components/TextInput/TextInput.stories.svelte index 7ea9a8d6cd..2c052f2d9f 100644 --- a/packages/stacks-svelte/src/components/TextInput/TextInput.stories.svelte +++ b/packages/stacks-svelte/src/components/TextInput/TextInput.stories.svelte @@ -67,7 +67,7 @@ {fillSide} > {#snippet fill()} - {fillSide}ed fill + {fillSide}ed fill {/snippet}
@@ -116,7 +116,7 @@ {state} > {#snippet message()} - {state || "default"} message + {state || "default"} message {/snippet}
@@ -134,7 +134,7 @@ required > {#snippet description()} - this input has been marked required. + this input has been marked required. {/snippet}
@@ -186,23 +186,26 @@

The examples below show all the snippets this component supports.

- + {#snippet description()} - This TextInput includes a description snippet. + This TextInput includes a description snippet. {/snippet}
{#snippet message()} - This TextInput includes a message snippet. + This TextInput includes a message snippet. {/snippet}
{#snippet fill()} - https:// + https:// {/snippet}
From 7d8d4d580f8631b8f1185031e8673fff395af44f Mon Sep 17 00:00:00 2001 From: Sal Date: Tue, 2 Dec 2025 13:34:06 -0500 Subject: [PATCH 38/44] fix lint --- packages/stacks-svelte/src/components/TextArea/TextArea.svelte | 3 ++- .../stacks-svelte/src/components/TextInput/TextInput.svelte | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/stacks-svelte/src/components/TextArea/TextArea.svelte b/packages/stacks-svelte/src/components/TextArea/TextArea.svelte index c1989d675b..165974fcba 100644 --- a/packages/stacks-svelte/src/components/TextArea/TextArea.svelte +++ b/packages/stacks-svelte/src/components/TextArea/TextArea.svelte @@ -4,6 +4,7 @@