From 28698c85419369eaa93bfdeb85336dfe88f0daf8 Mon Sep 17 00:00:00 2001 From: Jason Morais Date: Thu, 16 Oct 2025 10:40:44 -0400 Subject: [PATCH] initial changes --- .../ui/components.instructions.md | 95 ++++----- .../ui/container-components.instructions.md | 59 +++--- .../instructions/ui/graphql.instructions.md | 183 +++++++++--------- .../instructions/ui/layouts.instructions.md | 181 ++++++----------- .github/instructions/ui/pages.instructions.md | 85 ++++---- .../presentational-components.instructions.md | 55 +++--- 6 files changed, 277 insertions(+), 381 deletions(-) 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)