Skip to content

Carve G-components into @galaxyproject/galaxy-ui workspace package#22588

Draft
dannon wants to merge 13 commits intogalaxyproject:devfrom
dannon:feature/client-ui-package
Draft

Carve G-components into @galaxyproject/galaxy-ui workspace package#22588
dannon wants to merge 13 commits intogalaxyproject:devfrom
dannon:feature/client-ui-package

Conversation

@dannon
Copy link
Copy Markdown
Member

@dannon dannon commented Apr 28, 2026

Stacked on #22554 -- merge that one first. Diff here will collapse to just the galaxy-ui changes once that merges.

Galaxy's G-prefixed BaseComponents have grown into a proper component library, but they live inside client/src/components/BaseComponents/ alongside everything else. This PR carves them out into a dedicated internal workspace package, @galaxyproject/galaxy-ui, so the library has a clear surface, its own dependencies, and a future path to being published or consumed by other projects (Galaxy Workbench, etc.).

The package is intentionally "private": true for now -- the goal of this PR is just the structural move, not the publish surface. Consuming code in client/src/ continues to import from @galaxyproject/galaxy-ui and the bundler resolves it through the workspace alias, so runtime behavior is unchanged.

The work is split into prep commits and the actual move:

Prep (decouple G-components from app-level concerns so they can stand alone):

  • Move ColorVariant into componentVariants.ts
  • Port GTip styling to CSS custom properties (no more dependency on app CSS)
  • Add GHeading and swap GModal off Common/Heading
  • Inline two generic @/utils usages in GModal and GForm

Move:

  • Scaffold the @galaxyproject/galaxy-ui workspace package
  • Move G-components and supporting utilities in
  • Declare galaxy-ui as a devDependency of galaxy-client (it's bundled into client/dist/ at build time, so consumers don't need it at install time -- listing it as a runtime dep would have broken the published galaxy-client tarball)

@mvdbeek
Copy link
Copy Markdown
Member

mvdbeek commented Apr 28, 2026

This is conflicted too

dannon added 13 commits April 28, 2026 09:36
Relocates the standalone @galaxyproject/galaxy-api-client package under
client/ as a sibling to the future workspace packages directory. No
workspace adoption yet -- the package remains a standalone pnpm project
at its new location, with its own lockfile.

Along with the move:
- Retarget src/api symlink to ../../../src/api (one level deeper).
- Adjust sync-version.js's GALAXY_ROOT relative path for the new depth.
- Update client-api-test.yaml and publish_artifacts.yaml paths.
- Add packages/ to client/.eslintrc.js ignorePatterns so nested workspace
  packages aren't pulled into client/tsconfig's lint scope.
- Prettier autofixes applied to the moved files by the pre-commit hook.
Adds client/pnpm-workspace.yaml so that pnpm install from client/
resolves galaxy-api-client as a workspace member. The per-package
client/packages/api-client/pnpm-lock.yaml goes away in favor of the
single client/pnpm-lock.yaml covering the whole workspace.

CI is simplified to a single install step, then workspace-filtered
build/test/publish invocations (pnpm --filter @galaxyproject/galaxy-api-client).

This is the first real workspace member; the packages/* glob is ready
to accept extractions (galaxy-utils, galaxy-ui, galaxy-composables) in
follow-up PRs.
With the workspace in place, flip the client<->api-client relationship.
The OpenAPI schema becomes canonical in the api-client package, and the
main client re-exports its types from @galaxyproject/galaxy-api-client
as a workspace dependency. The old symlink from api-client back into
client/src/api goes away -- the library no longer reaches into the app.

Changes:
- Move client/src/api/schema/schema.ts (48K lines) into
  client/packages/api-client/src/schema/schema.ts as the canonical copy.
- Add client/packages/api-client/src/schema/index.ts matching the old
  barrel.
- Update api-client's api-types.ts to import from the new local path;
  remove the no-longer-needed client/packages/api-client/src/api symlink.
- Replace client/src/api/schema/index.ts with a re-export from
  @galaxyproject/galaxy-api-client.
- Add @galaxyproject/galaxy-api-client as a workspace:* dep in client.
- Wire a postinstall hook in client/package.json to build api-client on
  pnpm install so its .d.ts is available to vue-tsc.
- Update make update-client-api-schema to generate into the new canonical
  location.
- Fix the one file still importing from @/api/schema/schema (the index
  barrel re-exports components already).

This PR now demonstrates the workspace end-to-end: a real library
package, consumed by the app, building through the workspace toolchain.
Further extractions (galaxy-utils, galaxy-ui, galaxy-composables) follow
in subsequent PRs using the same pattern.
During make client-dev-server, imports of @galaxyproject/galaxy-api-client
now resolve directly to packages/api-client/src/index.ts rather than its
built dist/. Edits to the package source trigger HMR in the main client
without a manual rebuild.

Production vite build is unchanged -- it still consumes the package via
its package.json exports (dist/index.js + dist/index.d.ts), so the built
bundle reflects the same interface external consumers would see.

defineConfig switches to a function form so 'command' is available for
the dev/build discriminator. Only the resolve.alias field is
command-dependent; everything else is shared.
Adds client/packages/README.md covering what lives there, the bar for
adding new packages, and common ops (pnpm --filter, postinstall, the
dev-mode source alias). Cross-links from client/README.md so the main
client docs point at it.
The client/ package.json now has @galaxyproject/galaxy-api-client at
workspace:* and a postinstall that filters into the workspace to build
it. npm publish doesn't rewrite the workspace: protocol, so the published
tarball would carry the literal "workspace:*" and break downstream
installs; pnpm publish substitutes the real version. The postinstall is
also workspace-only -- if it ships in the tarball, consumers' npm install
fails when pnpm --filter runs outside any workspace -- so npm pkg delete
strips it before pnpm publish runs.
ColorVariant lives with the other component variant types inside
BaseComponents/ so G-components don't need to reach back into
@/components/Common to get their own types. Common/index.ts re-exports
for the app-code consumers that still import it from there.

Prep work for carving BaseComponents into a @galaxyproject/galaxy-ui
workspace package -- the package needs its types self-contained.
Drops the @import of @/style/scss/theme/blue.scss and switches to the
--color-* tokens from custom_theme_variables.scss (PR galaxyproject#19946, Laila
Los): --color-blue-600 for info, --color-orange-600/200 for warning,
--color-green-600/200 for success, --color-red-600/200 for danger, and
--color-grey-100 for neutral background.

GTip was the only G-component with an explicit theme SCSS import, so
removing it cleans up the last bit of mandatory theme coupling in
BaseComponents. The SCSS scale-color() calls for warning/success/danger
backgrounds map to the 200-shade of each hue, which is the closest
pre-defined match and avoids the partial-transparency pattern the color
system intentionally moved away from.

Prep work for the @galaxyproject/galaxy-ui workspace package: the
package can't depend on Galaxy's SCSS theme, so it consumes CSS custom
properties injected by the app at :root.
GHeading is a near-identical variant of Common/Heading.vue with the
Galaxy-specific bits removed: no IconLike dependency from
@/components/icons/galaxyIcons (accepts FontAwesome IconDefinition
directly), and no @import of the Galaxy theme SCSS -- the separator
stripe uses var(--color-grey-200) instead of $brand-secondary (same
hex value).

GModal was the only G-component importing Common/Heading.vue. It now
uses GHeading, which keeps BaseComponents self-contained. Heading.vue
stays in place for the dozens of feature-component consumers.

Prep work for the @galaxyproject/galaxy-ui workspace package: the
package can't depend on Galaxy-specific icon types or theme SCSS.
GModal's match() call just maps small/medium/large to sm/md/lg for
GHeading -- swap it for a plain record lookup. GForm's assertDefined
on the form template ref becomes an inline null check. Both are prep
for the galaxy-ui extraction: neither helper is UI-shaped, so those
stay put in @/utils/ while the component boundary stays clean.
Adds packages/ui/ as a second workspace member alongside api-client --
private, source-only, no library build. Empty src/index.ts barrel;
components and composables move in next.

Wires galaxy-ui into the main client as a workspace:* dep and as an
unconditional resolve.alias in vite.config.mjs (serve and build). The
api-client alias stays serve-only because it has a real dist/ build
and production consumes that via package.json exports; galaxy-ui is
internal-only so we skip the build step entirely and let the main
client's @vitejs/plugin-vue2 handle the Vue 2 SFCs from source in
both dev and prod.

client/packages/README.md now lists both packages and calls out the
"flips to a library build + publish when the interface stabilizes on
Vue 3" intent.
Relocates 15 G-prefixed base components (GButton, GButtonGroup, GCheckbox,
GCollapse, GHeading, GLink, GModal, GOverlay, GTab, GTabs, GTip, GTooltip,
Form/{GForm,GFormInput,GFormLabel}), 6 supporting composables
(accessibleHover, clickableElement, currentTitle, markdown, resolveElement,
uid), componentVariants, and tooltipTiming into packages/ui/src/. Old
paths become re-export shims so consumers keep working unchanged --
app-side imports get updated gradually rather than in a mass codemod.

Internal imports within the package are rewritten to relative paths; zero
@/ imports remain in packages/ui/src/, so the boundary doesn't silently
depend on the main client's source tree.
galaxy-ui is "private": true and never gets published to npm. With it
declared as a runtime dependency, pnpm publish would rewrite workspace:*
to 0.0.0-internal in the published galaxy-client tarball, and consumers'
npm install would then fail trying to fetch a non-existent package.
galaxy-ui is a source dep only -- its compiled output is bundled into
client/dist/ at build time, so consumers don't need it at install time.
@dannon dannon force-pushed the feature/client-ui-package branch from fc089cd to da0a104 Compare April 28, 2026 20:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants