meshery/meshery

[UI] Restructure Phase 5.b. - Deduplicate Component (Reuse)

Open

#18,661 创建于 2026年4月10日

在 GitHub 查看
 (2 评论) (2 反应) (2 负责人)HTML (10,013 star) (3,101 fork)batch import
component/uiframework/reacthelp wantedkind/enhancementlanguage/javascript

描述

Prologue

NOTE: THIS IS A CHILD ISSUE FOR THE EPIC AT #18654 See design spec.

Phase 1 breakdown

This checklist breaks down the Modal system workstream in #18661 into contributor-sized requests. All migration tasks depend on #18751.

  • #18751
  • #18752
  • #18753
  • #18754
  • #18755
  • #18756

Guiding Principles

These are load‑bearing. The entire plan enforces these six rules.

  1. Sistent is the only UI kit. No file outside Sistent's internals may import from @mui/, @material-ui/, or @rjsf/mui. Period.
  2. Tokens, never literals. No hex, rgb, or named color string may appear in any .tsx/.ts file outside ui/theme/ (a single wrapper module - see §4). Colors come from theme.palette., spacing from theme.spacing(), breakpoints from theme.breakpoints..
  3. styled() over style={{}}. Inline style props are reserved for dynamic values that cannot be expressed in a styled component (e.g. transform: translate(x,y) for a draggable). Colors are never dynamic enough to justify inline.
  4. One concept, one home. Every domain (Designs, Workspaces, Connections, …) lives in exactly one folder. Cross‑cutting primitives live under ui/components/shared/.
  5. Size budget: 400 lines. Any component file > 400 lines is a refactor candidate; > 600 lines is blocked by lint warning; > 1000 lines is a hard error in CI.
  6. Discoverable filenames. No index.tsx as the only file in a folder. No generic style.tsx, utils.tsx, helpers.tsx, components.tsx - files are named for what they contain.

Implementation

1 Modal system

Today: 22 modal files, each reinventing open/close, header, footer, confirm button styling.

Target: ui/components/shared/Modal/ with exactly these files:

shared/Modal/
├── Modal.tsx # Base: children, onClose, title, size, actions
├── ConfirmModal.tsx # Wraps Modal: title, message, confirm/cancel
├── InfoModal.tsx # Wraps Modal: title, body (Markdown)
├── FormModal.tsx # Wraps Modal: integrates react-hook-form / RJSF
├── useModal.ts # Hook for imperative open/close
└── index.ts

Migration map:

Current file New home
ConfirmationModal.tsx ConfirmModal (delete file)
ExportModal.tsx FormModal instance in designs/export/ExportDesignModal.tsx
ViewInfoModal.tsx InfoModal instance in workspaces/ViewInfoModal.tsx
General/Modals/GenericModal.tsx Modal (delete file)
General/Modals/Modal.tsx Delete (consolidates into base Modal)
General/Modals/InfoModal.tsx InfoModal (delete)
General/Modals/EnvironmentModal.tsx environments/EnvironmentFormModal.tsx
General/Modals/ConnectionModal.tsx connections/ConnectionFormModal.tsx
General/Modals/PublishModal.tsx designs/PublishDesignModal.tsx
General/Modals/ImportModal.tsx designs/ImportDesignModal.tsx
Dashboard/UnsavedChangesModal.tsx shared/Modal/UnsavedChangesModal.tsx
RelationshipBuilder/CreateRelationshipModal.tsx registry/CreateRelationshipModal.tsx
Registry/RegistryModal.tsx registry/RegistryModal.tsx
Settings/Registry/ImportModelModal.tsx registry/ImportModelModal.tsx
Settings/Registry/CreateModelModal.tsx registry/CreateModelModal.tsx
TroubleshootingModalComponent.tsx shared/Troubleshooting/TroubleshootingModal.tsx
SpacesSwitcher/WorkspaceModal.tsx workspaces/WorkspaceFormModal.tsx
SpacesSwitcher/ShareModal.tsx workspaces/ShareWorkspaceModal.tsx
connections/meshSync/RegisterConnectionModal.tsx connections/RegisterConnectionModal.tsx
pages/extension/AccessMesheryModal.tsx layout/AccessMesheryModal.tsx

Every one of these becomes either <Modal>, <ConfirmModal>, <InfoModal>, or <FormModal>. The top‑level GenericModal / Modal.tsx / InfoModal.tsx duplicates disappear.

2 Card system

Create shared/Card/ResourceCard.tsx — a single flippable, menu‑enabled, status‑badge card. Today's MesheryPatternCard, FiltersCard, PerformanceCard, MesheryWorkspaceCard, environment-card, FlipCard all become thin instances passing content slots. Expected LOC savings: ~800.

3 Stepper system

Create shared/Stepper/Stepper.tsx that takes a steps array. Today's DeployStepper, RelationshipFormStepper, CSVStepper, UrlStepper, connections/meshSync/Stepper/* all become data‑driven instances. Expected LOC savings: ~600.

4 EmptyState, LoadingState, PageHeader

  • EmptyState — replace LoadingComponents/, EmptyState/K8sContextEmptyState.tsx, connections/meshSync/MeshSyncEmptyState.tsx, Lifecycle/General/empty-state/, and the ad‑hoc empty‑states inside SpacesSwitcher/*Content.tsx files.
  • LoadingState — absorbs LoadingComponents/Animations/* (6 animation files). Each animation is a variant.
  • PageHeader — every pages/* currently hand‑rolls a title bar. Replace with <PageHeader title={…} actions={…} breadcrumbs={…} />.

5 Icons

One folder: ui/assets/icons/. Rules:

  1. Delete ui/components/icons/ (1 file, an index.ts).
  2. Merge ui/assets/new-icons/*.svg (25 files) into ui/assets/icons/ as .tsx components (SVGs become React components for consistency with the existing 76 icons).
  3. Delete ui/components/shapes/ (2 files) → ui/assets/icons/shapes/.
  4. Any @mui/icons-material import is replaced by a Sistent icon or a typed SVG under ui/assets/icons/.

6 Hooks consolidation

  • ui/components/hooks/ (3 files) + ui/utils/hooks/ → merged under ui/utils/hooks/.
  • ui/themes/hooks.tsx (theme toggler) → ui/theme/useThemePreference.ts.

7 Workspaces consolidation

SpacesSwitcher/ (18 files) and Lifecycle/Workspaces/ (10 files) are two halves of the same feature. Merge into ui/components/workspaces/:

workspaces/
├── switcher/ # was: SpacesSwitcher/SpaceSwitcher, MenuComponent, MobileViewSwitcher
├── list/ # was: Lifecycle/Workspaces/Workspace{Grid,Data}View
├── content/ # was: SpacesSwitcher/*Content.tsx (5 files — should be 1 component + variants)
├── card/ # was: MesheryWorkspaceCard (now instance of shared/Card)
├── modals/ # WorkspaceFormModal, ShareModal
├── hooks/ # was: SpacesSwitcher/hooks.tsx
└── styles/ # was: SpacesSwitcher/styles.tsx + Lifecycle/Workspaces/styles.tsx merged

The 5 *Content.tsx files in SpacesSwitcher/ (MainDesignsContent, MainViewsContent, MyDesignsContent, MyViewsContent, RecentContent, SharedContent, WorkspaceContent) are all the same component with different props — collapse to 1 file with a variant prop.

8 Lifecycle consolidation

Lifecycle/ and DesignLifeCycle/ are unrelated despite the name collision.

  • Lifecycle/Environments/components/environments/
  • Lifecycle/Workspaces/components/workspaces/ (merged above)
  • Lifecycle/General/ → absorbed into shared/
  • DesignLifeCycle/components/designs/lifecycle/
  • Delete Lifecycle/ top‑level folder.

Acceptance Tests

  1. Modal/Card/Stepper count in app code drops to 1 canonical each. max-lines rule promoted to error at 600.

Contributor Guides and Handbook

贡献者指南