Skip to content
Open
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
61 changes: 61 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ https://github.com/user-attachments/assets/8b1b8ef2-9fba-4951-bc9a-beaed4f6aff6
- [GeoJSON Preview tool (Beta)](#geojson-preview-tool-beta)
- [Coordinate Conversion tool](#coordinate-conversion-tool)
- [Bounding Box tool](#bounding-box-tool)
- [Color Contrast Checker tool](#color-contrast-checker-tool)
- [Resources](#resources)
- [Observability \& Tracing](#observability--tracing)
- [Features](#features)
Expand Down Expand Up @@ -453,6 +454,66 @@ An array of four numbers representing the bounding box: `[minX, minY, maxX, maxY
- "Calculate the bounding box of this GeoJSON file" (then upload a .geojson file)
- "What's the bounding box for the coordinates in the uploaded parks.geojson file?"

#### Color Contrast Checker tool

Checks color contrast ratios between foreground and background colors for WCAG 2.1 accessibility compliance.

**Parameters:**

- `foregroundColor` (string, required): Foreground color (text color) in any CSS format (hex, rgb, rgba, named colors)
- `backgroundColor` (string, required): Background color in any CSS format (hex, rgb, rgba, named colors)
- `level` (string, optional): WCAG conformance level to check against ("AA" or "AAA", default: "AA")
- `fontSize` (string, optional): Font size category ("normal" or "large", default: "normal")
- Normal: < 18pt or < 14pt bold
- Large: ≥ 18pt or ≥ 14pt bold

**Color format support:**

- Hex colors: `#RGB`, `#RRGGBB`, `#RRGGBBAA`
- RGB/RGBA: `rgb(r, g, b)`, `rgba(r, g, b, a)`
- Named colors: `black`, `white`, `red`, `blue`, `gray`, etc.

**WCAG 2.1 requirements:**

- WCAG AA: 4.5:1 for normal text, 3:1 for large text
- WCAG AAA: 7:1 for normal text, 4.5:1 for large text

**Returns:**

A JSON object with:

- `contrastRatio`: Calculated contrast ratio (e.g., 21 for black on white)
- `passes`: Whether the combination meets the specified WCAG level
- `level`: WCAG level checked ("AA" or "AAA")
- `fontSize`: Font size category ("normal" or "large")
- `minimumRequired`: Minimum contrast ratio required for the level and font size
- `wcagRequirements`: Complete WCAG contrast requirements for all levels
- `recommendations`: Array of suggestions (only included when contrast fails)

**Example:**

```json
{
"contrastRatio": 21,
"passes": true,
"level": "AA",
"fontSize": "normal",
"minimumRequired": 4.5,
"wcagRequirements": {
"AA": { "normal": 4.5, "large": 3.0 },
"AAA": { "normal": 7.0, "large": 4.5 }
}
}
```

**Example prompts:**

- "Check if black text on white background is WCAG AA compliant"
- "What's the contrast ratio between #4264fb and white?"
- "Does gray text (#767676) on white meet AAA standards for large text?"
- "Check color contrast for rgb(51, 51, 51) on rgb(245, 245, 245)"
- "Is this color combination accessible: foreground 'navy' on background 'lightblue'?"

## Agent Skills

This repository includes [Agent Skills](https://agentskills.io) that provide domain expertise for building maps with Mapbox. Skills teach AI assistants about map design, security best practices, and common implementation patterns.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) Mapbox, Inc.
// Licensed under the MIT License.

import { z } from 'zod';

export const CheckColorContrastInputSchema = z.object({
foregroundColor: z
.string()
.min(1)
.describe(
'Foreground color (text color) in any CSS format (hex, rgb, rgba, named colors)'
),
backgroundColor: z
.string()
.min(1)
.describe(
'Background color in any CSS format (hex, rgb, rgba, named colors)'
),
level: z
.enum(['AA', 'AAA'])
.optional()
.describe('WCAG conformance level to check against (default: AA)'),
fontSize: z
.enum(['normal', 'large'])
.optional()
.describe(
'Font size category: normal (<18pt or <14pt bold) or large (≥18pt or ≥14pt bold)'
)
});

export type CheckColorContrastInput = z.infer<
typeof CheckColorContrastInputSchema
>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) Mapbox, Inc.
// Licensed under the MIT License.

import { z } from 'zod';

const WcagLevelRequirementsSchema = z.object({
AA: z.object({
normal: z.number().describe('Minimum contrast ratio for normal text (AA)'),
large: z.number().describe('Minimum contrast ratio for large text (AA)')
}),
AAA: z.object({
normal: z.number().describe('Minimum contrast ratio for normal text (AAA)'),
large: z.number().describe('Minimum contrast ratio for large text (AAA)')
})
});

export const CheckColorContrastOutputSchema = z.object({
contrastRatio: z
.number()
.describe('Calculated contrast ratio between foreground and background'),
passes: z
.boolean()
.describe('Whether the contrast ratio meets the specified WCAG level'),
level: z.string().describe('WCAG level checked (AA or AAA)'),
fontSize: z.string().describe('Font size category (normal or large)'),
minimumRequired: z
.number()
.describe(
'Minimum contrast ratio required for the specified level and font size'
),
wcagRequirements: WcagLevelRequirementsSchema.describe(
'Complete WCAG contrast requirements for all levels'
),
recommendations: z
.array(z.string())
.optional()
.describe('Optional recommendations for improvement')
});

export type CheckColorContrastOutput = z.infer<
typeof CheckColorContrastOutputSchema
>;
Loading
Loading