Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,10 @@ specs @rajsite @jattasNI @atmgrifter00 @mollykreis
# .snyk security scanning configuration file
/.snyk @chris468 @cameronwaterman @BKnight760 @rbell517 @jattasNI @prestwick

# AI Instructions
/.github/prompts @fredvisser
copilot-instructions.md @fredvisser
agents.md @fredvisser

# Change files don't need explicit reviewers
/change
38 changes: 38 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Nimble Design System – Global AI Instructions

## Quick Orientation
- **Core**: Web Components (FAST Foundation) in `packages/nimble-components`.
- **Wrappers**: Angular, Blazor, and React wrappers live in their respective workspaces.
- **Truth**: The `CONTRIBUTING.md` files are the single source of truth. **Read them** before starting complex tasks.

## Core Workflows
```bash
# Install & build everything
npm install && npm run build

# Storybook + tests (run from repo root)
npm run storybook
npm run tdd -w @ni/nimble-components
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this command was removed, npm run test-chrome -w @ni/nimble-components will do iterative component build and run tests


# Generate change files before PRs that touch published packages
npm run change
```

## Change Management
- Every PR impacting a published package needs a beachball change file (`npm run change`). See the "Beachball change file" section of [`CONTRIBUTING.md`](../CONTRIBUTING.md).
- Keep builds/test scripts passing locally before queuing CI.

## Common Pitfalls
- ❌ Forgetting `npm run change` when touching published packages.
- ❌ Styling component state via classes instead of attributes/behaviors.
- ❌ Hardcoding tag names inside templates instead of importing tag constants.
- ❌ Skipping Storybook docs/matrix updates when component APIs change.
- ❌ Not running formatter/tests before pushing (`npm run format`, `npm run tdd:watch`).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tdd:watch also removed, should probably just run the test command like above


## Key References
- Architecture: `docs/Architecture.md`
- Repo contributing guide: `CONTRIBUTING.md`
- Nimble component guide: `packages/nimble-components/CONTRIBUTING.md`
- CSS guidelines: `packages/nimble-components/docs/css-guidelines.md`
- Storybook authoring guide: `packages/storybook/CONTRIBUTING.md`
- Specs overview: `specs/README.md`
75 changes: 75 additions & 0 deletions .github/prompts/nimble.update-agent-instructions.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
name: nimble.update-agent-instructions
description: Synchronize the AI coding agent instructions with the latest project documentation and patterns.
---

**Goal**: Synchronize the AI coding agent instructions with the latest project documentation, patterns, and VS Code best practices (using directory-scoped `agents.md` files).

**Role**: You are an expert maintainer of the Nimble Design System. Your job is to ensure that the instructions provided to AI agents are accurate, concise, up-to-date, and structured to create effective "Agents.md" instructions.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONTRIBUTING should be updated with more detail on how humans are supposed to trigger this action.

Also. as commented in different files this is generating lots of incorrect content in agents.md and gets out of sync quickly. What is the workflow for updating those without having it conflict with this workflow running.


## Guiding Principles

Follow the latest VS Code and GitHub Copilot best practices:

1. **Directory-Scoped Instructions**: Use `agents.md` files placed in the root of each workspace/package (e.g., `packages/nimble-components/agents.md`). This allows the agent to automatically adopt the correct context based on the active working directory.
2. **Include Overview**: Start with a high-level summary of the package's purpose and tech stack.
3. **Include Build & Test Commands**: Provide copy-pasteable commands for building and testing the specific package.
4. **Prefer Links Over Duplication**: Link to existing documentation (CONTRIBUTING.md, specs, guidelines) rather than duplicating content. This reduces maintenance burden and ensures single source of truth.
5. **Essential Information Only**: Include only critical patterns, gotchas, and quick-reference snippets that AI agents need immediately. Detailed documentation belongs in the linked files.
6. **Code Snippets for Common Patterns**: Include concise, verified code examples for frequently-used patterns (component registration, testing setup, templates, styles) that would otherwise require multiple file reads.

## Context Sources
Read the following files to understand the current "source of truth":
1. `CONTRIBUTING.md` (Root)
2. `packages/nimble-components/CONTRIBUTING.md`
3. `packages/nimble-components/docs/css-guidelines.md`
4. `packages/spright-components/CONTRIBUTING.md`
5. `packages/ok-components/CONTRIBUTING.md`
6. `packages/storybook/CONTRIBUTING.md`
7. `packages/storybook/src/docs/component-status.mdx`

## Target Files
You will be creating or updating the following instruction files:
1. `.github/copilot-instructions.md` (Global instructions - applies to everything)
2. `packages/nimble-components/agents.md`
3. `packages/ok-components/agents.md`
4. `packages/spright-components/agents.md`
5. `packages/angular-workspace/agents.md`
6. `packages/blazor-workspace/agents.md`
7. `packages/react-workspace/agents.md`
8. `packages/nimble-tokens/agents.md`
9. `packages/storybook/agents.md`

## Instructions

1. **Analyze Changes**: Compare the "Context Sources" against the "Target Files". Look for:
* New build commands or workflow steps.
* Changes to file structure or naming conventions.
* New required patterns (e.g., new testing requirements).
* Deprecated patterns that should be removed from instructions.

2. **Structure the File**:
* **Overview**: A brief description of the package.
* **Build & Test**: Specific `npm run` or `dotnet` commands for this package.
* **Common Pitfalls**: A list of "Do's and Don'ts".
* **Key References**: Links to local `CONTRIBUTING.md` and other docs.
* **Core Patterns**: (Optional) Code snippets for common tasks.

3. **Verify Code Snippets**:
* Check that the code snippets (e.g., `index.ts` boilerplate, `styles.ts` patterns) match the current best practices found in the codebase.
* **Only include snippets that are**: (a) used frequently, (b) hard to infer from docs alone, (c) critical to get right.

4. **Reduce Duplication**:
* Review all duplicated content. Can it be replaced with a link + 1-sentence summary?
* Keep: Command references, critical patterns, common pitfalls with examples.
* Remove: Detailed explanations that exist in linked docs, policy details, extended rationale.

4. **Update Global Instructions** (`.github/copilot-instructions.md`):
* Ensure links to documentation are correct.
* Update "Common Pitfalls" if new recurring issues have been identified.
* Keep it high-level: Architecture, Workflows, and Global Patterns.


6. **Output**:
* Present the changes as file edits (using `replace_string_in_file` or by showing the diff).
* If no changes are needed, explicitly state that the instructions are up-to-date.
7 changes: 6 additions & 1 deletion beachball.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,10 @@ module.exports = {
return `- ${entry.comment} ([ni/nimble@${entry.commit.substring(0, 7)}](https://github.com/ni/nimble/commit/${entry.commit}))`;
}
}
}
},
ignorePatterns: [
'agents.md',
'docs/',
'specs/',
Comment on lines +15 to +17
Copy link
Member

@rajsite rajsite Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add this to ignore these files in beachball change checks in packages

]
};
50 changes: 50 additions & 0 deletions packages/angular-workspace/agents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Nimble Angular – AI Instructions

## Overview
Angular directives that wrap Nimble Web Components to provide first-class Angular integration (Forms, Router, etc.).
- **Pattern**: One Directive per Component
- **State**: Directives are stateless proxies; state lives in the Web Component.

## Build & Test
Run these commands from the repo root:
- **Build**: `npm run build -w @ni/nimble-angular`
- **Test**: `npm run test -w @ni/nimble-angular`

## Key References
- [`nimble-angular/CONTRIBUTING.md`](nimble-angular/CONTRIBUTING.md) – Directive patterns, testing, and versioning.

## Core Patterns

### Directive Skeleton
```typescript
@Directive({
selector: 'nimble-example'
})
export class NimbleExampleDirective {
public get myAttribute(): string {
return this.elementRef.nativeElement.myAttribute;
}

@Input()
public set myAttribute(value: string) {
this.renderer.setProperty(this.elementRef.nativeElement, 'myAttribute', value);
}

constructor(private readonly renderer: Renderer2, private readonly elementRef: ElementRef<Example>) {}
}
```

### Form Integration
- Implement `ControlValueAccessor` for inputs.
- Use `Renderer2` for property updates.
- Forward events using `@HostListener`.

## Testing
- Test `ControlValueAccessor` with `[(ngModel)]`.
- Verify module imports: `expect(customElements.get('nimble-example')).not.toBeUndefined();`.
- Use `fakeAsync` and `processUpdates()` for async behavior.

## Common Pitfalls
- ❌ **Direct DOM Manipulation**: Use `Renderer2` instead of modifying `nativeElement` directly.
- ❌ **Missing CVA**: Form components *must* implement `ControlValueAccessor`.
- ❌ **State Duplication**: Don't duplicate component state in the directive; proxy it.
48 changes: 48 additions & 0 deletions packages/blazor-workspace/agents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Nimble Blazor – AI Instructions

## Overview
Blazor Razor Components that wrap Nimble Web Components for use in .NET applications.
- **Pattern**: Razor Component (`.razor`) + Code-behind (`.razor.cs`)
- **Binding**: 2-way binding via `EventCallback`

## Build & Test
Run these commands from the repo root:
- **Build**: `dotnet build packages/blazor-workspace/NimbleBlazor.sln`
- **Test**: `dotnet test packages/blazor-workspace/NimbleBlazor.sln`

## Key References
- [`NimbleBlazor/CONTRIBUTING.md`](NimbleBlazor/CONTRIBUTING.md) – Wrapper patterns, testing, and setup.

## Core Patterns

### Wrapper Skeleton (`.razor`)
```razor
@inherits NimbleInputBase<string>
<nimble-example
my-attribute="@MyAttribute"
@attributes="AdditionalAttributes">
</nimble-example>
```

### Wrapper Logic (`.razor.cs`)
```csharp
public partial class NimbleExample : ComponentBase
{
[Parameter]
public string? MyAttribute { get; set; }

[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
}
```

## Testing
- **Unit**: Use bUnit in `NimbleBlazor.Tests`.
- **Acceptance**: Use Playwright in `NimbleBlazor.Tests.Acceptance`.
- Disable prerendering: `@rendermode @(new InteractiveServerRenderMode(prerender: false))`
- Use `NewPageForRouteAsync` to load the test page.

## Common Pitfalls
- ❌ **Missing `CaptureUnmatchedValues`**: Always allow users to pass arbitrary attributes.
- ❌ **Sync Interop**: Avoid synchronous JS interop; use `InvokeAsync`.
- ❌ **Hardcoded Events**: Use `EventCallback` for all event handling.
115 changes: 115 additions & 0 deletions packages/nimble-components/agents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Nimble Components – AI Instructions

## Overview

The core Web Components library for the Nimble Design System, built on the **FAST Foundation**.

- **Framework**: FAST Element (Web Components)
- **Styling**: SCSS-like `css` tagged templates with Design Tokens
- **Testing**: Karma/Jasmine (Unit), Playwright (Visual/Interaction)

## Build & Test

Run these commands from the repo root:

- **Build**: `npm run build -w @ni/nimble-components`
- **Test (Watch)**: `npm run tdd:watch -w @ni/nimble-components`
- **Test (All Browsers)**: `npm run test-webkit -w @ni/nimble-components`
- **Lint**: `npm run lint -w @ni/nimble-components`

## Key References

- [`CONTRIBUTING.md`](CONTRIBUTING.md) – component lifecycle, Storybook, accessibility.
- [`docs/css-guidelines.md`](docs/css-guidelines.md) – cascade layers, `display()` utility, attribute-driven states.
- [`docs/coding-conventions.md`](docs/coding-conventions.md) – const-object enums, comment expectations.

## Component Skeleton

<!-- Pattern derived from src/text-field/index.ts -->

### `index.ts`

```typescript
import { attr } from '@ni/fast-element';
import { DesignSystem, FoundationElement } from '@ni/fast-foundation';
import { styles } from './styles';
import { template } from './template';

declare global {
interface HTMLElementTagNameMap {
'nimble-example': Example;
}
}

export class Example extends FoundationElement {
@attr({ attribute: 'my-attribute' })
public myAttribute?: string;
}

const nimbleExample = Example.compose({
baseName: 'example',
baseClass: FoundationElement,
template,
styles
});

DesignSystem.getOrCreate().withPrefix('nimble').register(nimbleExample());
export const exampleTag = 'nimble-example';
```

<!-- Pattern derived from src/text-field/styles.ts -->

### `styles.ts`

```typescript
import { css } from '@ni/fast-element';
import { display } from '../utilities/style/display';
import { bodyFont } from '../theme-provider/design-tokens';

export const styles = css`
@layer base, hover, focusVisible, active, disabled, top;

${display('flex')}

@layer base {
:host {
font: ${bodyFont};
}
}
`;
```

<!-- Pattern derived from src/text-field/tests/text-field.spec.ts -->

### `tests/*.spec.ts`

```typescript
import { html } from '@ni/fast-element';
import { fixture, type Fixture } from '../../utilities/tests/fixture';
import { Example, exampleTag } from '..';

describe('Example', () => {
async function setup(): Promise<Fixture<Example>> {
return fixture<Example>(html`<${exampleTag}></${exampleTag}>`);
}

it('constructs a nimble-example', () => {
expect(document.createElement(exampleTag)).toBeInstanceOf(Example);
});

it('updates when attribute changes', async () => {
const { element, connect, disconnect } = await setup();
await connect();
element.setAttribute('my-attribute', 'value');
expect(element.myAttribute).toBe('value');
await disconnect();
});
});
```

## Common Pitfalls

- ❌ **Hardcoded Colors**: Always use tokens (e.g., `bodyFont`), never hex codes or raw CSS vars.
- ❌ **Class-based State**: Use attributes/behaviors to drive state, not `.is-active` classes.
- ❌ **Missing Exports**: Always export the tag constant and update `src/all-components.ts`.
- ❌ **Flaky Tests**: Use `await connect()` and `await disconnect()` in every test.
36 changes: 36 additions & 0 deletions packages/nimble-tokens/agents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Nimble Tokens – AI Instructions

## Overview

The source of truth for design tokens (colors, fonts, sizes) and icons.

- **Tooling**: Style Dictionary (tokens), Adobe Illustrator (icons)
- **Output**: SCSS, CSS, TypeScript, and JSON

## Build

Run these commands from the repo root:

- **Build**: `npm run build -w @ni/nimble-tokens`

## Key References

- [`CONTRIBUTING.md`](CONTRIBUTING.md) – Build scripts, editing base tokens, updating icons.

## Workflows

- **Edit Tokens**: Modify JSON in `source/styledictionary/properties`. Run `npm run build`.
- **Add Icons**:
1. Export optimized SVGs from Illustrator to `dist/icons/svg`.
2. Remove `<defs>` tags (unless multi-colored).
3. Run `npm run build -w @ni/nimble-tokens`.
4. Update `icon-metadata.ts` in `nimble-components`.

## Naming Conventions

- **Icons**: Use Font Awesome names where possible (e.g., `key`, `cog`). Avoid metaphors (`access-control`, `logout`).

## Common Pitfalls

- ❌ **Missing Build**: Always run `npm run build` after changing tokens or icons.
- ❌ **Complex SVGs**: Icons should be simple paths. Remove `<defs>`, `style` tags, and colors (unless multi-colored).
Loading