Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6bff88e
first approach to message input component using prompt input from ass…
PelayoFelgueroso Jul 3, 2026
a6b1130
Add custom Select
PelayoFelgueroso Jul 13, 2026
d094ca4
Add stories and tests
PelayoFelgueroso Jul 13, 2026
7d56017
add voiceTranscription hook
PelayoFelgueroso Jul 14, 2026
7644f63
Changes based on the new API
PelayoFelgueroso Jul 15, 2026
529bdb9
Add chip icon to types
PelayoFelgueroso Jul 15, 2026
baa29c4
Fix API based on team decissions and document it
PelayoFelgueroso Jul 16, 2026
7a554d3
add overview doc
PelayoFelgueroso Jul 17, 2026
2f69a67
Add documentation
PelayoFelgueroso Jul 20, 2026
3541c3f
Add stories and tests
PelayoFelgueroso Jul 20, 2026
d3c47ab
Merge branch 'master' into PelayoFelgueroso/message-input
PelayoFelgueroso Jul 20, 2026
030371c
Add localization
PelayoFelgueroso Jul 20, 2026
188cc98
fix tests based on label changes
PelayoFelgueroso Jul 20, 2026
e24fa26
Fix tests and improve code quality
PelayoFelgueroso Jul 20, 2026
0063e89
change allowVoiceInput in Code Page
PelayoFelgueroso Jul 20, 2026
d33d9a3
update advanced example
PelayoFelgueroso Jul 20, 2026
372d468
improve tests and types, and correct manage of min and maxLength errors.
PelayoFelgueroso Jul 21, 2026
2c85af6
Remove unused functions in utils
PelayoFelgueroso Jul 21, 2026
7c46ed7
update minLength and maxLenght error behaviour within current formFi…
PelayoFelgueroso Jul 21, 2026
74601e4
Merge branch 'master' into PelayoFelgueroso/message-input
PelayoFelgueroso Jul 22, 2026
ab69ce8
fix based on comments
PelayoFelgueroso Jul 23, 2026
a0656d7
Merge branch 'PelayoFelgueroso/message-input' of https://github.com/d…
PelayoFelgueroso Jul 23, 2026
a8bafe0
pass all the relevant information onSubmit action
PelayoFelgueroso Jul 23, 2026
90a68af
fix tests and update examples at code page
PelayoFelgueroso Jul 23, 2026
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
17 changes: 17 additions & 0 deletions apps/website/pages/components/message-input/code.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Head from "next/head";
import type { ReactElement } from "react";
import MessageInputCodePage from "screens/components/message-input/code/MessageInputCodePage";
import MessageInputPageLayout from "screens/components/message-input/MessageInputPageLayout";

const Code = () => (
<>
<Head>
<title>Message Input code — Halstack Design System</title>
</Head>
<MessageInputCodePage />
</>
);

Code.getLayout = (page: ReactElement) => <MessageInputPageLayout>{page}</MessageInputPageLayout>;

export default Code;
17 changes: 17 additions & 0 deletions apps/website/pages/components/message-input/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Head from "next/head";
import type { ReactElement } from "react";
import MessageInputPageLayout from "screens/components/message-input/MessageInputPageLayout";
import MessageInputOverviewPage from "screens/components/message-input/overview/MessageInputOverviewPage";

const Index = () => (
<>
<Head>
<title>Message Input — Halstack Design System</title>
</Head>
<MessageInputOverviewPage />
</>
);

Index.getLayout = (page: ReactElement) => <MessageInputPageLayout>{page}</MessageInputPageLayout>;

export default Index;
8 changes: 7 additions & 1 deletion apps/website/screens/common/componentsList.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@
"status": "stable",
"icon": "filled_file_upload"
},
{
"label": "Message input",
"path": "/components/message-input",
"status": "experimental",
"icon": "chat_bubble"
},
{
"label": "Number input",
"path": "/components/number-input",
Expand Down Expand Up @@ -271,7 +277,7 @@
"label": "Popover",
"path": "/components/popover",
"status": "experimental",
"icon": "chat_bubble"
"icon": "chat_bubble"
}
]
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { DxcParagraph, DxcFlex } from "@dxc-technology/halstack-react";
import PageHeading from "@/common/PageHeading";
import TabsPageHeading from "@/common/TabsPageLayout";
import ComponentHeading from "@/common/ComponentHeading";
import { ReactNode } from "react";

const MessageInputPageHeading = ({ children }: { children: ReactNode }) => {
const tabs = [
{ label: "Overview", path: "/components/message-input" },
{ label: "Code", path: "/components/message-input/code" },
];

return (
<DxcFlex direction="column" gap="var(--spacing-gap-xxl)">
<PageHeading>
<DxcFlex direction="column" gap="var(--spacing-gap-xl)">
<ComponentHeading name="Message Input" />
<DxcParagraph>
Message inputs are composition components specifically designed to capture and send user messages in{" "}
<strong>conversational interfaces</strong>, both in human-to-human messaging and AI-assisted applications.
</DxcParagraph>
<TabsPageHeading tabs={tabs} />
</DxcFlex>
</PageHeading>
{children}
</DxcFlex>
);
};

export default MessageInputPageHeading;
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
import { DxcTable, DxcFlex } from "@dxc-technology/halstack-react";
import DocFooter from "@/common/DocFooter";
import QuickNavContainer from "@/common/QuickNavContainer";
import Code, { ExtendedTableCode, TableCode } from "@/common/Code";
import Example from "@/common/example/Example";
import controlled from "./examples/controlled";
import uncontrolled from "./examples/uncontrolled";
import advanced from "./examples/advanced";

const fileDataTypeString = `{
label: string;
icon?: string | SVG;
};`;
const callbackFileTypeString = "(files: FileData[]) => void";
const filesTypeString = `FileData[] | []`;
const selectOptionsTypeString = `{
label?: string;
icon?: string | SVG;
value: string;
onSelect: () => void;
selected?: boolean;
}[]`;
const onButtonClickTypeString = `(val: {
type: "submit" | "stop";
value?: string;
files?: FileData[];
selectedOption?: SelectOption;
}) => void;
`;

const sections = [
{
title: "Props",
content: (
<DxcTable>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td>allowRecording</td>
<td>
<TableCode>boolean</TableCode>
</td>
<td>If true, the voice recording button will be shown.</td>
<td>
<TableCode>false</TableCode>
</td>
</tr>
<tr>
<td>callbackFile</td>
<td>
<TableCode>{callbackFileTypeString}</TableCode>
<p>
being <Code>FileData</Code> an object with the following properties:
</p>
<ExtendedTableCode>{fileDataTypeString}</ExtendedTableCode>
</td>
<td>This function will be called when the selection of top items changes.</td>
<td>-</td>
</tr>
<tr>
<td>defaultValue</td>
<td>
<TableCode>string</TableCode>
</td>
<td>Initial value of the input, only when it is uncontrolled.</td>
<td>-</td>
</tr>
<tr>
<td>disabled</td>
<td>
<TableCode>boolean</TableCode>
</td>
<td>If true, the component will be disabled.</td>
<td>
<TableCode>false</TableCode>
</td>
</tr>
<tr>
<td>error</td>
<td>
<TableCode>string</TableCode>
</td>
<td>
If it is a defined value and also a truthy string, the component will change its appearance, showing the
error below the input component. If the defined value is an empty string, it will reserve a space below
the component for a future error, but it would not change its look. In case of being undefined or null,
both the appearance and the space for the error message would not be modified.
</td>
<td>-</td>
</tr>
<tr>
<td>files</td>
<td>
<TableCode>{filesTypeString}</TableCode>
</td>
<td>Items to be shown at the top.</td>
<td>-</td>
</tr>
<tr>
<td>isGenerating</td>
<td>
<TableCode>boolean</TableCode>
</td>
<td>If true, it indicates that a request is being processed after the user submits a query.</td>
<td>
<TableCode>false</TableCode>
</td>
</tr>
<tr>
<td>maxLength</td>
<td>
<TableCode>number</TableCode>
</td>
<td>
Specifies the maximum length allowed by the input. This will be checked both when the input element loses
the focus and while typing within it. If the string entered does not comply the maximum length, the onBlur
and onChange functions will be called with the current value and an internal error informing that the
value length does not comply the specified range. If a valid length is reached, the error parameter of
both events will not be defined.
</td>
<td>-</td>
</tr>
<tr>
<td>minLength</td>
<td>
<TableCode>number</TableCode>
</td>
<td>
Specifies the minimum length allowed by the input. This will be checked aboth when the input element loses
the focus and while typing within it. If the string entered does not comply the minimum length, the onBlur
and onChange functions will be called with the current value and an internal error informing that the
value length does not comply the specified range. If a valid length is reached, the error parameter of
both events will not be defined.
</td>
<td>-</td>
</tr>
<tr>
<td>selectOptions</td>
<td>
<ExtendedTableCode>{selectOptionsTypeString}</ExtendedTableCode>
</td>
<td>Options to be shown on the dropdown under the input.</td>
<td>-</td>
</tr>
<tr>
<td>onBlur</td>
<td>
<TableCode>{"(val: { value: string; error?: string }) => void"}</TableCode>
</td>
<td>
This function will be called when the input element loses the focus. An object including the input value
and the error (if the value entered is not valid) will be passed to this function. If there is no error,
error will not be defined.
</td>
<td>-</td>
</tr>
<tr>
<td>onButtonClick</td>
<td>
<ExtendedTableCode>{onButtonClickTypeString}</ExtendedTableCode>
</td>
<td>
This function will be called when the user clicks on the button (submit or stop) or presses enter. The
type parameter indicates whether it's a <Code>'submit'</Code> or <Code>'stop'</Code> event. For submit
events, <Code>'value'</Code>, <Code>'files'</Code>and <Code>'selectedOption'</Code> are provided.
</td>
<td>-</td>
</tr>
<tr>
<td>onChange</td>
<td>
<TableCode>{"(val: { value: string; error?: string }) => void"}</TableCode>
</td>
<td>
This function will be called when the user types within the input element of the component. An object
including the current value and the error (if the value entered is not valid) will be passed to this
function. If there is no error, error will not be defined.
</td>
<td>-</td>
</tr>
<tr>
<td>placeholder</td>
<td>
<TableCode>string</TableCode>
</td>
<td>Text to be put as placeholder of the input.</td>
<td>-</td>
</tr>
<tr>
<td>size</td>
<td>
<TableCode>{"'small' | 'medium' | 'large' | 'fillParent'"}</TableCode>
</td>
<td>Specifies the size of the component. The size will affect the width of the input.</td>
<td>
<TableCode>'medium'</TableCode>
</td>
</tr>
<tr>
<td>tabIndex</td>
<td>
<TableCode>number</TableCode>
</td>
<td>
Value of the <Code>tabindex</Code> attribute.
</td>
<td>-</td>
</tr>
<tr>
<td>value</td>
<td>
<TableCode>string</TableCode>
</td>
<td>
Value of the input. If undefined, the component will be uncontrolled and the value will be managed
internally by the component.
</td>
<td>-</td>
</tr>
</tbody>
</DxcTable>
),
},
{
title: "Examples",
subSections: [
{
title: "Uncontrolled",
content: <Example example={uncontrolled} defaultIsVisible />,
},
{
title: "Controlled",
content: <Example example={controlled} defaultIsVisible />,
},
{
title: "Advanced",
content: <Example example={advanced} defaultIsVisible />,
},
],
},
];

const MessageInputCodePage = () => {
return (
<DxcFlex direction="column" gap="4rem">
<QuickNavContainer sections={sections} startHeadingLevel={2} />
<DocFooter githubLink="https://github.com/dxc-technology/halstack-react/blob/master/packages/lib/src/message-input/MessageInput.tsx" />
</DxcFlex>
);
};

export default MessageInputCodePage;
Loading
Loading