diff --git a/src/index.html b/src/index.html index 4a45dca..b9d33e7 100644 --- a/src/index.html +++ b/src/index.html @@ -193,8 +193,8 @@

Agentic workflow wizard
@@ -202,8 +202,8 @@

Agentic workflow wizard
-

Your workflow generator prompt is ready

-

Copy it, then paste it into your agent from the repository you want to automate.

+

Your workflow generator prompt is ready

+

Copy it, then paste it into your agent from the repository you want to automate.

@@ -211,10 +211,10 @@

Your workflow generator prompt is ready

- Prompt preview - Review before copying + Prompt preview + Review before copying
-
+
@@ -258,7 +258,7 @@

Your workflow generator prompt is ready

-
-

Prompt copied

+

Prompt copied

Your workflow is one prompt away

Open your coding agent from the repository you want to automate, then paste the prompt to generate your agentic workflow.

- Run it in your repository - Your agent will take it from there. + Run it in your repository + Your agent will take it from there.
- +
diff --git a/src/js/ui.js b/src/js/ui.js index 3f06da4..773825c 100644 --- a/src/js/ui.js +++ b/src/js/ui.js @@ -792,9 +792,9 @@ function showCopyFailure() { const status = document.getElementById('copy-status'); clearTimeout(copyFeedbackTimer); button.dataset.defaultLabel ||= button.textContent; - button.textContent = 'Copy failed — try again'; + button.textContent = button.dataset.failureLabel || 'Copy failed — try again'; button.classList.add('copy-error'); - status.textContent = 'Prompt could not be copied. Please try again.'; + status.textContent = status.dataset.failureMessage || 'Prompt could not be copied. Please try again.'; copyFeedbackTimer = setTimeout(resetCopyFeedback, 3000); } diff --git a/src/js/wizard-config.js b/src/js/wizard-config.js index 0933e93..b16be19 100644 --- a/src/js/wizard-config.js +++ b/src/js/wizard-config.js @@ -40,6 +40,25 @@ const LANDING_ELEMENTS = { outputs_label: 'landing-outputs-label' }; +const FINISH_ELEMENTS = { + step_label: 'finish-step-label', + step_description: 'finish-step-description', + title: 'finish-title', + message: 'finish-message', + copy_button: 'btn-copy', + preview_label: 'finish-preview-label', + preview_hint: 'finish-preview-hint' +}; + +const COPY_SUCCESS_ELEMENTS = { + eyebrow: 'copy-modal-eyebrow', + title: 'copy-modal-title', + description: 'copy-modal-description', + next_step_title: 'copy-modal-next-step-title', + next_step_description: 'copy-modal-next-step-description', + action: 'copy-modal-action' +}; + const FOOTER_ELEMENTS = { source: ['footer-source', 'footer-source-label'], report_issue: ['footer-report-issue', 'footer-report-issue'], @@ -68,6 +87,33 @@ export function applyPageContent(config, configUrl) { const landing = config && config.landing ? config.landing : {}; Object.entries(LANDING_ELEMENTS).forEach(([key, id]) => setText(id, landing[key])); + const finish = config && config.finish ? config.finish : {}; + Object.entries(FINISH_ELEMENTS).forEach(([key, id]) => setText(id, finish[key])); + const copyButton = document.getElementById('btn-copy'); + if (copyButton) { + if (typeof finish.copy_button === 'string') { + copyButton.dataset.defaultLabel = finish.copy_button; + } + if (typeof finish.copy_failure_button === 'string') { + copyButton.dataset.failureLabel = finish.copy_failure_button; + } + } + const copyStatus = document.getElementById('copy-status'); + if (copyStatus && typeof finish.copy_failure_status === 'string') { + copyStatus.dataset.failureMessage = finish.copy_failure_status; + } + const preview = document.getElementById('finish-preview'); + if (preview && typeof finish.preview_aria_label === 'string') { + preview.setAttribute('aria-label', finish.preview_aria_label); + } + + const copySuccess = config && config.copy_success ? config.copy_success : {}; + Object.entries(COPY_SUCCESS_ELEMENTS).forEach(([key, id]) => setText(id, copySuccess[key])); + const closeButton = document.getElementById('copy-modal-close'); + if (closeButton && typeof copySuccess.close_label === 'string') { + closeButton.setAttribute('aria-label', copySuccess.close_label); + } + const footer = config && config.footer ? config.footer : {}; Object.entries(FOOTER_ELEMENTS).forEach(([key, ids]) => { const item = footer[key] || {}; diff --git a/src/wizard.json b/src/wizard.json index 6884ee5..3055cfb 100644 --- a/src/wizard.json +++ b/src/wizard.json @@ -12,6 +12,27 @@ "agent_label": "Agent", "outputs_label": "Safe outputs" }, + "finish": { + "step_label": "Finish", + "step_description": "copy your prompt and run it", + "title": "Your workflow generator prompt is ready", + "message": "Copy it, then paste it into your agent from the repository you want to automate.", + "copy_button": "Copy prompt", + "copy_failure_button": "Copy failed — try again", + "copy_failure_status": "Prompt could not be copied. Please try again.", + "preview_label": "Prompt preview", + "preview_hint": "Review before copying", + "preview_aria_label": "Generated prompt preview" + }, + "copy_success": { + "close_label": "Close", + "eyebrow": "Prompt copied", + "title": "Your workflow is one prompt away", + "description": "Open your coding agent from the repository you want to automate, then paste the prompt to generate your agentic workflow.", + "next_step_title": "Run it in your repository", + "next_step_description": "Your agent will take it from there.", + "action": "Got it" + }, "footer": { "source": { "url": "https://github.com/githubnext/gh-aw-wizard", diff --git a/test/a11y.test.js b/test/a11y.test.js index 1367589..a802845 100644 --- a/test/a11y.test.js +++ b/test/a11y.test.js @@ -108,8 +108,12 @@ describe('Copy prompt success modal', () => { }); it('tells users to run the copied prompt in their repository', () => { - expect(html).toContain('Open your coding agent from the repository you want to automate'); - expect(html).toContain('Run it in your repository'); + expect(wizard.copy_success.description).toContain( + 'Open your coding agent from the repository you want to automate' + ); + expect(wizard.copy_success.next_step_title).toBe('Run it in your repository'); + expect(html).toContain('id="copy-modal-description"'); + expect(html).toContain('id="copy-modal-next-step-title"'); }); it('announces clipboard failures without opening the success modal', () => { diff --git a/test/wizard-config.test.js b/test/wizard-config.test.js index 247d356..1628048 100644 --- a/test/wizard-config.test.js +++ b/test/wizard-config.test.js @@ -54,6 +54,12 @@ describe('wizard configuration', () => { const elements = { 'landing-title': { textContent: '' }, 'landing-button-label': { textContent: '' }, + 'finish-title': { textContent: '' }, + 'btn-copy': { textContent: '', dataset: {} }, + 'copy-status': { textContent: '', dataset: {} }, + 'finish-preview': { setAttribute: vi.fn() }, + 'copy-modal-title': { textContent: '' }, + 'copy-modal-close': { setAttribute: vi.fn() }, 'footer-source': { href: '' }, 'footer-source-label': { textContent: '' }, 'footer-security': { href: '', textContent: '' } @@ -70,6 +76,17 @@ describe('wizard configuration', () => { title: 'Build an automation', button: 'Start building' }, + finish: { + title: 'Your custom prompt is ready', + copy_button: 'Copy custom prompt', + copy_failure_button: 'Try copying again', + copy_failure_status: 'The custom prompt was not copied.', + preview_aria_label: 'Custom prompt preview' + }, + copy_success: { + close_label: 'Dismiss', + title: 'Custom prompt copied' + }, footer: { source: { url: './source', @@ -84,6 +101,21 @@ describe('wizard configuration', () => { expect(elements['landing-title'].textContent).toBe('Build an automation'); expect(elements['landing-button-label'].textContent).toBe('Start building'); + expect(elements['finish-title'].textContent).toBe('Your custom prompt is ready'); + expect(elements['btn-copy']).toMatchObject({ + textContent: 'Copy custom prompt', + dataset: { + defaultLabel: 'Copy custom prompt', + failureLabel: 'Try copying again' + } + }); + expect(elements['copy-status'].dataset.failureMessage).toBe('The custom prompt was not copied.'); + expect(elements['finish-preview'].setAttribute).toHaveBeenCalledWith( + 'aria-label', + 'Custom prompt preview' + ); + expect(elements['copy-modal-title'].textContent).toBe('Custom prompt copied'); + expect(elements['copy-modal-close'].setAttribute).toHaveBeenCalledWith('aria-label', 'Dismiss'); expect(elements['footer-source']).toMatchObject({ href: 'https://custom.example/config/source' });