Skip to content

feat: Deployment Sets, Color/Icon Management, and Multi-Model Integration#99

Merged
miethe merged 54 commits intomainfrom
feat/deployment-sets
Feb 25, 2026
Merged

feat: Deployment Sets, Color/Icon Management, and Multi-Model Integration#99
miethe merged 54 commits intomainfrom
feat/deployment-sets

Conversation

@miethe
Copy link
Owner

@miethe miethe commented Feb 25, 2026

Summary

Major feature branch introducing Deployment Sets (v1 + v2), site-wide Color & Icon Management, and Multi-Model SDLC Integration.

Deployment Sets v1 — Full Feature

  • DFS resolution service with depth limits and BFS circular-reference detection
  • Batch deploy service with per-artifact error handling
  • 11 REST endpoints under /api/v1/deployment-sets/
  • Pydantic schemas for all DTOs
  • List page with card grid, search, create/edit dialogs
  • Detail page with inline edit and member management
  • 3-tab AddMemberDialog (Artifacts, Groups, Sets) with circular-ref validation
  • Batch deploy modal with project/profile selectors and result table
  • TypeScript types, API client, 10 React Query hooks
  • Feature flag gating (SKILLMEAT_DEPLOYMENT_SETS_ENABLED)
  • Integration tests, performance benchmarks, component tests

Deployment Sets v2 — UI Enhancement

  • Clickable set cards opening detail modal (replaces dedicated page)
  • Tabbed modal (Overview, Members, Groups) with inline editing
  • Minified member cards with already-selected state
  • Collapsible member sections by type
  • Colored tags unified with artifact tag system
  • Tag editor with API-compliant 100-char limit
  • Groups tab with collection-scoped smart fallback

Color & Icon Management

  • Custom Colors API (/api/v1/custom-colors/) with DB persistence
  • Shared ColorSelector and IconPicker components
  • Deployment Set color/icon fields in create/edit dialogs
  • Settings page Colors and Icons tabs
  • Icon pack install/remove UI with URL and file upload
  • localStorage migration to API-backed store
  • Backend integration tests and E2E a11y smoke test

Multi-Model SDLC Integration

  • Multi-model orchestration config (.claude/config/multi-model.toml)
  • Cross-model review checkpoints and creative workflows
  • Debug escalation and disagreement protocols
  • Usage spec and CLAUDE.md integration

Documentation

  • CHANGELOG updated with all features and bug fixes
  • README rebuilt with Deployment Sets feature section
  • features.json updated (160+ API endpoints, 25 web pages)
  • Feature flags doc updated
  • Web UI guide expanded with Deployment Sets and Color/Icon sections
  • Agent context files updated (component-patterns, data-flow-patterns, deployment-data-flows, api-endpoint-mapping)

Bug Fixes

  • Removed per-request Alembic migration from BaseRepository
  • Fixed icon picker crashes on undefined pack.icons

Test plan

  • Verify deployment sets CRUD via web UI
  • Create nested set (set containing groups and another set) and batch deploy
  • Confirm circular-reference detection blocks invalid configurations
  • Test color/icon picker in group and deployment set dialogs
  • Verify custom colors persist via Settings > Colors tab
  • Install/remove icon pack via Settings > Icons tab
  • Confirm feature flag disables deployment sets navigation when false
  • Run pytest for backend tests
  • Run pnpm test for frontend tests

🤖 Generated with Claude Code

miethe and others added 30 commits February 24, 2026 12:56
…depth limit

Implement DeploymentSetService.resolve() with BFS pre-fetch for member
data (avoids N+1) and pure DFS resolution with depth-20 limit,
deduplication by artifact_uuid (first-seen order), and group expansion.
Add domain exceptions module with DeploymentSetResolutionError and
DeploymentSetCycleError. 20 unit tests covering nesting, dedup, groups,
depth limits, and edge cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hability

Implement _check_cycle() using BFS descendant reachability to prevent
circular references when adding set members. Self-references rejected
immediately, transitive cycles detected with full path reporting.
add_member_with_cycle_check() gates set-type members through cycle
check before delegating to repository. 12 new tests covering direct,
transitive, DAG, and self-reference scenarios.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…or handling

Implement batch_deploy() that resolves a set to artifact UUIDs, maps
each to name/type via CollectionArtifact JOIN query, resolves project_id
to project_path, and deploys each artifact via DeploymentManager. Per-
artifact exceptions caught without aborting loop. Structured logging
with warning-level messages for missing UUIDs. 9 new tests covering
partial failure, unknown UUID, project lookup, and log assertions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
12 schemas covering CRUD, member management, resolution, and batch
deploy operations. MemberCreate includes model_validator enforcing
exactly one reference field (artifact_uuid/group_id/nested_set_id).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…feature flag

Router at /api/v1/deployment-sets with full CRUD, member management,
recursive resolution, clone, and batch deploy endpoints. Cycle detection
maps to HTTP 422. 34 integration tests covering happy paths and error
cases. Feature flag deployment_sets_enabled added to APISettings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both DS-007 (schemas) and DS-008 (endpoints) completed with 34 passing
integration tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… Query hooks

Types mirror all Pydantic response/request DTOs. Hooks cover full CRUD for sets
and members, resolution, cloning, and batch deploy with proper cache invalidation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…dit dialogs

Card grid shows name, description, member count, color accent, and action menu.
Search filters client-side by name/description/tags. Create and edit dialogs
with color presets and tag input. Nav entry added under Collections section.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… and members endpoint

Detail page shows set metadata with inline-editable name/description, color accent,
resolved artifact count, and member list with type badges. Added GET members endpoint
to API router and corresponding hook/API client function.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ef error handling

Dialog supports adding Artifacts, Groups, or other Sets as members. Each tab has
search filtering, loading skeletons, empty states, and just-added feedback. 422
circular reference errors show toast. Wired to detail page Add Member button.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…deploy flow

Adds batchDeploySetByProjectId API function and useBatchDeploySet React Query
hook that POSTs to /deployment-sets/{id}/deploy. Invalidates deployments cache
on success without touching deployment-sets cache.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lectors and result table

Two-step modal: select target project + optional profile, then view per-artifact
deploy results with status badges (success/skipped/error) and summary line.
Wired to detail page Deploy Set button and list card deploy action.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…deploy, delete, clone

14 tests covering: circular reference detection (422 on A→B→A), batch deploy
adapter with 3-level nested resolution, FR-10 delete semantics (inbound parent
refs removed), clone isolation, and observability warning logs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tion

5 tests verifying resolution of 320-member 5-level nested sets completes
within 500ms SLA. Tests both in-memory DFS and DB-backed paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tchDeployModal

57 Jest/RTL tests covering: 3-tab member picker, circular-ref error toasts,
batch deploy input form, result table with status badges, summary line counts,
and accessibility attributes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…d nav gating

Adds GET /config/feature-flags endpoint, useFeatureFlags React Query hook with
graceful fallback, deployment-sets page client with flag gating (disabled state
shows empty state), and conditional nav item visibility. Fixes hook count in
index.ts (13 deployment-sets hooks).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…acker

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tory

Running run_migrations() on every repository instantiation caused a race
condition under concurrent API requests — Alembic's global script state
was mutated by multiple threads simultaneously, producing KeyError: 'script'
on the deployment-sets deploy endpoint.

Migrations are already run once at startup via CacheManager.__init__().
The redundant per-request call is removed; create_tables() is kept for
backward-compat safety (idempotent via checkfirst=True).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… and context for UI enhancement

Frontend-only v2 enhancing deployment sets with modal-based detail view,
clickable cards, ArtifactBrowseCard-variant member cards, and redesigned
AddMemberDialog with MiniArtifactCard grid and filtering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… (DSv2-001, DSv2-002)

Create DeploymentSetDetailsModal with tabbed layout (Overview/Members) following
ArtifactDetailsModal pattern. Refactor DeploymentSetCard for full-card click with
keyboard accessibility while preserving action menu functionality.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ist page (DSv2-003, DSv2-004)

Implement Overview tab with set metadata (color swatch, tags, member counts,
timestamps). Wire DeploymentSetDetailsModal into deployment-sets-page-client
with selectedSetId state. Thread onOpen prop through DeploymentSetList to cards.
Replace [id] detail page with permanentRedirect to /deployment-sets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…erDialog (DSv2-005, DSv2-007)

Create DeploymentSetMemberCard with rich artifact layout (type borders, badges)
and summary layout for groups/sets. Redesign AddMemberDialog with MiniArtifactCard
grid, real-time search filtering, and artifact type toggle filters.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ation (DSv2-006)

Add DeploymentSetMembersTab with responsive grid of DeploymentSetMemberCard
components. Artifact members open ArtifactDetailsModal, set members open nested
DeploymentSetDetailsModal, group members show info popover. Includes loading
skeletons and empty state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All 7 tasks (14 pts) across 3 phases completed successfully.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ng, and colored tags

- Expand modal to max-w-5xl for better card visibility
- Add Deploy button and kebab menu (Edit/Delete) to modal header
- Make name, description, and tags editable inline in Overview tab
- Add DeploymentSetTagEditor with tag search, toggle, and create
- Fix MiniArtifactCard min-width in AddMemberDialog (min-w-[180px])
- Add colored tags with getTagColor + inline tag popover on set cards

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s button

Redesign Members tab with type-grouped collapsible sections (Artifacts,
Groups, Sets) with independent scrolling per section. Add "Add Members"
button at tab top that opens AddMemberDialog. Sections show count in
header and collapse with chevron toggle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace raw fetch('/api/v1/groups') (missing required collection_id param)
with useGroups(collectionId) hook. Thread collectionId as configurable prop
through AddMemberDialog → GroupTab, falling back to the first collection
via useCollections when not provided.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add DeploymentSetTag junction model and migration for many-to-many
relationship between deployment sets and shared tags. Extend TagService
and TagRepository with deployment_set_count support. Update
create/edit-deployment-set-dialog to use the unified tag system.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
miethe and others added 24 commits February 25, 2026 09:41
The tags API has a max limit of 100, but useTags(200) was being
called which caused a 422 validation error when opening the tag
picker.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract DeploymentSetTagEditor from modal into shared component
  used by both the card and modal (identical tag editing UX)
- Card now shows all available tags from API instead of only current tags
- useUpdateDeploymentSet uses setQueryData for instant detail cache
  update (no refetch delay)
- All DS mutations (create/update/delete) invalidate tag queries so
  deployment_set_count stays fresh

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…llback

Thread collectionId from page → modal → AddMemberDialog so the Groups
tab loads groups from the correct collection. Replace naive
useCollections({ limit: 1 }) fallback with priority-ordered selection:
explicit prop > name match (default/main/personal) > highest artifact
count > first item.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d state

- Add MiniGroupCard with dynamic group icon/color from group-constants
- Add MiniDeploymentSetCard with set color accent and member tooltip
- Add Member dialog: Groups/Sets tabs now use mini card grids with
  "Already Selected" disabled overlay for existing members
- Members tab in details modal: replaced DeploymentSetMemberCard with
  mini cards (artifact/group/set) using hover remove overlay
- member-list.tsx: replaced row list with mini card grid layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hestration docs

Implement the foundation layer of multi-model SDLC integration based on the
architecture report. All external model integrations are opt-in by default;
Claude remains the sole orchestrator.

Phase 1 changes:
- codex skill: default GPT-5.3-Codex, model line separation (Codex vs General),
  effort policy table, escalation rules, Codex-Spark fast option
- gemini-cli skill: Gemini 3.1 Pro (~1M/65K context), Flash option, image/SVG
  workflows, output chunking discipline, creative prompt templates
- sora skill: Sora 2 naming alignment, synced audio capability
- multi-model.toml: unified model routing config with effort policies,
  checkpoints, thresholds, and asset pipeline provenance tracking
- model-selection-guide: decision tree for model routing with interaction
  patterns and unique capabilities map
- agent-assignments: external model task assignments with reliability hazards
- quality-gates: optional cross-model validation gate and disagreement protocol
- gemini-orchestrator agent: updated to Gemini 3.1 Pro with new capabilities

Remaining phases: 2 (checkpoint workflows), 3 (creative workflows),
4 (advanced integration — Teams, local LLM, consensus).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…eative integration

Phase 2 — Checkpoint Workflows:
- cross-model-review.md: plan review (Codex read-only) and PR cross-validation
  (Gemini Pro/Flash) workflow specs with prompt templates and model selection logic
- escalation-protocols.md: debug escalation to Codex after failed cycles,
  thinking/effort escalation rules (adaptive-first, artifact-gated), review
  escalation thresholds
- disagreement-protocol.md: CI-as-referee when models conflict — tests decide,
  "prove it" rule for missing tests, reversibility-based design disagreement handling

Phase 3 — Creative Workflows:
- creative-workflows.md: unified routing for image/SVG/UI mockup/video tasks
  with step-by-step workflows and model selection decision tree
- nano-banana-pro SKILL.md: asset pipeline integration with provenance tracking
  (meta.json schema), batch generation, model routing context (NBP vs Gemini)
- sora SKILL.md: SDLC integration section with orchestration pattern and
  asset pipeline storage

Remaining: Phase 4 (Teams, local LLM, effort auto-tuning, consensus, cost tracking)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create .claude/specs/multi-model-usage-spec.md: comprehensive rules and
  patterns for using the multi-model system — config reading, checkpoint
  behavior, effort policy, decision tree, workflow patterns, disagreement
  protocol, asset provenance, and reference map
- Update CLAUDE.md: add Multi-Model Integration subsection under Agent
  Delegation with capability routing table, effort policy summary,
  disagreement protocol pointer, and key reference paths

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… & icon management

5-phase plan covering backend (CustomColor model, colors API, icon packs config),
shared frontend components (ColorSelector, IconPicker with shadcn-iconpicker),
deployment set integration, settings appearance tab, and validation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ment

Progress tracker with 26 tasks across 5 phases (47 story points),
8 parallelization batches. Context file maps all affected files
and technical decisions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lor/icon persistence

- Add CustomColor ORM model, Alembic migrations (custom_colors table + deployment_sets color/icon columns)
- Add CustomColorRepository with hex validation and CustomColorService
- Add /api/v1/colors CRUD router and /api/v1/settings/icon-packs config router
- Wire deployment_sets POST/PUT/GET to persist and return color + icon fields
- Fix Alembic env.py to auto-resolve DB URL from skillmeat config
- Add icon-packs.config.json with default Lucide pack

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ings tabs, and refactor dialogs

- Install shadcn-iconpicker and upgrade lucide-react to 0.575.0 for dynamic import support
- Add color-constants.ts and icon-constants.ts with shared types and preset definitions
- Add React Query hooks for custom colors and icon packs (use-colors.ts, use-icon-packs.ts)
- Create shared ColorSelector and IconPicker components in components/shared/
- Refactor GroupMetadataEditor to use shared components (removes ~220 lines of inline logic)
- Add Appearance tab to Settings page with Colors and Icons sub-tabs (CRUD + toggle UI)
- Update CreateDeploymentSetDialog and EditDeploymentSetDialog with shared components

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…torage migration

- Add 22 integration tests covering all /api/v1/colors and /api/v1/settings/icon-packs endpoints
- Add one-time localStorage migration banner to Colors settings tab (migrates legacy custom colors)
- Deployment set cards already correctly display stored color/icon — no change needed
- Icon-picker lazy bundle confirmed: 6KB chunk via next/dynamic with ssr:false

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…test

- Fix 3 TS2532 errors in shadcn-iconpicker primitive (non-null assertions on guarded index accesses)
- ColorSelector and IconPicker verified WCAG 2.1 AA compliant (aria-labels, aria-pressed, role=group)
- Add E2E Playwright smoke test for custom color create → verify in dialogs → delete flow
- Mark all 26 tasks completed (100%); implementation plan status → completed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…edit dialog

API icon pack response only contains {id, name, enabled} — no icons array.
Add `?? []` null-coalesce so the loop is a no-op and the picker falls back
to showing all Lucide icons (iconsList=undefined).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ash on Icons tab

Same root cause as icon-picker fix — API response omits icons array.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ialog

- Fix "0 icons" by reading count from local iconsData (~1400+ Lucide icons) instead of API
- Add IconPackViewerDialog: max-w-5xl, 80vh, sidebar category tabs + 8-12 col icon grid
- Search filters by name/tags within active category; live result count shown
- Clicking pack row opens viewer; Switch stopPropagation to avoid accidental open
- DynamicIcon renders each icon live from lucide-react/dynamic

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…racking

New feature planning for Similar Artifacts — detection, comparison,
and consolidation across collection and marketplace. Includes:
- PRD with 6-phase breakdown (42 story points)
- Implementation plan with 3 phase files
- Progress tracking (3 phase files + context worknotes)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…le upload

- POST /settings/icon-packs/install accepts URL or multipart file upload;
  validates JSON structure, guards against duplicate IDs, stores metadata only
- DELETE /settings/icon-packs/{pack_id} removes user-installed packs
  (lucide-default is protected)
- AddIconPackDialog with tabbed URL/file-upload interface, loading spinner,
  success alert, and per-tab error clearing
- IconPackRow gains trash button for non-default packs wired to useDeleteIconPack
- Three new frontend hooks: useInstallIconPackFromUrl, useInstallIconPackFromFile,
  useDeleteIconPack — all invalidate iconPackKeys.all on success

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…packs

Replace the fixed GROUP_ICON_OPTIONS set and _normalize_and_validate_choice
calls with simple string/length validation (max 32 chars) so any Lucide or
custom icon-pack token is accepted without a schema change.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  CHANGELOG.md (+109 lines)

  - Site-Wide Color & Icon Management (2026-02-25) — Custom colors API, shared ColorSelector/IconPicker, settings tabs,
  icon pack management, localStorage migration
  - Deployment Sets v2 — UI Enhancement (2026-02-24) — Clickable cards, detail modal with tabs, inline editing, minified
  member cards, colored tags, tag unification
  - Deployment Sets v1 — Full Feature (2026-02-23) — Resolution service, circular-ref detection, batch deploy, 11 REST
  endpoints, frontend pages, testing
  - Multi-Model SDLC Integration (2026-02-22) — Multi-model orchestration, routing config, checkpoints, creative
  workflows
  - Bug Fixes — Alembic per-request migration removal, icon picker null guards

  README.md (+19 lines)

  - New Deployment Sets feature section with 5 features
  - Updated endpoint count to 160+ and web pages to 25

  features.json (+56 lines)

  - New deployment-sets category with 5 features driving the README build

  User Docs

  - web-ui-guide.md (+85 lines) — Deployment Sets usage guide, Color & Icon Customization guide, Settings tab updates
  - feature-flags.md (+10 lines) — SKILLMEAT_DEPLOYMENT_SETS_ENABLED flag documentation

  Agent Context Files

  - component-patterns.md (+198 lines) — Shared components (ColorSelector, IconPicker), Deployment Sets component
  patterns
  - data-flow-patterns.md (+9 lines) — Stale times and cache invalidation for deployment sets
  - deployment-data-flows.md (+63 lines) — Resolution flow, batch deploy flow, cache invalidation graph
  - api-endpoint-mapping.md (+59 lines) — 11 deployment set endpoints, 4 custom color endpoints
@miethe miethe merged commit 3d3c818 into main Feb 25, 2026
15 of 61 checks passed
@miethe miethe deleted the feat/deployment-sets branch February 25, 2026 20:08
* an X dismiss button with aria-label="Close", so we target the one whose
* direct text content is "Close" (not wrapped in a sr-only span).
*/
function getFooterCloseButton() {

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note test

Unused function getFooterCloseButton.

Copilot Autofix

AI 1 day ago

In general, unused functions should be removed or, if they represent intended behavior, they should be used in the code. Here, getFooterCloseButton is a test helper that is not actually used. The safest fix without changing behavior is to delete the unused helper function entirely, rather than adding artificial calls just to silence the warning.

Concretely, in skillmeat/web/__tests__/deployment-sets/batch-deploy-modal.test.tsx, remove the entire getFooterCloseButton function definition and its associated comment block (lines 107–120 in the snippet). No additional imports, variables, or methods are needed, and no other parts of the file need to be updated.

Suggested changeset 1
skillmeat/web/__tests__/deployment-sets/batch-deploy-modal.test.tsx

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/skillmeat/web/__tests__/deployment-sets/batch-deploy-modal.test.tsx b/skillmeat/web/__tests__/deployment-sets/batch-deploy-modal.test.tsx
--- a/skillmeat/web/__tests__/deployment-sets/batch-deploy-modal.test.tsx
+++ b/skillmeat/web/__tests__/deployment-sets/batch-deploy-modal.test.tsx
@@ -104,21 +104,6 @@
   return { ...utils, onOpenChange };
 }
 
-/**
- * Find the footer "Close" button specifically — the Radix Dialog also renders
- * an X dismiss button with aria-label="Close", so we target the one whose
- * direct text content is "Close" (not wrapped in a sr-only span).
- */
-function getFooterCloseButton() {
-  const allClose = screen.getAllByRole('button', { name: /close/i });
-  // The footer button renders with visible text "Close"; the dialog X button
-  // renders its label as sr-only text. We find the one whose textContent
-  // (trimmed) is exactly "Close" without child elements hiding it.
-  const footer = allClose.find((btn) => btn.textContent?.trim() === 'Close');
-  if (!footer) throw new Error('Could not find footer Close button');
-  return footer;
-}
-
 // ---------------------------------------------------------------------------
 // Mock data
 // ---------------------------------------------------------------------------
EOF
@@ -104,21 +104,6 @@
return { ...utils, onOpenChange };
}

/**
* Find the footer "Close" button specifically the Radix Dialog also renders
* an X dismiss button with aria-label="Close", so we target the one whose
* direct text content is "Close" (not wrapped in a sr-only span).
*/
function getFooterCloseButton() {
const allClose = screen.getAllByRole('button', { name: /close/i });
// The footer button renders with visible text "Close"; the dialog X button
// renders its label as sr-only text. We find the one whose textContent
// (trimmed) is exactly "Close" without child elements hiding it.
const footer = allClose.find((btn) => btn.textContent?.trim() === 'Close');
if (!footer) throw new Error('Could not find footer Close button');
return footer;
}

// ---------------------------------------------------------------------------
// Mock data
// ---------------------------------------------------------------------------
Copilot is powered by AI and may make mistakes. Always verify output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant