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.