@luscii-healthtech/web-ui 61.0.2 → 62.0.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.
@@ -41,11 +41,11 @@ type SharedProps = {
41
41
  * </LabeledRadioCardGroup>
42
42
  * ```
43
43
  *
44
- * Using `children` prop for custom content:
44
+ * Using `children` prop for custom content, rendered as-is:
45
45
  * ```tsx
46
46
  * <LabeledRadioCardGroup>
47
47
  * <LabeledRadioCard name="payment" id="credit" value="credit">
48
- * <Stack axis="y" _gap="base">
48
+ * <Stack as="span" axis="y" _gap="base">
49
49
  * <Text variant="body-base-regular">Credit Card</Text>
50
50
  * <Text variant="body-small-light" color="neutral-secondary">
51
51
  * Pay securely with your card
@@ -60,6 +60,11 @@ export declare const LabeledRadioCard: React.ForwardRefExoticComponent<(Omit<Omi
60
60
  subtitle?: React.ReactNode;
61
61
  leadingIcon?: React.ReactNode;
62
62
  }, "ref"> | Omit<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "children"> & SharedProps & {
63
+ /**
64
+ * Custom content, rendered as-is: lay it out and style it yourself. It's
65
+ * rendered inside a `<label>`, so use phrasing elements (e.g.
66
+ * `<Stack as="span">`).
67
+ */
63
68
  children: React.ReactNode;
64
69
  }, "ref">) & React.RefAttributes<HTMLInputElement>>;
65
70
  export {};
@@ -1,7 +1,34 @@
1
1
  import React from "react";
2
2
  import { type FormFieldSize } from "../../types/general.types.js";
3
3
  import { type TextareaProps } from "./Textarea";
4
- export declare const LabeledTextarea: React.ForwardRefExoticComponent<Omit<TextareaProps, "isDisabled" | "isError"> & {
4
+ /**
5
+ * Form-ready textarea component that wraps {@link Textarea} with a label, helper text,
6
+ * and error text. This is the **recommended component for multi-line text in forms**.
7
+ *
8
+ * Features:
9
+ * - Renders a native `<textarea>` — compatible with `react-hook-form` `register()` directly.
10
+ * - Displays a label above the textarea when provided, linked to the textarea with `htmlFor`.
11
+ * - Shows helper text or error text below the textarea with proper `aria-describedby` wiring.
12
+ * - Automatically toggles error styling and `aria-invalid` when `errorText` is provided.
13
+ * A consumer-supplied `aria-invalid` is kept when there's no `errorText`.
14
+ *
15
+ * When to use:
16
+ * - Use `LabeledTextarea` for notes, messages, descriptions and other free text that can
17
+ * span multiple lines.
18
+ * - For single-line text, use {@link LabeledInput} instead.
19
+ * - If you need a bare textarea without label/helper/error, use {@link Textarea} directly.
20
+ *
21
+ * @example
22
+ * // With react-hook-form
23
+ * <LabeledTextarea
24
+ * label="Message"
25
+ * helperText="The patient will see this message in the app"
26
+ * {...register("message")}
27
+ * />
28
+ *
29
+ * @see {@link Textarea} for the low-level building block without form wiring.
30
+ */
31
+ type Props = Omit<TextareaProps, "isError" | "isDisabled"> & {
5
32
  /**
6
33
  * The visible label, linked to the textarea with `htmlFor`. When omitted, give
7
34
  * the textarea an accessible name with `aria-label` or `aria-labelledby`.
@@ -31,7 +58,13 @@ export declare const LabeledTextarea: React.ForwardRefExoticComponent<Omit<Texta
31
58
  *
32
59
  * By default the field only takes its intrinsic width.
33
60
  */
34
- width?: FormFieldSize | [FormFieldSize, FormFieldSize?, FormFieldSize?, FormFieldSize?, FormFieldSize?];
61
+ width?: FormFieldSize | [
62
+ FormFieldSize,
63
+ FormFieldSize?,
64
+ FormFieldSize?,
65
+ FormFieldSize?,
66
+ FormFieldSize?
67
+ ];
35
68
  /**
36
69
  * When true, the field stretches to fill the full width of its container,
37
70
  * also when the container aligns its children to the start.
@@ -39,4 +72,8 @@ export declare const LabeledTextarea: React.ForwardRefExoticComponent<Omit<Texta
39
72
  * Shorthand for `width="full"`. When both are given, `width` wins.
40
73
  */
41
74
  fullWidth?: boolean;
42
- } & React.RefAttributes<HTMLTextAreaElement>>;
75
+ };
76
+ export declare const LabeledTextarea: (props: Props & {
77
+ ref?: React.Ref<HTMLTextAreaElement>;
78
+ }) => React.JSX.Element;
79
+ export {};
@@ -41,11 +41,11 @@ type SharedProps = {
41
41
  * </LabeledRadioCardGroup>
42
42
  * ```
43
43
  *
44
- * Using `children` prop for custom content:
44
+ * Using `children` prop for custom content, rendered as-is:
45
45
  * ```tsx
46
46
  * <LabeledRadioCardGroup>
47
47
  * <LabeledRadioCard name="payment" id="credit" value="credit">
48
- * <Stack axis="y" _gap="base">
48
+ * <Stack as="span" axis="y" _gap="base">
49
49
  * <Text variant="body-base-regular">Credit Card</Text>
50
50
  * <Text variant="body-small-light" color="neutral-secondary">
51
51
  * Pay securely with your card
@@ -60,6 +60,11 @@ export declare const LabeledRadioCard: React.ForwardRefExoticComponent<(Omit<Omi
60
60
  subtitle?: React.ReactNode;
61
61
  leadingIcon?: React.ReactNode;
62
62
  }, "ref"> | Omit<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "children"> & SharedProps & {
63
+ /**
64
+ * Custom content, rendered as-is: lay it out and style it yourself. It's
65
+ * rendered inside a `<label>`, so use phrasing elements (e.g.
66
+ * `<Stack as="span">`).
67
+ */
63
68
  children: React.ReactNode;
64
69
  }, "ref">) & React.RefAttributes<HTMLInputElement>>;
65
70
  export {};
@@ -1,7 +1,34 @@
1
1
  import React from "react";
2
2
  import { type FormFieldSize } from "../../../types/general.types.js";
3
3
  import { type TextareaProps } from "./Textarea";
4
- export declare const LabeledTextarea: React.ForwardRefExoticComponent<Omit<TextareaProps, "isDisabled" | "isError"> & {
4
+ /**
5
+ * Form-ready textarea component that wraps {@link Textarea} with a label, helper text,
6
+ * and error text. This is the **recommended component for multi-line text in forms**.
7
+ *
8
+ * Features:
9
+ * - Renders a native `<textarea>` — compatible with `react-hook-form` `register()` directly.
10
+ * - Displays a label above the textarea when provided, linked to the textarea with `htmlFor`.
11
+ * - Shows helper text or error text below the textarea with proper `aria-describedby` wiring.
12
+ * - Automatically toggles error styling and `aria-invalid` when `errorText` is provided.
13
+ * A consumer-supplied `aria-invalid` is kept when there's no `errorText`.
14
+ *
15
+ * When to use:
16
+ * - Use `LabeledTextarea` for notes, messages, descriptions and other free text that can
17
+ * span multiple lines.
18
+ * - For single-line text, use {@link LabeledInput} instead.
19
+ * - If you need a bare textarea without label/helper/error, use {@link Textarea} directly.
20
+ *
21
+ * @example
22
+ * // With react-hook-form
23
+ * <LabeledTextarea
24
+ * label="Message"
25
+ * helperText="The patient will see this message in the app"
26
+ * {...register("message")}
27
+ * />
28
+ *
29
+ * @see {@link Textarea} for the low-level building block without form wiring.
30
+ */
31
+ type Props = Omit<TextareaProps, "isError" | "isDisabled"> & {
5
32
  /**
6
33
  * The visible label, linked to the textarea with `htmlFor`. When omitted, give
7
34
  * the textarea an accessible name with `aria-label` or `aria-labelledby`.
@@ -31,7 +58,13 @@ export declare const LabeledTextarea: React.ForwardRefExoticComponent<Omit<Texta
31
58
  *
32
59
  * By default the field only takes its intrinsic width.
33
60
  */
34
- width?: FormFieldSize | [FormFieldSize, FormFieldSize?, FormFieldSize?, FormFieldSize?, FormFieldSize?];
61
+ width?: FormFieldSize | [
62
+ FormFieldSize,
63
+ FormFieldSize?,
64
+ FormFieldSize?,
65
+ FormFieldSize?,
66
+ FormFieldSize?
67
+ ];
35
68
  /**
36
69
  * When true, the field stretches to fill the full width of its container,
37
70
  * also when the container aligns its children to the start.
@@ -39,4 +72,8 @@ export declare const LabeledTextarea: React.ForwardRefExoticComponent<Omit<Texta
39
72
  * Shorthand for `width="full"`. When both are given, `width` wins.
40
73
  */
41
74
  fullWidth?: boolean;
42
- } & React.RefAttributes<HTMLTextAreaElement>>;
75
+ };
76
+ export declare const LabeledTextarea: (props: Props & {
77
+ ref?: React.Ref<HTMLTextAreaElement>;
78
+ }) => React.JSX.Element;
79
+ export {};
@@ -37,6 +37,13 @@ export declare const OverviewLabeledRadioCard: Story;
37
37
  export declare const UsingLabelAndSubtitleProps: Story;
38
38
  export declare const UsingChildrenPropForCustomContent: Story;
39
39
  export declare const SingleColumnWithIcons: Story;
40
+ /**
41
+ * A `ReactNode` passed as `label` or `children` is rendered as-is and fills
42
+ * the card, so you decide its layout: e.g. center the content, or put an icon
43
+ * above the label. Use phrasing elements (e.g. `Stack as="span"`), as the
44
+ * content is rendered inside a `<label>`.
45
+ */
46
+ export declare const CustomContentLayout: Story;
40
47
  /**
41
48
  * Besides a string, `title` takes a node, such as a `Heading` with an info
42
49
  * icon. It's still rendered as the fieldset's `<legend>`, so it names the
@@ -1,13 +1,15 @@
1
1
  import type { StoryObj } from "@storybook/react-vite";
2
2
  declare const meta: {
3
3
  title: string;
4
- component: import("react").ForwardRefExoticComponent<Omit<import("../src").TextareaProps, "isDisabled" | "isError"> & {
4
+ component: (props: (Omit<import("../src").TextareaProps, "isDisabled" | "isError"> & {
5
5
  label?: React.ReactNode;
6
6
  helperText?: React.ReactNode;
7
7
  errorText?: React.ReactNode;
8
8
  width?: import("../src/types/general.types").FormFieldSize | [import("../src/types/general.types").FormFieldSize, import("../src/types/general.types").FormFieldSize?, import("../src/types/general.types").FormFieldSize?, import("../src/types/general.types").FormFieldSize?, import("../src/types/general.types").FormFieldSize?];
9
9
  fullWidth?: boolean;
10
- } & import("react").RefAttributes<HTMLTextAreaElement>>;
10
+ }) & {
11
+ ref?: React.Ref<HTMLTextAreaElement>;
12
+ }) => import("react").JSX.Element;
11
13
  args: {
12
14
  onChange: import("@vitest/spy").Mock<(...args: any[]) => any>;
13
15
  onBlur: import("@vitest/spy").Mock<(...args: any[]) => any>;
@@ -87,3 +89,8 @@ export declare const Widths: Story;
87
89
  * `width` also accepts a tuple of sizes per breakpoint.
88
90
  */
89
91
  export declare const ResponsiveWidth: Story;
92
+ /**
93
+ * `LabeledTextarea` accepts a `ref`, which points to its native `<textarea>`.
94
+ * Form libraries such as react-hook-form's `register()` rely on this.
95
+ */
96
+ export declare const WithRef: Story;
@@ -6,9 +6,6 @@ import { type StoryObj } from "@storybook/react-vite";
6
6
  *
7
7
  * The selection is only applied when the user confirms it with the "Set"
8
8
  * button, so the field value doesn't change while the user is still choosing.
9
- *
10
- * See `POPOVER_RADIOCARD_RECIPE_SHORTCOMINGS.md` in the root of this
11
- * repository for the workarounds this recipe needs.
12
9
  */
13
10
  declare const meta: {
14
11
  title: string;
@@ -1970,16 +1970,9 @@ button, input:where([type='button'], [type='reset'], [type='submit']), ::file-se
1970
1970
  .ui\:max-w-\[calc\(100dvw-\(var\(--ui-spacing-xl\)\)\)\] {
1971
1971
  max-width: calc(100dvw - (var(--ui-spacing-xl)));
1972
1972
  }
1973
- .ui\:max-w-\[none\] {
1974
- max-width: none;
1975
- }
1976
1973
  .ui\:max-w-full {
1977
1974
  max-width: 100%;
1978
1975
  }
1979
- .ui\:max-w-none {
1980
- max-width: none;
1981
- max-width: var(--ui-spacing-none);
1982
- }
1983
1976
  .ui\:max-w-screen {
1984
1977
  max-width: 100vw;
1985
1978
  }
@@ -3804,9 +3797,6 @@ button, input:where([type='button'], [type='reset'], [type='submit']), ::file-se
3804
3797
  .ui\:text-\(--ui-primitive-color-red-700\) {
3805
3798
  color: var(--ui-primitive-color-red-700);
3806
3799
  }
3807
- .ui\:text-\(--ui-primitive-color-…\) {
3808
- color: var(--ui-primitive-color-…);
3809
- }
3810
3800
  .ui\:text-amber-700 {
3811
3801
  color: var(--ui-color-amber-700);
3812
3802
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luscii-healthtech/web-ui",
3
- "version": "61.0.2",
3
+ "version": "62.0.1",
4
4
  "license": "MIT",
5
5
  "author": {
6
6
  "name": "Joris Janssen"