Skip to content

feat: Add huxChat — stream-ready AI chat Alpine.js component#34

Open
Copilot wants to merge 10 commits intomainfrom
copilot/define-functional-requirements-chat-component
Open

feat: Add huxChat — stream-ready AI chat Alpine.js component#34
Copilot wants to merge 10 commits intomainfrom
copilot/define-functional-requirements-chat-component

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 8, 2026

Introduces huxChat, a logic scaffold for ChatGPT/Claude-style UIs. Covers the full interaction surface — message thread, live streaming, input handling, message actions, suggested prompts, thinking messages, response rating, chat export, and persisted voice toggle — without coupling to any backend.

Registration (PatternRegistration.astro)

New huxChatRegistration script block registering Alpine.data('huxChat', ...):

  • State: messages[] (id, role, content, status: 'sending'|'complete'|'error', rating: 'up'|'down'|null), isLoading, inputValue, suggestedPrompts[], isVoiceEnabled, thinkingMessage
  • sendMessage() — guards on empty input + isLoading; appends user message; calls response handler. Clearly marked API Integration Point. Developers set this.thinkingMessage at key points in their fetch/SSE handler.
  • scrollToBottom() — defers via $nextTick on x-ref="messageList"
  • handleKeydown(event)Enter sends, Shift+Enter passes through
  • copyToClipboard(id) — writes message content from reactive state via navigator.clipboard (not huxCopy, which is DOM-source only); the toolbar "Copy Alpine.js + HTML" button uses huxCopy
  • regenerateResponse(id) — splices from the target index and re-invokes the response handler
  • rateMessage(id, rating) — sets message.rating to 'up' or 'down'; calling again with the same rating toggles it back to null
  • exportChat() — collects all complete messages, formats as You: … / Assistant: … plain text, and triggers a chat-export.txt download via Blob URL
  • toggleVoice() — flips isVoiceEnabled, persists to localStorage under hux-chat:voice-enabled; component manages state only — developers wire their own TTS call
  • selectSuggestedPrompt(prompt) — fills inputValue and calls sendMessage()
  • _simulateResponse() — demo stub that shows thinking messages for 1.5s (cycling every 3s), then streams a contextual response word-by-word at ~55ms/word; explicitly documented as the replacement point for real fetch/SSE/WebSocket logic
huxChat({
  suggestedPrompts: ['What can this chat scaffold do?', 'How do I connect this to an API?'],
  messages: [{ id: 'intro', role: 'assistant', content: 'Hi! How can I help?', status: 'complete', rating: null }],
})

Demo (src/components/demos/Chat.astro)

Working demo UI: scrollable role="log" message list with aria-live="polite", user/assistant bubbles, whitespace-pre-wrap on message content for correct newline rendering, animated typing indicator with live thinkingMessage text (cycles every 3s), word-by-word streaming simulation that demonstrates the real streaming UX, always-visible copy/thumbs-up/thumbs-down/regenerate actions (rating buttons highlight and reflect state via aria-pressed), contextual suggested prompts on empty state ('What can this chat scaffold do?', 'Explain how streaming works here', 'How do I connect this to an API?'), auto-expanding textarea, export button (disabled when no complete messages), and aria-pressed voice toggle.

Docs (src/content/patterns/chat.mdx)

Full pattern page following HyperUX conventions: API → Options → Quick Start → Common Usage Patterns (API integration, thinking messages, message actions with rating, export, voice toggle) → Behavior Contract → Error Handling → Accessibility Notes → Notes. Includes a note clarifying the huxCopy vs navigator.clipboard distinction for copy actions.

Agent-Logs-Url: https://github.com/markmead/hyperux/sessions/d05ebac7-4d1f-4d9f-8f9a-b6a40ed5130d

Co-authored-by: markmead <50486078+markmead@users.noreply.github.com>
@cloudflare-workers-and-pages
Copy link
Copy Markdown
Contributor

cloudflare-workers-and-pages Bot commented May 8, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
hyperux f8896b6 Commit Preview URL

Branch Preview URL
May 08 2026, 06:14 PM

Copilot AI changed the title [WIP] Define functional requirements for AI chat Alpine.js component feat: Add huxChat — stream-ready AI chat Alpine.js component May 8, 2026
Copilot AI requested a review from markmead May 8, 2026 09:33
@markmead
Copy link
Copy Markdown
Owner

markmead commented May 8, 2026

@copilot Nice start – an immediate issue I see is that newlines aren't shown in the chat message. Aside from that, can confirm how the following work?

  • Sending a message with voice
  • Getting new messages from an API into the x-data
  • Are we using huxCopy for the copy-to-clipboard functionality?

Some features that would be nice:

  • Updates from the AI as it thinks ("Working on it", "Crunching the numbers" – that sort of thing)
  • Thumbs up/down the AI response
  • Export the full chat

Can you think of anything else?

@markmead markmead added the enhancement New feature or request label May 8, 2026
Copilot AI and others added 2 commits May 8, 2026 09:50
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 8, 2026

@copilot Nice start – an immediate issue I see is that newlines aren't shown in the chat message. Aside from that, can confirm how the following work?

  • Sending a message with voice
  • Getting new ...

Addressed in commit 9fd6874. Here's a rundown:

Newlines fixed — message content now uses whitespace-pre-wrap so \n in user/assistant text renders correctly.

Thinking messages — added thinkingMessage: string state. The demo stub cycles through "Working on it…", "Crunching the numbers…", "Almost there…" while waiting. In a real integration, set this.thinkingMessage at key points in your fetch/SSE handler and clear it when the response arrives. Displayed inline in the typing bubble with aria-live="polite".

Thumbs up/down — new rateMessage(id, rating) method. Each message object now has a rating: null | 'up' | 'down' field. Calling with the same rating toggles it back to null. Buttons highlight green/red when active and expose state via aria-pressed.

Export chat — new exportChat() method. Collects all complete messages, formats them as You: … / Assistant: … joined by double newlines, and triggers a chat-export.txt download via a Blob URL. The toolbar export button is disabled when no complete messages exist.

VoicetoggleVoice() manages state (isVoiceEnabled) and persists it to localStorage. The component intentionally doesn't implement TTS itself — developers gate their own speechSynthesis or voice API call on isVoiceEnabled. Documented in the Notes section.

API integration — the _simulateResponse() stub is the single replacement point for both sendMessage() and regenerateResponse(). Your fetch/SSE loop pushes content into the sending assistant message in place. The docs include a full streaming integration snippet.

huxCopy vs per-message copy — the toolbar "Copy Alpine.js + HTML" button uses huxCopy (DOM source). copyToClipboard(id) uses navigator.clipboard directly because it reads from reactive component state, not a DOM element. This distinction is now documented in the Notes section.

@markmead
Copy link
Copy Markdown
Owner

markmead commented May 8, 2026

@copilot Nice, some feedback:

  • thinkingMessage changes way too quickly though – slow it down to 3s.
  • Keep the interactions within the message visible (no hover-to-show)
  • Can we have some different messages for the demo?
  • Can we demonstrate streaming messages for the demo?

…ompts, streaming demo

Agent-Logs-Url: https://github.com/markmead/hyperux/sessions/074caaad-67ec-488c-9238-dedc2cd5b28b

Co-authored-by: markmead <50486078+markmead@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 8, 2026

@copilot Nice, some feedback:

  • thinkingMessage changes way too quickly though – slow it down to 3s.
  • Keep the interactions within the message visible (no hover-to-show)
    ...

Done in cb569f2:

  • Thinking messages now cycle every 3s instead of 500ms.
  • Message actions (copy, thumbs up/down, regenerate) are always visible — no hover required.
  • Suggested prompts updated to: "What can this chat scaffold do?", "Explain how streaming works here", "How do I connect this to an API?" — these map directly to the demo responses.
  • Streaming demo_simulateResponse() now streams word-by-word at ~55ms/word from a pool of 4 contextual responses. Shows 1.5s of thinking messages first, then the words appear progressively. The streaming indicator transitions seamlessly to the text as it arrives.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new huxChat Alpine.js pattern to HyperUX: an interaction-ready chat scaffold (messages, streaming UX hooks, actions, export, and persisted voice toggle), plus a full demo and documentation page.

Changes:

  • Registered new huxChat Alpine data component in PatternRegistration.astro (state + message lifecycle helpers + demo streaming stub).
  • Added a complete demo UI (Chat.astro) showcasing streaming/thinking states, actions (copy/rate/regenerate), export, and voice toggle.
  • Added a full pattern doc page (chat.mdx) describing API, options, usage patterns, behavior contract, error handling, and accessibility notes.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
src/components/PatternRegistration.astro Registers huxChat and provides the scaffold behavior + demo _simulateResponse() implementation.
src/components/demos/Chat.astro Implements the interactive demo UI used on the pattern page and for copyable snippets.
src/content/patterns/chat.mdx Documents the new chat pattern (API/options/behavior/accessibility) and links the demo.

Comment thread src/content/patterns/chat.mdx Outdated
Comment thread src/content/patterns/chat.mdx Outdated
Comment thread src/components/PatternRegistration.astro
Comment thread src/components/PatternRegistration.astro Outdated
Comment thread src/components/demos/Chat.astro Outdated
@markmead
Copy link
Copy Markdown
Owner

markmead commented May 8, 2026

@copilot Address the PR feedback.

…generateResponse guard, a11y

Agent-Logs-Url: https://github.com/markmead/hyperux/sessions/f74084ea-bcdc-4e3d-8bf0-6c97a1c64d92

Co-authored-by: markmead <50486078+markmead@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 8, 2026

@copilot Address the PR feedback.

Done in f65e73c. Four review issues addressed:

  • messages option type — now documents the full shape: { id: string, role: 'user' | 'assistant', content: string, status: 'sending' | 'complete' | 'error', rating: 'up' | 'down' | null }.
  • scrollToBottom() docs note — removed the inaccurate claim about passing a custom ref; the method always reads this.$refs.messageList and accepts no parameters.
  • regenerateResponse(id) guard — now validates the target is role === 'assistant' and status === 'complete' before splicing, and logs a clear error otherwise. Also replaced findLast() (not universally available in non-transpiled scripts) with Array.prototype.some().
  • Typing indicator accessibility — container now has role="status" + aria-live="polite", with an sr-only "Assistant is typing" text node for screen readers. Decorative dots and visible thinkingMessage text are marked aria-hidden="true" to prevent duplication.

@markmead markmead marked this pull request as ready for review May 8, 2026 11:31
markmead added 2 commits May 8, 2026 13:42
Replace inline SVGs in src/components/demos/Chat.astro with Lucide/Astro icon components (Download, Send, Mic, MicOff, ThumbsUp, ThumbsDown, RefreshCw, Clipboard) and apply several UI refinements: adjust container height/overflow, make message list spacing dynamic, tweak avatar sizes/labels, simplify typing indicator markup, reorder and restyle message action buttons, and update textarea/send button positioning and styles. Also update generated workerd runtime comment in worker-configuration.d.ts to a newer version.
Replace inline <svg> markup in Combobox, Dialog, and Dropdown demos with lucide/astro icon components. Adds imports for X and ChevronDown, swaps SVG blocks for <X /> and <ChevronDown /> (preserving bindings like x-bind:class), and adjusts size classes for the Combobox clear button for consistent styling and simpler markup.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.

const thinkingInterval = setInterval(() => {
stepIndex = (stepIndex + 1) % thinkingSteps.length
this.thinkingMessage = thinkingSteps[stepIndex]
}, 3000)
Comment on lines +1487 to +1489
link.click()

URL.revokeObjectURL(url)
`huxChat` is a logic scaffold for ChatGPT/Claude-style UIs. It manages a message thread, loading state, input handling, message actions, suggested prompts, thinking messages, response rating, chat export, and a voice toggle — without coupling you to any specific backend or streaming protocol.

Replace the `_simulateResponse()` call in `sendMessage()` and `regenerateResponse()` with your own `fetch`/SSE/WebSocket logic to connect to any AI backend.

Comment thread src/components/demos/Chat.astro
@markmead
Copy link
Copy Markdown
Owner

markmead commented May 8, 2026

@copilot Address the feedback, but instead of making the setTimeout 500ms, increase the clear interval to be 300ms, and make the message interval 1000ms.

… constraints note

Agent-Logs-Url: https://github.com/markmead/hyperux/sessions/ca190480-a69d-4d3a-b8ab-4dd6c454adc7

Co-authored-by: markmead <50486078+markmead@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 8, 2026

@copilot Address the feedback, but instead of making the setTimeout 500ms, increase the clear interval to be 300ms, and make the message interval 1000ms.

Done in f8896b6. All three reviewer issues addressed:

  • Thinking message interval → 1000ms (down from 3000ms), so it now cycles at least once before the 1500ms setTimeout clears it.
  • Blob URL revocation → deferred with setTimeout(() => URL.revokeObjectURL(url), 300) so the download isn't cancelled before it starts.
  • navigator.clipboard constraints → added a note near the intro documenting the HTTPS/secure context requirement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Define Functional Requirements: Feature-Rich AI Chat Alpine.js Component with Excellent DX

3 participants