diff --git a/.github/instructions/ui/components.instructions.md b/.github/instructions/ui/components.instructions.md index 08cfbadf7..ed5fe10f6 100644 --- a/.github/instructions/ui/components.instructions.md +++ b/.github/instructions/ui/components.instructions.md @@ -1,82 +1,53 @@ ---- applyTo: "apps/ui-sharethrift/src/components/**/*" --- # Copilot Instructions: UI Components -## Purpose - -- The `components` directory provides reusable UI building blocks for the applicant-facing web UI. -- Components are built with React, TypeScript, and leverage Ant Design and Tailwind CSS for styling. - -## Architecture & Patterns - -- **React + TypeScript**: Component-driven UI with strict typing for reliability and maintainability. -- **Ant Design & Tailwind CSS**: Use Ant Design components and theming wherever possible; use Tailwind CSS for custom styles. -- **Feature-based Structure**: Organize components and logic by feature or domain concept. -- **State Management**: Use React hooks and context for local and global state. Avoid prop drilling and trivial state management solutions. -- **Accessibility**: Ensure all components are accessible (ARIA, keyboard navigation, semantic HTML). - -## Coding Conventions - -- Use functional components and React hooks. -- Prefer composition over inheritance. -- Use strict TypeScript types for props, state, and context. -- Component name must match file name in PascalCase. Each component file should export a single component. -- Each component must have a corresponding `{ComponentName}Props` type defined. -- Use kebab-case for file and directory names. -- Use the [Container pattern](https://www.patterns.dev/react/presentational-container-pattern/) for separating concerns for data fetching/manipulation and presentation. -- Suffix container components with `Container` (e.g., `ProfileViewContainer`). - -## Styling +## Overview -- Use Ant Design components and theming for UI consistency. -- Use Tailwind CSS for custom component styles. -- Prefer CSS modules or scoped styles for custom styles if Tailwind is not suitable. +This directory contains reusable UI components for the applicant-facing web UI, built with **React**, **TypeScript**, **Ant Design**, and **Tailwind CSS**. -## State Management +## Principles -- Use React hooks (`useState`, `useEffect`, etc.) for local state. -- Use context or state management libraries only when necessary for shared/global state. +- **Component-driven & Typed**: Use functional React components with strict TypeScript typing. +- **Styling**: Prefer Ant Design components and theming; use Tailwind CSS or CSS Modules for custom styles. +- **Accessibility**: Ensure ARIA support, keyboard navigation, and semantic HTML. +- **Testing**: Every component must include a unit test and a Storybook story. -## Accessibility +## Structure & Naming -- Prefer components to be accessible (ARIA attributes, keyboard navigation, semantic HTML) where possible. -- Use accessible Ant Design components. +- Use the [Container Pattern](https://www.patterns.dev/react/presentational-container-pattern/): + - Suffix container components with `Container` (e.g., `ProfileViewContainer`). +- Component file must: + - Export a single PascalCase-named component. + - Include a `{ComponentName}Props` type. +- Use kebab-case for file and folder names. -## Testing +## State & Logic -- Write unit tests for components, especially for logic and rendering. -- Every component must have a corresponding Storybook story. +- Use `useState`, `useEffect`, and other React hooks for local state. +- Use React Context or state libraries only when shared/global state is needed. +- Avoid prop drilling and trivial state solutions. -## Error Handling +## Code Conventions -- Handle loading states gracefully. (e.g ``) -- Propagate error messages via Ant Design components (e.g. `message`) -- Use fallback UI for no data (e.g., ``) - -## Reusability - -- Make components reusable and composable. -- Avoid hardcoding values; use props and context. - -## Naming Conventions - -- Use PascalCase for component names. -- Suffix container components with `Container` (e.g., `ProfileViewContainer`). +- Prefer composition over inheritance. +- Memoize expensive computations (`useMemo`, `React.memo`). +- Avoid unnecessary re-renders. +- Make components composable and reusable—avoid hardcoded values. -## Performance +## UX & Error Handling -- Memoize expensive computations with `useMemo` or `React.memo`. -- Avoid unnecessary re-renders. +- Handle loading (``), empty states (``), and errors (`message`) gracefully. -## File Organization +## Organization -- Place shared components in the `shared/` folder. -- Place layout-specific components in the appropriate `layouts/` folder. +- Use `shared/` for common components. +- Use `layouts/` for layout-specific components. ## References -- [React Documentation](https://react.dev/) -- [Ant Design Documentation](https://ant.design/docs/react/introduce) -- [Storybook Documentation](https://storybook.js.org/docs/react/get-started/introduction) -- [TypeScript Handbook](https://www.typescriptlang.org/docs/) \ No newline at end of file +- [React](https://react.dev/) +- [Ant Design](https://ant.design/docs/react/introduce) +- [Tailwind CSS](https://tailwindcss.com/docs) +- [Storybook](https://storybook.js.org/docs/react/get-started/introduction) +- [TypeScript](https://www.typescriptlang.org/docs/) diff --git a/.github/instructions/ui/container-components.instructions.md b/.github/instructions/ui/container-components.instructions.md index 11b73c2c2..eb54bb256 100644 --- a/.github/instructions/ui/container-components.instructions.md +++ b/.github/instructions/ui/container-components.instructions.md @@ -1,54 +1,43 @@ ---- applyTo: "apps/ui-sharethrift/src/components/**/*.container.tsx" --- # Copilot Instructions: Container Components -## Purpose - -- Container components manage data fetching, business logic, and state for their corresponding presentational components. -- They separate concerns by isolating side effects, API calls, and state management from UI rendering. - -## Architecture & Patterns +## Overview -- **Container/Presentational Pattern**: Each container component (`*.container.tsx`) wraps a presentational component, passing props derived from state, context, or API responses. -- **Co-location**: Place container components next to their presentational counterparts and related `.graphql` files for maintainability. -- **GraphQL Integration**: Use Apollo Client hooks (`useQuery`, `useMutation`, etc.) for data operations. Import queries/mutations from adjacent `.graphql` files. +Container components handle **data fetching**, **state**, and **business logic**, separating concerns from UI rendering. They wrap and supply props to corresponding presentational components. -## Coding Conventions +## Principles -- Use functional components and React hooks. -- Suffix container components with `Container` (e.g., `ProfileViewContainer`). -- Component name must match file name in PascalCase. -- Each container must define a `{ComponentName}ContainerProps` type for its props. -- Use strict TypeScript types for all state, props, and API responses. -- Use kebab-case for file and directory names. -- Provide handler functions through display component props for all relevant actions (e.g., handleClick, handleChange, handleSubmit, handleSave). +- **Container/Presentational Pattern**: Container components (`*.container.tsx`) derive props from state, context, or API, and pass them to presentational components. +- **Colocation**: Place containers next to their UI counterparts and related `.graphql` files for clarity and maintainability. -## State Management +## Data & State -- Use React hooks (`useState`, `useEffect`, `useContext`) for local and shared state only when necessary. Avoid prop drilling and trivial state management solutions. +- Use **Apollo Client** hooks (`useQuery`, `useMutation`, etc.) for GraphQL operations. +- Use **React hooks** (`useState`, `useEffect`, `useContext`) for local and shared state when necessary. +- Use `ComponentQueryLoader` for standardized loading, error, and empty states. -## Data Fetching +## Code Conventions -- Use Apollo Client hooks for GraphQL queries and mutations. -- Leverage the shared `ComponentQueryLoader` component for consistent data fetching, loading, and error handling. +- Use functional components and strict TypeScript typing (`{ComponentName}ContainerProps`). +- Match file name and component name (PascalCase). +- Use `Container` suffix (e.g., `ProfileViewContainer`). +- Follow kebab-case for file and directory names. +- Provide handler props for actions (e.g., `handleClick`, `handleSubmit`). ## Error Handling -- Use the `ComponentQueryLoader` for consistent error handling and fallback UI via the optional `errorComponent` or `noDataComponent` props - -## Accessibility - -- Ensure all rendered UI is accessible, including loading and error states. - +- Use `ComponentQueryLoader` with `errorComponent` and `noDataComponent` props for graceful fallbacks. +- Ensure accessibility for loading/error states. -## File Organization +## File Structure -- Place container components in the same folder as their presentational components and related `.graphql` files. -- Align container and presentational components by keeping their file names consistent (e.g., `profile-view.container.tsx` and `profile-view.tsx`). +- Co-locate: + - Container and presentational components (e.g., `profile-view.container.tsx` + `profile-view.tsx`) + - Related `.graphql` files in the same directory. ## References -- [React Container/Presentational Pattern](https://www.patterns.dev/react/presentational-container-pattern/) -- [Apollo Client Docs](https://www.apollographql.com/docs/react/) -- [Ant Design Documentation](https://ant.design/docs/react/introduce) \ No newline at end of file +- [Container/Presentational Pattern](https://www.patterns.dev/react/presentational-container-pattern/) +- [Apollo Client](https://www.apollographql.com/docs/react/) +- [Ant Design](https://ant.design/docs/react/introduce) \ No newline at end of file diff --git a/.github/instructions/ui/graphql.instructions.md b/.github/instructions/ui/graphql.instructions.md index 997811901..59daab4a7 100644 --- a/.github/instructions/ui/graphql.instructions.md +++ b/.github/instructions/ui/graphql.instructions.md @@ -1,94 +1,93 @@ ---- -applyTo: "apps/ui-sharethrift/src/components/**/*.graphql" ---- - -## Copilot Instructions: GraphQL - -### Purpose - -- `.graphql` files in the frontend define GraphQL queries, mutations, and fragments for use with Apollo Client and React components. -- They enable type-safe, modular, and maintainable data fetching and manipulation. - -### Organization & Structure - -- Place `.graphql` files next to the component or container that uses them, typically in the same feature or layout folder. -- For a given container component, there should be a corresponding `.graphql` file with the same base name. (e.g `contact-details.container.graphql`) -- All queries, mutations, and fragments used in the container component should be defined in the corresponding `.graphql` file. - -### Coding Conventions - -- Queries and mutations should use the following naming convention `` - - Given a container component named `ContactDetailsContainer` in the `applicant` layout which uses the `ApplicantUser` query, the query name should be: `ApplicantContactDetailsContainerApplicantUser` -- Fragments should use the following naming convention `Fields` - - Given a container component named `ContactDetailsContainer` in the `applicant` layout, a fragment for the `ApplicantUser` type should be named: `ApplicantContactDetailsContainerUserFields` -- Always prefer reusable fragments over direct field access in queries/mutations. -- Use variables for dynamic values; avoid hardcoding IDs or parameters. -- Keep queries minimal—request only the fields needed by the component. -- Include the `id` fields on fragment types where the `id` field is present to ensure consistency in Apollo Cache. -- Ensure queries and mutations use the same fragment definitions to ensure consistency in Apollo Cache. - -### Integration - - -- Import `.graphql` files into TypeScript/JS files using codegen-generated types for type safety. -- Use Apollo Client hooks (`useQuery`, `useMutation`, etc.) with imported queries/mutations. -- Co-locate fragments with the components that use them for maintainability. - -### Apollo Client Link Chain Customization - -- Configure Apollo Client with a dynamic link chain to flexibly route operations to different data sources: - - **Batching**: Use a batching link (e.g., `BatchHttpLink`) to combine multiple GraphQL operations into a single HTTP request. This is why container components are allowed to define their own queries and mutations; the batching link can optimize their execution on the server. - - **Authentication & Custom Headers**: Add custom Apollo links to inject authentication tokens or other headers into requests. - - **REST Integration**: Use Apollo's REST link to fetch data from non-GraphQL APIs. Route specific operations to REST endpoints using a link map and split logic. Typical usage is for fetching JSON data from Azure Blob Storage. -- Example generalized setup: - ```ts - import { ApolloClient, InMemoryCache, ApolloLink, from } from '@apollo/client'; - import { BatchHttpLink } from '@apollo/client/link/batch-http'; - import { RestLink } from 'apollo-link-rest'; - - // Define links for different data sources - const batchGraphqlLink = new BatchHttpLink({ uri: '/graphql', batchMax: 10, batchInterval: 20 }); - const restApiLink = new RestLink({ uri: '/rest-api' }); - - // Custom links for authentication, headers, etc. - const authLink = new ApolloLink((operation, forward) => { - operation.setContext(({ headers = {} }) => ({ - headers: { - ...headers, - Authorization: 'Bearer ' - } - })); - return forward(operation); - }); - - // Link map for routing operations - const linkMap = { - CountryDetails: restApiLink, // Example: route 'CountryDetails' query to REST - default: from([authLink, batchGraphqlLink]) - }; - - // Dynamic split logic based on operation name - const dynamicLink = ApolloLink.split( - operation => operation.operationName in linkMap, - new ApolloLink((operation, forward) => { - const link = linkMap[operation.operationName as keyof typeof linkMap] || linkMap.default; - return link.request(operation, forward); - }), - linkMap.default - ); - - const client = new ApolloClient({ - cache: new InMemoryCache(), - link: dynamicLink - }); - ``` -- You can extend this pattern to route based on context, operation type, or other criteria. Update the link chain dynamically (e.g., on authentication changes) as needed. - -### Testing - -- Mock queries and mutations in Storybook stories and unit tests using Apollo Client's mocking utilities. - -### Example Structure +# Copilot Instructions: GraphQL Files + +`.graphql` files define queries, mutations, and fragments used with **Apollo Client** in React components. They support **type-safe**, **modular**, and **maintainable** data access. + +## Organization + +- Co-locate `.graphql` files with related container and presentational components. +- Use consistent base filenames (e.g., `contact-details.container.graphql` for `contact-details.container.tsx`). +- Define all GraphQL operations used by a container in its corresponding `.graphql` file. + +## Naming Conventions + +- **Queries & Mutations**: + Format: `` + Example: `ApplicantContactDetailsContainerApplicantUser` + +- **Fragments**: + Format: `Fields` + Example: `ApplicantContactDetailsContainerUserFields` + +## Coding Guidelines + +- Use Apollo variables—avoid hardcoded IDs or params. +- Keep queries minimal; only fetch fields needed by the component. +- Prefer reusable **fragments** over inline fields. +- Always include `id` in fragments where applicable to support Apollo cache normalization. +- Reuse consistent fragments across queries and mutations for cache alignment. + +## Integration + +- Import `.graphql` files using codegen-generated types. +- Use Apollo hooks (`useQuery`, `useMutation`) in container components. +- Co-locate fragments with the components that consume them. + +## Apollo Link Chain + +Apollo Client is configured with a **custom link chain** to flexibly route GraphQL and REST operations: + +- **Batching**: Use `BatchHttpLink` to group GraphQL operations into a single request. +- **Auth & Headers**: Use `ApolloLink` to inject headers and tokens. +- **REST Support**: Use `RestLink` for non-GraphQL APIs (e.g., Azure Blob Storage). +- **Dynamic Routing**: Route operations using a `linkMap` and `ApolloLink.split`. + +### Example Link Chain Setup + +```ts +import { ApolloClient, InMemoryCache, ApolloLink, from } from '@apollo/client'; +import { BatchHttpLink } from '@apollo/client/link/batch-http'; +import { RestLink } from 'apollo-link-rest'; + +const batchGraphqlLink = new BatchHttpLink({ uri: '/graphql', batchMax: 10, batchInterval: 20 }); +const restApiLink = new RestLink({ uri: '/rest-api' }); + +const authLink = new ApolloLink((operation, forward) => { + operation.setContext(({ headers = {} }) => ({ + headers: { + ...headers, + Authorization: 'Bearer ', + } + })); + return forward(operation); +}); + +const linkMap = { + CountryDetails: restApiLink, + default: from([authLink, batchGraphqlLink]), +}; + +const dynamicLink = ApolloLink.split( + op => op.operationName in linkMap, + new ApolloLink((op, forward) => { + const link = linkMap[op.operationName] || linkMap.default; + return link.request(op, forward); + }), + linkMap.default +); + +const client = new ApolloClient({ + cache: new InMemoryCache(), + link: dynamicLink, +}); +``` + +> You can extend this pattern to route based on context, auth state, or operation type. + +## Testing + +- Use Apollo mocking utilities to simulate queries/mutations in unit tests and Storybook stories. + +## Example Structure ``` components/ @@ -99,7 +98,7 @@ components/ my-component.tsx ``` -### References +## References - [Apollo Client Docs](https://www.apollographql.com/docs/react/) - [GraphQL Specification](https://spec.graphql.org/) \ No newline at end of file diff --git a/.github/instructions/ui/layouts.instructions.md b/.github/instructions/ui/layouts.instructions.md index 4dad67b58..48d15588d 100644 --- a/.github/instructions/ui/layouts.instructions.md +++ b/.github/instructions/ui/layouts.instructions.md @@ -1,161 +1,108 @@ ---- -applyTo: "apps/ui-sharethrift/src/components/layouts/**/*" ---- - # Copilot Instructions: Layouts -## Internal References -- ui.instructions.md -- components.instructions.md -- pages.instructions.md -- container-components.instructions.md -- presentational-components.instructions.md +The `layouts/` directory defines shared page scaffolding and route structures for the applicant-facing UI. Layouts wrap content in consistent structure (headers, sidebars, footers) and control top-level routing. ## Purpose -- The `layouts` directory provides reusable layout components and containers for structuring pages and feature flows in the applicant-facing web UI. -- Layouts define page scaffolding, routing, and shared UI regions (headers, footers, sidebars). +- Define reusable layout components for app sections. +- Encapsulate routing, navigation, and shared UI regions. +- Use for authenticated and unauthenticated flows (e.g., `root/` layout). -## Architecture & Patterns +## Patterns & Structure -- **React + TypeScript**: Use functional components with strict typing for reliability and maintainability. -- **Feature-based Structure**: Organize layouts by feature or domain concept (e.g., applicant, cases, shared). -- **Composition**: Prefer composition over inheritance; layouts should wrap or compose child components. +- **React + TypeScript**: Use functional components with strict typing. +- **Feature-Based Layouts**: Organize by domain (e.g., `applicant/`, `cases/`, `shared/`). +- **Composition over Inheritance**: Wrap child content using layout components. -## Coding Conventions +## File Conventions -- Use functional components and React hooks. -- Each layout component must have a corresponding `{ComponentName}Props` type. -- Component name must match file name in PascalCase. Each file should export a single component. -- Use kebab-case for file and directory names. +- Use **PascalCase** for component names and matching file names. +- Use **kebab-case** for file/folder paths. - Suffix container components with `Container` (e.g., `SectionLayoutContainer`). -- Use absolute imports from the `src` root. -- Group imports: external libraries first, then internal modules. +- Use absolute imports from `src/`. ## Routing & Navigation -- **Each layout must have an `index.tsx` file that defines all top-level routes for that layout.** - - These routes are mapped to page components from the `pages/` folder. - - The top-level routes in `index.tsx` appear in the sidebar navigation menu. - - Each route uses a page component from `pages/` as its `element`. - - The sidebar navigation is built from the layout's route configuration and reflects these top-level routes. - - The component name in `index.tsx` should match the layout name in PascalCase. -- **Page components in `pages/` must be mapped in `index.tsx` to be accessible via navigation.** +- Each layout must include an `index.tsx` that defines all top-level routes. +- These routes: + - Map to page components from `pages/`. + - Drive the sidebar navigation menu. + - Use the layout’s main component as the top-level wrapper (e.g., `SectionLayoutContainer`). +- Route config (`pageLayouts`) includes path, title, icon, ID, and optional `parent` key. -### Example: Mapping Routes to Page Components in `index.tsx` +### Example Route Mapping ```tsx -import { Routes, Route } from 'react-router-dom'; -import { SectionLayoutContainer } from './section-layout.container'; -import { Home } from './pages/home'; -import { Members } from './pages/members'; -// ...other imports - -const pageLayouts = [ - { path: '', title: 'Home', icon: , id: 'ROOT' }, - { path: 'members/*', title: 'Members', icon: , id: 5, parent: 'ROOT' }, - // ...other layouts -]; - -export const Admin = () => ( - - }> - } /> - } /> - {/* ...other routes */} - - -); +}> + } /> + } /> + ``` -This pattern ensures each top-level route in `index.tsx` is mapped to a page component from the `pages/` folder and appears in the sidebar navigation. - ## Styling -- Use Ant Design components and theming for UI consistency. -- Use Tailwind CSS for custom styles as needed. -- Prefer CSS modules or scoped styles for custom styles if Tailwind inline styles become extensive. +- Use **Ant Design** for consistent components. +- Use **Tailwind CSS** for custom styles. +- Use scoped styles or CSS modules if Tailwind isn't sufficient. -## State Management +## State & Data -- Use React hooks (`useState`, `useEffect`, etc.) for local state. -- Use context or state management libraries only when necessary for shared/global state. - -## Accessibility - -- Ensure layouts are accessible (ARIA attributes, keyboard navigation, semantic HTML). -- Use accessible Ant Design components for navigation and structure. +- Use React hooks (`useState`, `useEffect`) for local state. +- Use context or external state libraries only when necessary. +- Use GraphQL via Apollo hooks in containers (if needed). ## Error Handling -- Handle loading and error states gracefully (e.g., ``, ``, ``). -- Provide fallback UI for errors and blocked access. +- Handle loading and error states with ``, ``, ``, etc. +- Provide fallback UI for blocked access or no data. -## Reusability +## Accessibility -- Make layouts reusable and composable for different page types and flows. -- Avoid hardcoding values; use props and context. +- Ensure layouts and nav are accessible (ARIA, keyboard support, semantic HTML). +- Use accessible Ant Design components. ## Testing -- Write unit tests for layout components. -- Every layout should have a corresponding Storybook story. +- Each layout should have: + - Unit tests + - A Storybook story + - Optional container tests if logic is non-trivial ## Performance -- Memoize expensive computations with `useMemo` or `React.memo`. +- Memoize layout components or logic-heavy sections (`useMemo`, `React.memo`). - Avoid unnecessary re-renders. ## Folder Structure ``` layouts/ -|-- root/ # Required: unauthenticated entry point for the application -| |-- index.tsx # Required: defines page layouts and configures available routes -| |-- section-layout.tsx # Required: shared structure for all pages in this layout -| |-- sub-page-layout.tsx # Optional: additional shared layout structure for sub-pages -| |-- components/ # Required: supporting components -| | |-- {component-name}.container.graphql # Optional: GraphQL queries/mutations/fragments -| | |-- {component-name}.container.tsx # Optional: container for data fetching and logic -| | |-- {component-name}.stories.tsx # Required: Storybook stories for the presentational component -| | |-- {component-name}.tsx # Required: presentational component for rendering the data -| |-- pages/ # Required: page components using container components to render full pages -| | |-- {component-name}.tsx # Required: page component for rendering the full page -| | |-- {component-name}.stories.tsx # Required: Storybook stories for the page component -| |-- ... -|-- {layout-name}/ # Optional: layouts for a specific section of the application -| |-- index.tsx # Required: defines page layouts and configures available routes -| |-- section-layout.container.graphql # Optional: GraphQL queries/mutations/fragments for section layout -| |-- section-layout.container.tsx # Optional: container for data fetching and logic for section layout -| |-- section-layout.tsx # Required: shared structure for all pages in this layout -| |-- sub-page-layout.tsx # Optional: additional shared layout structure for sub-pages -| |-- components/ # Required: supporting components -| | |-- ... -| |-- pages/ # Optional: page components using container components to render full pages -| | |-- ... -| |-- ... -|-- ... + root/ + index.tsx # Required: route config + section-layout.tsx # Required: shared layout wrapper + sub-page-layout.tsx # Optional + components/ # Supporting layout components + pages/ # Page components rendered by routes + {layout-name}/ + index.tsx + section-layout.tsx + components/ + pages/ ``` -- The `root` layout is always required and provides the global scaffolding and entry points for the application (e.g., top-level routing, authentication, global UI regions). -- Additional layout folders (for features, roles, or business domains) are included as needed, based on the application's business requirements and structure. -- Every layout folder must include: - - `section-layout.tsx`: The shared structure component that all pages in the layout must use. - - `index.tsx`: The entry point for the layout, defining available routes and ensuring each route uses the section layout. -- Each feature folder may also include: - - Supporting components (e.g., header.tsx, footer.tsx, navigation, etc.). - - GraphQL fragments/queries, if applicable. - - Storybook stories and tests for each layout component. - - Container components for data fetching and logic separation. - - Sub-page layouts for additional structure. - - Page components for individual views. -- Use kebab-case for file and directory names. -- Use PascalCase for component names. -- Avoid deeply nested folders; keep structure clear and maintainable. +- `root/` is always required as the unauthenticated/global entry point. +- Each layout must include `section-layout.tsx` and `index.tsx`. +- Layouts may also include: + - GraphQL queries/mutations (`*.container.graphql`) + - Container components for layout-level logic + - Presentational components + - Storybook stories + - Sub-page layouts for complex flows + ## References -- [React Documentation](https://react.dev/) -- [Ant Design Documentation](https://ant.design/docs/react/introduce) -- [Storybook Documentation](https://storybook.js.org/docs/react/get-started/introduction) +- [React Docs](https://react.dev/) +- [Ant Design](https://ant.design/docs/react/introduce) +- [Storybook Docs](https://storybook.js.org/docs/react/get-started/introduction) - [TypeScript Handbook](https://www.typescriptlang.org/docs/) -- [MDN Accessibility Guide](https://developer.mozilla.org/en-US/docs/Web/Accessibility) +- [MDN Accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility) diff --git a/.github/instructions/ui/pages.instructions.md b/.github/instructions/ui/pages.instructions.md index 5c52bdc5a..5ebbee1a4 100644 --- a/.github/instructions/ui/pages.instructions.md +++ b/.github/instructions/ui/pages.instructions.md @@ -1,65 +1,58 @@ ---- -applyTo: "apps/ui-sharethrift/src/components/layouts/**/pages/*.tsx" ---- +# Copilot Instructions: Page Components -# Copilot Instructions: Pages - -## Internal References -- ui.instructions.md -- components.instructions.md -- layouts.instructions.md -- container-components.instructions.md +Page components in the `pages/` folder represent top-level routes within a layout. They compose UI from reusable components and containers and are mapped via the layout’s `index.tsx`. ## Purpose -- The `pages` folder contains page-level React components for a specific layout. -- Each page component represents a distinct route/view and is mapped in the layout's `index.tsx`. -- Pages are composed of components from the layout's `components/` folder wrapped in the layout's `SubPageLayout` component. +- Define route-level views tied to a layout. +- Use components from the layout’s `components/` folder. +- Wrap content in `SubPageLayout` to ensure consistent headers/structure. ## Page Types - **Single Page**: - - Implements a single view using `SubPageLayout` for header/content. - - Can include subpages/tabs via the shared `VerticalTabs` component. - - Example: + - A single view using `SubPageLayout`. + - May include `VerticalTabs` for internal tabs. + - Example: ```tsx - // example-page.tsx - import { SubPageLayout } from '../layouts/sub-page-layout'; - import { ExampleComponent } from '../components/example-component'; + Title}> + + + ``` - export const ExamplePage: React.FC = () => ( - Example Page}> - - - ); +- **Page Group**: + - Defines multiple sub-routes using nested ``. + - Used for multi-view flows (e.g. list/detail/create). + - Example: + ```tsx + + } /> + } /> + } /> + ``` -- **Page Group (Multi-View Section)**: - - Implements a set of nested `Routes` for a section, each route providing its own page component. - - Used for sections with multiple related views (e.g., `properties.tsx`, `service-tickets.tsx`). - - Example: - ```tsx - // properties.tsx - - } /> - } /> - } /> - - ``` -## Coding Conventions +## Conventions - Use functional components and React hooks. -- Compose pages from reusable components and containers. -- Define `{PageName}Props` type for each page. -- Use strict TypeScript types. +- Define a `{PageName}Props` type for each page. +- Use strict TypeScript types for props and local state. - Use kebab-case for file names. +- Compose pages from containers and presentational components. + +## Composition Patterns + +- Wrap single pages in `SubPageLayout`. +- Use `VerticalTabs` for tabbed interfaces. +- Use nested `Routes` for multi-view page groups. -## Composition +## Testing & Storybook -- Use `SubPageLayout` for single pages. -- Use `VerticalTabs` for tabbed subpages. -- Use nested `Routes` for page groups. +- Every page component must have a corresponding Storybook story. +- Write unit tests if logic or branching is non-trivial. -## Testing & Reusability +## References -- Each page component must have a Storybook story. \ No newline at end of file +- [React Docs](https://react.dev/) +- [Storybook Docs](https://storybook.js.org/docs/react/get-started/introduction) +- [TypeScript Handbook](https://www.typescriptlang.org/docs/) diff --git a/.github/instructions/ui/presentational-components.instructions.md b/.github/instructions/ui/presentational-components.instructions.md index 9af57932d..8056df221 100644 --- a/.github/instructions/ui/presentational-components.instructions.md +++ b/.github/instructions/ui/presentational-components.instructions.md @@ -1,53 +1,50 @@ ---- -applyTo: "apps/ui-sharethrift/src/components/**/!(*.container).tsx" ---- - # Copilot Instructions: Presentational Components +Presentational components (`*.tsx` excluding `.container.tsx`) render UI based on props and manage only local UI state. They do not handle data fetching, side effects, or business logic. + ## Purpose -- Presentational components are responsible for rendering UI based on props. -- They are stateless or only manage local UI state, and do not perform data fetching or business logic. -- They receive all data and handler functions via props from container components. +- Render UI using props passed from container components. +- Remain stateless or handle only local UI state. +- Accept data and callbacks via props; do not fetch data or manage global state. ## Architecture & Patterns -- **Container/Presentational Pattern**: Presentational components (`*.tsx` files without `.container.` in the name) are paired with container components that handle data and logic. -- **Co-location**: Place presentational components next to their container counterparts and related `.graphql` files for maintainability. -- **Props-Driven**: Accept all data, state, and event handlers as props. Do not fetch data or manage global state. +- Follows the **Container/Presentational** pattern. +- Co-locate with their `.container.tsx` and `.graphql` counterparts. +- Use strict prop typing (`{ComponentName}Props`). -## Coding Conventions +## Conventions -- Use functional components and React hooks for local UI state only. -- Component name must match file name in PascalCase. -- Define a `{ComponentName}Props` type for all props. -- Use strict TypeScript types for all props and local state. -- Use kebab-case for file and directory names. -- Do not perform side effects, API calls, or business logic in presentational components. -- Use handler props for all user actions (e.g., `onClick`, `onChange`, `onSubmit`). +- Functional components only; use React hooks for local state. +- File/component name must match, in **PascalCase**. +- Use **kebab-case** for file and folder names. +- Define and export a `{ComponentName}Props` type. +- Use handler props (e.g., `onClick`, `onChange`, `onSubmit`) for all user actions. +- No side effects, API calls, or global state logic. ## Styling -- Use Ant Design components and theming for UI consistency. -- Use Tailwind CSS for custom styles if needed. -- Prefer CSS modules or scoped styles for custom styles if Tailwind is not suitable. +- Use Ant Design components and theming for consistency. +- Use Tailwind CSS for custom styles when needed. +- Prefer CSS modules or scoped styles when Tailwind isn’t sufficient. ## Accessibility -- Ensure all rendered UI is accessible (ARIA attributes, keyboard navigation, semantic HTML). -- Use accessible Ant Design components. +- Ensure accessible markup: ARIA, keyboard support, semantic HTML. +- Use accessible Ant Design components when possible. ## Testing -- Write unit tests for presentational components, focusing on rendering and interaction. -- Every presentational component should have a corresponding Storybook story. +- Write unit tests focused on rendering and UI interaction. +- Every presentational component must have a Storybook story. -## File Organization +## Organization -- Place presentational components in the same folder as their container components and related `.graphql` files. -- Align file names with container components (e.g., `profile-view.tsx` and `profile-view.container.tsx`). +- Co-locate with containers and related GraphQL files. +- Align file names (e.g., `profile-view.tsx` and `profile-view.container.tsx`). ## References - [React Container/Presentational Pattern](https://www.patterns.dev/react/presentational-container-pattern/) -- [Ant Design Documentation](https://ant.design/docs/react/introduce) \ No newline at end of file +- [Ant Design Docs](https://ant.design/docs/react/introduce) diff --git a/.github/instructions/ui/ui.instructions.md b/.github/instructions/ui/ui.instructions.md index 01c29c91e..ba9309353 100644 --- a/.github/instructions/ui/ui.instructions.md +++ b/.github/instructions/ui/ui.instructions.md @@ -6,88 +6,70 @@ applyTo: "apps/ui-sharethrift/src/components/ui/**/*" ## Purpose -- The `ui` folder implements the Atomic Design methodology for composing reusable UI components specific to this package. -- Components are organized as **molecules** (small, focused, tailored Ant Design-based components) and **organisms** (composed, more complex components). -- These components are intended to be shared across layouts and features within the package. +- The `ui` folder implements the Atomic Design methodology to organize reusable UI components. +- It contains **molecules** (small, focused components) and **organisms** (composed, higher-order components). +- Components are shared across layouts and features within the package. ## Atomic Design Structure -- **Molecules**: - - Small, reusable components that extend or tailor Ant Design primitives for project-specific needs. - - Should encapsulate a single, focused piece of functionality. - - Can be used directly by other code or composed into organisms. - - Example: custom input fields, loaders, upload buttons, user status indicators. - -- **Organisms**: - - More complex components composed of molecules (and possibly other organisms). - - Represent higher-level UI sections or widgets. - - Example: dropdown menus, form sections, headers, composite lists. +- **Molecules**: Extend or customize Ant Design primitives. Examples: loaders, buttons, input fields. +- **Organisms**: Built from molecules and represent more complex UI compositions. Examples: headers, dropdowns, form sections. ## Architecture & Patterns -- Use **React** functional components with **TypeScript** for strict typing and maintainability. +- Use React functional components with TypeScript. - Prefer composition over inheritance. -- Use the **container pattern** for data-fetching and logic separation when needed (suffix with `Container`). -- Use **Ant Design** components as the atomic base; extend with custom logic or styling as molecules. -- Use **Tailwind CSS** for custom utility styles; use CSS modules for scoped, component-specific styles when Tailwind is not suitable. +- Use Ant Design as the base for all UI components. +- Use Tailwind CSS for utility styles; use CSS modules (`*.module.css`) for scoped component styles. +- Use the container pattern for components that handle logic or data-fetching (suffix with `Container`). ## Coding Conventions -- Component name must match file name in PascalCase. Each file should export a single component. -- Each component must have a corresponding `{ComponentName}Props` type/interface. -- Use kebab-case for file and directory names. -- Co-locate tests (`.test.tsx`), stories (`.stories.tsx`), and styles (`.module.css`) with the component. -- Place a `README.md` in each component folder to document purpose and usage. +- Component name must match file name in PascalCase. +- Use kebab-case for all file and directory names. +- Define a `{ComponentName}Props` interface or type for every component. +- Co-locate all related files: component (`index.tsx`), test (`index.test.tsx`), story (`index.stories.tsx`), styles (`index.module.css`), and README (`README.md`). ## Styling -- Use Ant Design theming for UI consistency. -- Use Tailwind CSS for utility-first custom styles. -- Use CSS modules (`*.module.css`) for encapsulated, reusable component styles. -- Place `.module.css` files next to their component, using the same base name. +- Use Ant Design theming for consistency. +- Use Tailwind CSS for custom utility styling. +- Use CSS modules for encapsulated, reusable styles. ## Reusability & Composition -- Design molecules to be reusable and composable. +- Design molecules to be reusable across features and layouts. - Compose organisms from molecules and other organisms. -- Avoid hardcoding values; use props and context for configuration. +- Use props and context; avoid hardcoding values. ## Testing -- Every component must have a corresponding Storybook story and unit test. -- Use React Testing Library and Vitest for tests. +- Every component must include a Storybook story and unit test. +- Use React Testing Library and Vitest for all tests. ## Performance -- Memoize expensive computations with `useMemo` or `React.memo`. -- Avoid unnecessary re-renders. +- Use `useMemo` or `React.memo` to avoid unnecessary re-renders. ## File/Folder Structure - ``` ui/ - molecules/ # Small, focused, reusable components - {component-name}/ # Co-locate all files related to the molecule - index.module.css # Scoped CSS module (optional) - index.test.tsx # Unit test (required) - index.stories.tsx # Storybook story for molecule (required) - index.tsx # Entry point for the molecule (required) - component-name.test.tsx # Unit test for {component-name} (optional) - component-name.stories.tsx # Storybook story for {component-name} (optional) - component-name.tsx # Component used in this molecule (optional) - README.md # Usage and API documentation (recommended) - organisms/ # Composed, complex components made from molecules - {component-name}/ # Co-locate all files related to the organism - ... # Same as molecules - - ui.instructions.md # Copilot instructions for this folder + molecules/ + {component-name}/ + index.tsx + index.test.tsx + index.stories.tsx + index.module.css + README.md + organisms/ + {component-name}/ + ... + ui.instructions.md ``` -**Notes:** -- Each component should have its own folder if it includes multiple files (component, styles, tests, stories, etc.). -- Use kebab-case for directory names and file names. -- Co-locate all related files (component, test, story, styles, README) for maintainability. +- Each component gets its own folder if it includes multiple files. +- Co-locate component, test, story, styles, and docs in the same folder. ## References @@ -96,4 +78,4 @@ ui/ - [React Documentation](https://react.dev/) - [Ant Design Documentation](https://ant.design/docs/react/introduce) - [Storybook Documentation](https://storybook.js.org/docs/react/get-started/introduction) -- [TypeScript Handbook](https://www.typescriptlang.org/docs/) \ No newline at end of file +- [TypeScript Handbook](https://www.typescriptlang.org/docs/) diff --git a/packages/sthrift/graphql/.github/instructions/api-graphql.instructions.md b/packages/sthrift/graphql/.github/instructions/api-graphql.instructions.md index c646fc154..eb0f46ce7 100644 --- a/packages/sthrift/graphql/.github/instructions/api-graphql.instructions.md +++ b/packages/sthrift/graphql/.github/instructions/api-graphql.instructions.md @@ -1,87 +1,74 @@ -```instructions --- applyTo: "packages/sthrift/graphql/**/*.ts" --- # Copilot Instructions: @sthrift/graphql -## Purpose -- This package provides GraphQL API endpoints for the CellixJS DDD application. -- Implements Apollo Server v4 integrated with Azure Functions for serverless GraphQL hosting. -- Serves as the API gateway exposing domain functionality through GraphQL schemas and resolvers. -- Bridges the GraphQL layer with domain services through the Cellix service registry. +## Summary +Provides GraphQL API endpoints for Sharethrift (DDD) using Apollo Server v4 and Azure Functions. Acts as an API gateway bridging domain services via the Cellix service registry. -## Architecture & Patterns -- **Apollo Server v4**: Modern GraphQL server with full Apollo ecosystem integration. -- **Azure Functions Integration**: Custom adapter for Azure Functions v4 runtime. -- **Domain-Driven Design**: GraphQL resolvers interact with domain aggregates via unit of work patterns. -- **Context Injection**: Domain data sources and services injected through GraphQL context. -- **Type Safety**: Full TypeScript integration with strong typing for schemas, resolvers, and context. +## Architecture +- **Apollo Server v4** + custom **Azure Functions v4 adapter** +- **DDD**: Resolvers access aggregates via Unit of Work +- **Context Injection**: Domain data/services passed via GraphQL context +- **Type Safety**: Fully typed schemas, resolvers, and context using TypeScript -## Core Components -- **Schema Definition**: GraphQL type definitions using SDL (Schema Definition Language). -- **Resolvers**: Functions that fetch data for GraphQL fields, connected to domain services. -- **Context**: Request-scoped data including domain data sources, authentication, and services. -- **Azure Functions Adapter**: Custom middleware bridging Apollo Server and Azure Functions. +## Components +- **Schemas**: SDL defined via `#graphql` literals in `schema/types` +- **Resolvers**: Map fields to domain services in `schema/resolvers` +- **Context**: Defined in `context.ts`, includes `apiContext`, auth, etc. +- **Adapter**: `azure-functions.ts` connects Apollo Server to Azure Functions ## Coding Conventions -- Use TypeScript interfaces for GraphQL context types extending `BaseContext`. -- Define schemas using tagged template literals with `#graphql` comment for syntax highlighting. -- Resolvers should follow GraphQL resolver signature: `(parent, args, context, info)`. -- Access domain services through the injected `apiContext` in GraphQL context. -- Use proper error handling and return GraphQL-compatible error objects. -- Follow Apollo Server v4 patterns and best practices. +- Use TypeScript interfaces extending `BaseContext` +- Resolvers follow `(parent, args, context, info)` signature +- Access services via `context.apiContext` +- Errors should conform to GraphQL/Apollo error structures +- Follow Apollo Server v4 best practices -## File/Folder Structure +## File Structure ``` src/ -├── index.ts # Main GraphQL handler factory -├── azure-functions.ts # Azure Functions adapter for Apollo Server -├── context.ts # GraphQL context types and builders -├── schema/ # GraphQL schema definitions (future) -│ ├── types/ # Type definitions -│ └── resolvers/ # Resolver implementations -└── middleware/ # GraphQL middleware (auth, validation, etc.) +├── index.ts # GraphQL handler factory +├── azure-functions.ts # Azure adapter for Apollo Server +├── context.ts # Context types and builders +├── schema/ +│ ├── types/ # GraphQL SDL definitions +│ └── resolvers/ # Resolver implementations +└── middleware/ # Middleware for auth, validation, etc. ``` ## Integration with CellixJS -- Registered with Cellix service container via `graphHandlerCreator`. -- Receives `ApiContextSpec` containing domain data sources. -- Access domain aggregates through unit of work patterns. -- Follows established error handling and logging patterns. +Registered using `graphHandlerCreator`, consuming `ApiContextSpec` to access domain services via unit of work. Follows standard Cellix error handling and logging patterns. -## GraphQL Context Structure -```typescript +## GraphQL Context Example +```ts interface GraphContext extends BaseContext { - apiContext: ApiContextSpec; // Domain data sources and services + apiContext: ApiContextSpec; // Add authentication, user context, etc. } ``` ## Azure Functions Integration -- Uses custom adapter in `azure-functions.ts` for Apollo Server v4 compatibility. -- Handles HTTP request/response transformation between Azure Functions and Apollo. -- Supports both GET and POST requests with proper content-type handling. -- Includes error handling and proper HTTP status codes. +Custom adapter in `azure-functions.ts` transforms HTTP requests/responses for Apollo. Supports GET/POST with content-type handling, error formatting, and HTTP status codes. ## Testing -- Unit tests required for all resolvers using mocked domain services. -- Integration tests should test full GraphQL queries against real schema. -- Use Apollo Server testing utilities for schema validation. -- Test Azure Functions integration with proper request/response mocking. +- Unit tests for all resolvers using mocked domain services +- Integration tests run real GraphQL queries against schema +- Use Apollo Server testing tools for schema validation +- Test Azure integration with mocked HTTP requests/responses -## Performance Considerations -- Implement proper GraphQL query complexity analysis and limiting. -- Use DataLoader pattern for efficient database queries and N+1 prevention. -- Consider query depth limiting and timeout handling. -- Leverage Apollo Server caching mechanisms appropriately. +## Performance +- Implement query complexity and depth limits +- Use DataLoader to prevent N+1 issues +- Add timeout handling and Apollo caching as needed ## Security -- Implement authentication middleware in GraphQL context. -- Use domain-level authorization through passport/visa patterns. -- Validate and sanitize all input arguments. -- Implement rate limiting and query complexity analysis. +- Auth middleware added to context +- Use domain-level auth via passport/visa patterns +- Sanitize/validate inputs +- Apply rate limiting and query analysis ## Examples -- To add a new query: Define in schema, implement resolver, connect to domain service. -- To access domain data: Use `context.apiContext.domainDataSource.{Context}.{Aggregate}.{UnitOfWork}`. -- To handle errors: Throw GraphQL-compatible errors or use Apollo Server error extensions. \ No newline at end of file +- **New query**: Add to schema → implement resolver → connect to domain +- **Access domain data**: `context.apiContext.domainDataSource.{Context}.{Aggregate}.{UnitOfWork}` +- **Error handling**: Throw GraphQL errors or use Apollo error extensions