Form component that renders the "Open Ticket" submission UI at the top of ``, composing existing oss-lib primitives for subject input, message textarea, file attachments, and submit handling with multi-condition gating. ## Key Components ### `TicketOpenForm` Main exported component. Renders a two-column `` layout with a description panel on the left and the form fields on the right. **Props (`TicketOpenFormProps`):** | Prop | Type | Description | |---|---|---| | `onSubmit` | `(input) => Promise` | Wired to `useTicketActions().submitTicket`; returns `true` on success to trigger form reset | | `isSubmitting` | `boolean` | Single-flight guard owned by the parent | | `supportSystemDown` | `boolean` | Disables all inputs and shows an error banner when `true` | **Submit gating — `canSubmit` is `true` only when all of the following hold:** - Subject and content are non-empty after trim - Content is within `TICKET_TEXT_MAX_CHARS` - No uploads are in-flight (`hasInflightUploads === false`) - `isSubmitting` is `false` - `supportSystemDown` is `false` **Character counter** — visible once content reaches 80% of `TICKET_TEXT_MAX_CHARS`; turns red when the limit is exceeded. **Attachment handling** — delegates entirely to `useChatAttachments`, reusing the same upload pipeline as the chat composer. ## Usage Example ```typescript import { TicketOpenForm } from '@openframe/oss-lib' import { useTicketActions } from './hooks/use-ticket-actions' function TicketCenter() { const { submitTicket, isSubmitting, supportSystemDown } = useTicketActions() return ( ) } ``` On successful submission (`onSubmit` resolves `true`), the form automatically clears subject, content, and all attachments.