Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
ef42702
shine changes in classic
mukunku Nov 25, 2025
29ad4f5
svelte updates
mukunku Nov 25, 2025
0de35b8
a11y tweak
mukunku Nov 25, 2025
7a9d170
remove webkit overrides for testing
mukunku Nov 25, 2025
07c7e7d
fix lint
mukunku Nov 25, 2025
1e16a33
Create lemon-coins-chew.md
mukunku Nov 25, 2025
c3f42ad
add back zoom webkit fix
mukunku Nov 25, 2025
c445902
Merge branch 'sal/SPARK-68' of https://github.com/StackExchange/Stack…
mukunku Nov 25, 2025
5850d2a
implement #2064 into v3
mukunku Nov 25, 2025
3501ca0
Revert "implement #2064 into v3"
mukunku Nov 25, 2025
19a44ea
remove webkit override again
mukunku Nov 25, 2025
23b7197
consistent heights
mukunku Nov 25, 2025
593bb18
update baseline
mukunku Nov 25, 2025
5b53f97
Merge branch 'beta' into sal/SPARK-68
mukunku Nov 25, 2025
9c53bf6
adjust nested inputs heights
mukunku Nov 25, 2025
2d398b2
baseline
mukunku Nov 25, 2025
31ccf40
Various input sizing, layout, docs tweaks
dancormier Nov 25, 2025
a32288d
Input tweaks (#2073)
dancormier Nov 26, 2025
49a246d
Merge branch 'beta' into sal/SPARK-68
mukunku Nov 26, 2025
24d6dd0
Merge branch 'sal/SPARK-68' into sal/SPARK-81
mukunku Nov 26, 2025
1ce9645
stacks classic and docs updates
mukunku Nov 26, 2025
204531d
update baseline
mukunku Nov 26, 2025
6345440
create textarea svelte component
mukunku Nov 26, 2025
509a2c9
update figma link
mukunku Nov 26, 2025
a29374e
Merge branch 'beta' into sal/SPARK-68
mukunku Nov 26, 2025
ececbf2
set figma and svelte links
mukunku Nov 26, 2025
33c0ecf
Merge branch 'sal/SPARK-68' into sal/SPARK-81
mukunku Nov 26, 2025
d3acbc2
Create afraid-cheetahs-fetch.md
mukunku Nov 26, 2025
0bc8374
expose textarea component
mukunku Nov 26, 2025
3f51599
lint
mukunku Nov 26, 2025
f5007e5
Merge branch 'beta' into sal/SPARK-68
mukunku Dec 1, 2025
7c9d70d
PR feedback
mukunku Dec 2, 2025
529c431
fix tests
mukunku Dec 2, 2025
7952c81
Merge branch 'sal/SPARK-68' into sal/SPARK-81
mukunku Dec 2, 2025
fd3dda7
fix min-height
mukunku Dec 2, 2025
2e1d46d
add *new* label in navigation
mukunku Dec 2, 2025
c00d056
add accessibility section
mukunku Dec 2, 2025
80b5944
remove `optiona`l props per pr feedback
mukunku Dec 2, 2025
27683cf
remove superfluous wrapper div
mukunku Dec 2, 2025
59eaf1b
Merge branch 'beta' into sal/SPARK-81
mukunku Dec 2, 2025
f697e47
make min-height textarea specific
mukunku Dec 2, 2025
19001ec
lint
mukunku Dec 2, 2025
fda2ebe
fix tests
mukunku Dec 2, 2025
f08863c
remove all usages of flex--item
mukunku Dec 2, 2025
683e040
upgrade textinput & textarea to Svelte 5 style
mukunku Dec 2, 2025
b51bb78
lint
mukunku Dec 2, 2025
7d8d4d5
fix lint
mukunku Dec 2, 2025
4a899be
Create dirty-snails-obey.md
mukunku Dec 2, 2025
9e60b2e
upgrade migration guide
mukunku Dec 2, 2025
889087f
fix textarea tests
mukunku Dec 2, 2025
f9f7355
Merge branch 'beta' into sal/SPARK-28
mukunku Dec 3, 2025
98cc092
re-lint
mukunku Dec 3, 2025
16bb893
move snippet type declarations to the top
mukunku Dec 3, 2025
a18411e
lint
mukunku Dec 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/dirty-snails-obey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@stackoverflow/stacks-svelte": patch
---

chore(textinput/textarea): upgrade to Svelte 5 syntax

BREAKING CHANGES:
* The message, description, and fill slots have been replaced with snippets.
9 changes: 9 additions & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
- The variant `Muted` has been removed, `Tonal` has been added
- `s-btn__md` has been removed, `s-btn__lg` has been added

#### Inputs
- `s-input__md` removed
- `s-input__xl` removed
- **Nested inputs** html will require slight tweaking on consumers' side

#### Menu

The menu component has been updated to use new class names and structure. The following changes are breaking:
Expand Down Expand Up @@ -105,6 +110,10 @@ The menu component has been updated to use new class names and structure. The fo
- `.s-tag__xs` removed
- `.s-tag__md` removed

#### Textarea
- `s-textarea__md` removed
- `s-textarea__xl` removed

# Migrating from Stacks Svelte v0 to v1

## Breaking changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@
label={`${state || "default"} input`}
{state}
>
<span slot="message">{state || "default"} message</span>
{#snippet message()}
<span>{state || "default"} message</span>
{/snippet}
</TextArea>
</div>
{/each}
Expand All @@ -90,21 +92,17 @@

<Story name="Status" asChild>
<div class="d-grid g16">
<div class="d-flex fd-column">
<TextArea
id="optional-status-input"
placeholder="Age"
label="optional input"
optional
/>
</div>
<div class="d-flex fd-column">
<TextArea
id="required-status-input"
placeholder="Full name"
label="required input"
required
/>
>
{#snippet description()}
<span>this input has been marked required.</span>
{/snippet}
</TextArea>
</div>
</div>
</Story>
Expand Down Expand Up @@ -135,20 +133,24 @@
</div>
</Story>

<Story name="Slots" asChild>
<Story name="Snippets" asChild>
<p>The examples below show all the snippets this component supports.</p>
<div class="d-grid g16">
<div class="d-flex fd-column">
<TextArea id="description-slot-input" label="Description slot">
<span slot="description">
This TextArea includes a description slot.
</span>
<TextArea
id="description-snippet-input"
label="Description snippet"
>
{#snippet description()}
<span>This TextArea includes a description snippet.</span>
{/snippet}
</TextArea>
</div>
<div class="d-flex fd-column">
<TextArea id="message-slot-input" label="Message slot">
<span slot="message">
This TextArea includes a message slot.
</span>
<TextArea id="message-snippet-input" label="Message snippet">
{#snippet message()}
<span>This TextArea includes a message snippet.</span>
{/snippet}
</TextArea>
</div>
</div>
Expand Down
189 changes: 101 additions & 88 deletions packages/stacks-svelte/src/components/TextArea/TextArea.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
</script>

<script lang="ts">
import type { HTMLTextareaAttributes } from "svelte/elements";
import type { Snippet } from "svelte";
import Icon from "../Icon/Icon.svelte";
import Label from "../Label/Label.svelte";
import {
Expand All @@ -12,79 +14,96 @@
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 extends Omit<HTMLTextareaAttributes, "size"> {
/**
* `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?: Snippet;

/**
* Optional message snippet rendered after the input.
*/
message?: 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";
Expand All @@ -100,6 +119,7 @@

return classes;
};
let classes = $derived(getClasses(className, size));
</script>

<div
Expand All @@ -118,19 +138,19 @@
{label}
</Label>

{#if $$slots.description}
{#if description}
<!-- Renders a description between the label and input. -->
<p class="s-description mb0 mtn2" id={`${id}-description`}>
<slot name="description" />
{@render description()}
</p>
{/if}

<div class="ps-relative w100 d-flex">
<textarea
{id}
aria-describedby={$$slots.message
aria-describedby={message
? `${id}-message`
: $$slots.description
: description
? `${id}-description`
: undefined}
aria-invalid={state === "error"}
Expand All @@ -140,15 +160,8 @@
{placeholder}
{readonly}
{required}
{...$$restProps}
on:change
on:input
on:keydown
on:keyup
on:focus
on:blur
on:paste
/>
{...rest}
></textarea>

{#if state}
<div class="s-input-icon">
Expand All @@ -163,10 +176,10 @@
{/if}
</div>

{#if $$slots.message}
{#if message}
<!-- Renders a message after the input. -->
<p class="s-input-message" id={`${id}-message`}>
<slot name="message" />
{@render message()}
</p>
{/if}
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,7 @@ describe("TextArea", () => {
render(TextArea, {
id: "example-input",
label: "example label",
$$slots: {
description: snippet,
},
description: snippet,
});

expect(screen.getByText("test snippet").parentElement).to.have.class(
Expand All @@ -141,9 +139,7 @@ describe("TextArea", () => {
render(TextArea, {
id: "example-input",
label: "example label",
$$slots: {
message: snippet,
},
message: snippet,
});

expect(screen.getByText("test snippet").parentElement).to.have.class(
Expand Down
Loading