diff --git a/README.md b/README.md index b14f343..5a1642e 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,22 @@ Guides AI agents through building and integrating DHTMLX React Gantt in web appl - Styling, CSS variables, template-based visual customization - Common pitfalls and constraints +### `dhtmlx-angular-gantt` + +Guides AI agents through building and integrating DHTMLX Angular Gantt in web applications. Covers: + +- Package installation (trial and commercial) +- CSS setup and layout requirements +- Angular integration patterns +- Task and link state, mapping, and persistence +- Styling, CSS variables, template-based visual customization +- Common pitfalls and constraints ## Installation ```bash npx skills add DHTMLX/skills --skill dhtmlx-react-gantt +npx skills add DHTMLX/skills --skill dhtmlx-angular-gantt ``` Or copy manually: @@ -39,6 +50,7 @@ Or copy manually: ```bash git clone https://github.com/DHTMLX/skills cp -r skills/dhtmlx-react-gantt ~/.claude/skills/ +cp -r skills/dhtmlx-angular-gantt ~/.claude/skills/ ``` ## Requirements diff --git a/dhtmlx-angular-gantt/SKILL.md b/dhtmlx-angular-gantt/SKILL.md new file mode 100644 index 0000000..2adace8 --- /dev/null +++ b/dhtmlx-angular-gantt/SKILL.md @@ -0,0 +1,94 @@ +--- +name: dhtmlx-angular-gantt +description: > + Builds and integrates DHTMLX Angular Gantt into Angular applications. Covers setup, + inputs, templates, themes, data.save, data.batchSave, resources, calendars, undo/redo, + row reorder, sortorder, and Angular wrapper integration patterns for + @dhtmlx/trial-angular-gantt and @dhx/angular-gantt. Applies when working with gantt charts, + project timelines, task dependencies, task CRUD, resource panels, working calendars, + lightboxes, or weekend highlighting in Angular. Provides verified API guidance rather + than guessing Angular Gantt APIs. +paths: "**/*.ts,**/*.html,**/*.css,**/*.scss,angular.json,package.json" +allowed-tools: Read Grep +metadata: + tags: dhtmlx, gantt, angular, dependencies, baselines, milestones, resources +--- + +## Source Of Truth + +Use only: +1. The current project's files, structure, and established patterns +2. DHTMLX MCP for Angular Gantt API details: https://docs.dhtmlx.com/mcp +3. Official DHTMLX Angular Gantt docs as fallback: https://docs.dhtmlx.com/gantt/integrations/angular/ + +Never invent inputs, template signatures, callback contracts, event names, or backend behavior. + +If any Angular Gantt API detail is unclear, resolve it through DHTMLX MCP before writing code. + +## Preflight + +Before writing code, identify: +- **package**: `@dhtmlx/trial-angular-gantt` or `@dhx/angular-gantt` — check `package.json`, imports, lockfiles +- **runtime**: Angular standalone components or NgModule setup +- **ownership model**: Angular state/store as source of truth (recommended) or Gantt as source of truth (performance-focused) +- **persistence**: local only, `data.save` (default), or `data.batchSave` (bulk sync) + +## Workflow + +1. Confirm installed Angular Gantt package and matching import path. +2. Confirm wrapper CSS is imported and chart height chain is explicit. +3. Decide the state ownership model before implementing features, and keep one model per page/feature area. +4. Read only the reference file needed for the task: + - Angular wrapper integration/setup: [references/angular-integration.md](references/angular-integration.md) + - CRUD, state, and persistence: [references/data-and-crud.md](references/data-and-crud.md) + - Failure cases and guardrails: [references/known-failures.md](references/known-failures.md) + - Advanced patterns (reorder, resources, undo/redo, schema): [references/advanced-patterns.md](references/advanced-patterns.md) + - Styling, theming, templates, and override strategy: [references/styling-and-theming.md](references/styling-and-theming.md) +5. Use DHTMLX MCP before relying on advanced or unfamiliar APIs. +6. Implement with documented APIs only. + +## MCP Server + +This skill relies on DHTMLX MCP for API verification. If the `dhtmlx-mcp` tool is not available, ask the user to add it: + +Claude Code: +```bash +claude mcp add --transport http dhtmlx-mcp https://docs.dhtmlx.com/mcp +``` + +Codex: +```bash +codex mcp add dhtmlx-mcp --url https://docs.dhtmlx.com/mcp +``` + +If MCP is not available, use the official docs at https://docs.dhtmlx.com/gantt/integrations/angular/ as fallback. + +## Consult MCP First For + +Consult DHTMLX MCP before using or changing: +- template callbacks you have not already verified +- advanced inputs such as `batchSave`, `customLightbox`, `groupTasks`, `resourceFilter`, or `allowRawHTML` +- `events` callback signatures beyond commonly used handlers +- theme/skin names beyond known project usage +- complex layout/resource panel definitions (`resourceGrid`, `resourceTimeline`, shared scroll) +- workload cell template callbacks and overload logic + +## Hard Rules + +- Use wrapper path (``) by default for Angular tasks. +- The Gantt container must have explicit height through the parent chain. +- Use app theme as single source of truth; map it to Gantt theme. +- Keep tasks/links in Angular state/store when surrounding UI depends on chart state. +- Normalize date values before persistence. +- Build backend payloads explicitly from normalized app task/link models. +- If mutating through `instance`, keep Angular state synchronized immediately. +- Do not mix wrapper-driven inputs and imperative instance mutations without intentional synchronization. + +## Quick Checklist + +- [ ] Correct package identified +- [ ] Matching wrapper CSS import used +- [ ] Explicit height chain provided +- [ ] State ownership model chosen +- [ ] Dates normalized before persistence +- [ ] Advanced APIs verified with MCP diff --git a/dhtmlx-angular-gantt/references/advanced-patterns.md b/dhtmlx-angular-gantt/references/advanced-patterns.md new file mode 100644 index 0000000..b3e865d --- /dev/null +++ b/dhtmlx-angular-gantt/references/advanced-patterns.md @@ -0,0 +1,119 @@ +# Advanced Patterns + +Use this file when implementing row reorder, resource panels, undo/redo, or designing a backend schema for Gantt data. + +## Contents +- Row Reorder With Sortorder Persistence +- Resource Panel And Workload Visualization +- Undo/Redo With State Management +- Backend Schema Template + +## Row Reorder With Sortorder Persistence + +- enable row ordering in Gantt config +- treat reorder as a dedicated flow — do not route it through normal single-task update logic +- detect reorder intent from task update payload (for example `target` when available) +- when a row moves, rebuild the full ordered task list in memory +- recompute `sortorder` for all affected tasks, not only the moved task +- update state/store with the reordered list +- persist the full reordered set — update `sortorder` for every affected row +- if hierarchy changes during the move, persist `parent_id` alongside `sortorder` +- normal task updates must preserve current `sortorder` unless dedicated reorder flow changes it +- load tasks with `ORDER BY sortorder` from backend +- keep reorder implementation targeted — do not refactor unrelated CRUD paths + +## Resource Panel And Workload Visualization + +- Gantt does not enforce one standard task field for resource binding +- the relation is defined by `config.resource_property`, and built-in resource features watch `task[gantt.config.resource_property]` +- for a single-resource model, choose any task field that fits the app schema, then set `config.resource_property` to match it +- for a multi-resource model, the field named by `config.resource_property` can store either an array of resource IDs or an array of assignment objects +- for advanced flows, resource assignments can also be loaded separately from tasks +- build the resource list dynamically from real project data, not from a hardcoded array +- include an explicit `Unassigned` option only when the product actually needs one +- if using a single-resource model, resource grid display, timeline display, and lightbox editing should all read and write the same task field +- if using multi-resource assignments, keep the UI and persistence model aligned to the same assignment structure +- if using separate assignments, build task/resource views and save flows from the assignments dataset rather than inventing a display-only task field +- display workload in the resource grid as formatted values such as `"8h"`, `"16h"`, `"24h"` when the product uses hours +- wire lightbox resource selection so it maps back to the same field or assignment structure used by persistence +- layout must include both main Gantt rows (grid + timeline) and resource panel rows (resourceGrid + resourceTimeline or resourceHistogram) with shared horizontal scrolling when the product needs a combined view +- verify `resource_cell_value`, `resource_cell_class`, histogram templates, and resource timeline callback signatures with MCP before implementing + +### Supported Resource Binding Models + +Single-resource field on task: +```ts +config.resource_property = "user_id"; +// task.user_id <-> resource.id +``` + +Multiple resource IDs on task: +```ts +config.resource_property = "users"; +// task.users = [2, 3] +``` + +Assignment objects on task: +```ts +config.resource_property = "users"; +// task.users = [{ resource_id: 2, value: 8 }, { resource_id: 3, value: 4 }] +``` + +Separate assignments list: +```ts +{ + tasks: [...], + links: [...], + resources: [...], + assignments: [{ id: 1, task_id: 5, resource_id: 2, value: 8 }] +} +``` + +## Undo/Redo With State Management + +- use fresh state/store snapshots inside `data.save` callbacks — do not rely on stale captured values +- if using RxJS store, NgRx, or another external store for Gantt history, normalize all date values before writing to the store (state must be serializable) +- undo and redo actions must also update persistence — client-only history creates data gaps on reload +- persist history snapshots when rehydration across sessions is required +- save or refetch operations must not wipe the undo/redo history stack +- keep history refs/snapshots and store state in sync after every mutation + +## Backend Schema Template + +Recommended practical schema for a writable Gantt-backed app with tasks, links, and optional resources. This is not a DHTMLX-mandated contract. Adjust the field names and tables to fit the app and backend. + +Tasks table: +- `id` - UUID, primary key +- `project_id` - strongly recommended foreign key to a `projects` table for multi-project apps +- `text` - task name +- `start_date` - timestamp (nullable for projects that derive dates from children) +- `duration` - integer in the configured project duration unit (nullable, >= 0 when set) +- `progress` - numeric, constrained between 0 and 1 +- `parent_id` - self-referencing foreign key to tasks (must not equal `id`), cascade on delete +- `sortorder` - strongly recommended integer field for persistent row ordering +- `type` - one of `task`, `project`, `milestone` +- resource relation: + - either a task field named to match `config.resource_property` + - or no task field at all when the app uses separate resource assignments + +Duration storage guardrail: +- treat `duration_unit` as a project-level storage decision, not just a display preference +- choose the smallest unit the product must support at project start, because changing from `day` to `hour` or `minute` later usually requires conversion of persisted task durations +- stored durations are integers, so `duration_unit=\"day\"` supports whole-day tasks only and cannot represent a plain 4-hour task as `duration: 4` +- use `duration_unit=\"hour\"` when tasks like 4 hours must be stored directly, and `duration_unit=\"minute\"` when the product needs minute-level precision + +Links table: +- `id` - UUID, primary key +- `project_id` - strongly recommended foreign key to a `projects` table for multi-project apps +- `source` - foreign key to task, cascade on delete +- `target` - foreign key to task, cascade on delete (must not equal `source`) +- `type` - one of `0`, `1`, `2`, `3` + +Recommended constraints: +- unique constraint on `(project_id, source, target, type)` for links +- cascade on delete for project foreign keys in both tables + +Recommended indexes: +- `project_id` on both tables +- `parent_id` on tasks +- `source` and `target` on links diff --git a/dhtmlx-angular-gantt/references/angular-integration.md b/dhtmlx-angular-gantt/references/angular-integration.md new file mode 100644 index 0000000..4620133 --- /dev/null +++ b/dhtmlx-angular-gantt/references/angular-integration.md @@ -0,0 +1,192 @@ +# Angular Integration + +Use this file when setting up or modifying the Angular wrapper integration. + +## Installation + +Trial: +```bash +npm install @dhtmlx/trial-angular-gantt +``` + +Commercial (requires private registry setup and login): +```bash +npm config set @dhx:registry=https://npm.dhtmlx.com +npm login --registry=https://npm.dhtmlx.com --scope=@dhx --auth-type=legacy +npm install @dhx/angular-gantt +``` +The user must generate credentials in the [Client's Area](https://dhtmlx.com/clients/) and run the registry config and login commands themselves before the package can be installed. See [installation docs](https://docs.dhtmlx.com/gantt/integrations/angular/installation/) for details. + +Wrapper import and CSS import must match the installed package. + +Trial: +```ts +import { DhxGanttComponent } from "@dhtmlx/trial-angular-gantt"; +``` + +```css +@import "@dhtmlx/trial-angular-gantt/dist/angular-gantt.css"; +``` + +Commercial: +```ts +import { DhxGanttComponent } from "@dhx/angular-gantt"; +``` + +```css +@import "@dhx/angular-gantt/dist/angular-gantt.css"; +``` + +For NgModule apps, import `DhxGanttModule` from the same package channel. + +## CSS Placement Rule + +Prefer global wrapper CSS import (for example in `src/styles.css`). + +If wrapper CSS or `.dhx-*` overrides are placed in a component stylesheet, Angular style encapsulation can interfere with Gantt internals. In that case, use `ViewEncapsulation.None` in that component. + +## Height Rule + +The Gantt container must have explicit height via parent chain and chart block. + +Valid: +```html +
+ +
+``` + +## Documented Inputs + +Use documented inputs only: + +- `tasks` +- `links` +- `resources` +- `resourceAssignments` +- `baselines` +- `config` +- `templates` +- `plugins` +- `calendars` +- `markers` +- `locale` +- `theme` +- `data` +- `events` +- `customLightbox` +- `groupTasks` +- `filter` +- `resourceFilter` +- `allowRawHTML` + +## Events And Ready + +Use `events` for interaction behavior and `(ready)` for one-time initialized instance access. + +```html + +``` + +```ts +events = { + onTaskCreated: (task: any) => true, + onBeforeLightbox: (taskId: string | number) => true, +}; + +onReady({ instance }: { instance: GanttStatic }): void { + instance.showDate(new Date()); +} +``` + +## Instance Access + +Use `@ViewChild(DhxGanttComponent)` when direct instance access is required: + +```ts +@ViewChild(DhxGanttComponent) ganttCmp?: DhxGanttComponent; + +showToday(): void { + this.ganttCmp?.instance?.showDate(new Date()); +} +``` + +If you mutate data through the instance while also passing `tasks` and `links` as inputs, keep them synchronized. Otherwise Angular input updates can overwrite chart-side changes. + +## Theme Rule + +Use app theme as the single source of truth. + +Preferred built-in themes: +- `"terrace"` +- `"dark"` + +Typical mapping: +```ts +ganttTheme: "dark" | "terrace" = appTheme === "dark" ? "dark" : "terrace"; +``` + +Template usage: +```html + + +``` + +The `theme` input can be updated at runtime; keep it bound to app-level state/store so Gantt follows light/dark changes automatically. + +Do not introduce separate Gantt-only theme state if the app already has a global theme source. + +## Config And Templates + +Use `config` and `templates` for declarative setup. + +Common documented config areas: +- `config.columns` +- `config.scales` +- `config.readonly` +- `config.drag_move` +- `config.drag_resize` +- `config.resource_store` +- `config.resource_property` +- `config.layout` + +Typical config: +```ts +config = { + date_format: "%Y-%m-%d %H:%i", + row_height: 36, + bar_height: 24, + scales: [ + { unit: "month", step: 1, format: "%F %Y" }, + { unit: "day", step: 1, format: "%d %M" }, + ], + columns: [ + { name: "text", label: "Task", tree: true, width: "*" }, + { name: "start_date", label: "Start", align: "center" }, + { name: "duration", label: "Duration", align: "center" }, + { name: "add", width: 44 }, + ], +}; +``` + +Do not guess template callback signatures. Verify with MCP if there is any doubt. + +Example: +```ts +task_text: (_start, _end, task) => `#${task.id}: ${task.text}` +``` + +Template-driven styling example: +```ts +templates = { + task_class: (_start: Date, _end: Date, task: any) => + (task.progress ?? 0) >= 1 ? "completed-task" : "", + resource_cell_value: (_start: Date, _end: Date, _resource: any, tasks: any[]) => + `
${tasks.length * 8}h
`, +}; +``` + +Use `templateComponent(...)` only when Angular component rendering inside Gantt templates is required. diff --git a/dhtmlx-angular-gantt/references/data-and-crud.md b/dhtmlx-angular-gantt/references/data-and-crud.md new file mode 100644 index 0000000..0be4701 --- /dev/null +++ b/dhtmlx-angular-gantt/references/data-and-crud.md @@ -0,0 +1,133 @@ +# Data And CRUD + +Use this file when tasks, links, state ownership, or persistence are involved. + +## Data Model Essentials + +In Angular wrapper integrations, keep a normalized app model and map it explicitly to Gantt task/link payloads. + +Minimum task shape: +```ts +interface Task { + id: string | number; + text: string; + start_date: Date; + duration: number; + progress: number; + parent: string | number; + type?: "task" | "project" | "milestone"; + open?: boolean; + end_date?: Date; +} +``` + +Minimum link shape: +```ts +interface Link { + id: string | number; + source: string | number; + target: string | number; + type: "0" | "1" | "2" | "3"; +} +``` + +When loading from backend, map rows into app task/link models explicitly. Do not pass raw DB rows straight through. + +## Choose Ownership Model First + +Choose one model per page/feature area and keep it consistent. + +Angular state/store as source of truth (recommended for most apps): +- store/component state owns `tasks` and `links` +- wrapper receives arrays through inputs +- edits are captured in `data.save` or `data.batchSave` +- callbacks update state/store and arrays flow back into `` + +Gantt as source of truth (specialized/performance-heavy pages): +- chart and backend own most runtime lifecycle +- Angular mirrors only when required +- requires a clear reconciliation strategy + +Do not mix both models casually. + +## CRUD Default + +For regular CRUD, prefer `data.save`. + +Pattern: +```ts +dataConfig: AngularGanttDataConfig = { + save: async (entity, action, item, id) => { + // call store action + // store action normalizes payload + // store action persists backend write + // store action updates state on confirmed success + }, +}; +``` + +Strict rules: +- route persistence through store/service actions, not inline component mutation spaghetti +- normalize callback payloads before backend writes +- for create with backend-assigned IDs, return remap response (`{ id }` or `{ tid }`) when using per-change save flow +- update state from latest snapshot, not stale captured arrays +- keep links persistence guarded by real persisted task IDs +- for `update`, persist only normalized values +- for `delete`, remove from state and persistence layer +- normalize date values before serialization +- if using temporary IDs, replace them deterministically after persistence +- persist a link only when both `source` and `target` already refer to real persisted task IDs +- if a task still has a temporary client-side ID, defer or reject link persistence until the real task ID replacement flow completes +- do not send links that reference temporary IDs to the backend +- build backend payloads explicitly from normalized task/link models, not from raw callback objects + +## When To Use `batchSave` + +Use `data.batchSave` when: +- heavy operations can emit many changes +- bulk backend sync is more appropriate than single-entity persistence +- you need grouped change handling rather than one callback per edit + +Pattern: +```ts +dataConfig: AngularGanttDataConfig = { + batchSave: (changes) => { + // apply grouped task/link/resource changes + // persist grouped payloads + // update store in one coherent transition + }, +}; +``` + +Do not switch to `batchSave` casually. Verify the exact expected behavior with MCP first. + +## ID Remapping And Temporary IDs + +Create flows often start with temporary client-side IDs. + +Rules: +- backend must return persistent IDs +- in `save` mode, return `{ id: dbId }` or `{ tid: dbId }` so Gantt can remap +- do not persist links that reference temporary task IDs +- replace temporary IDs deterministically in state after create confirmation + +## Row Reorder And Sortorder + +Treat row reorder as dedicated flow, not normal update. + +Rules: +- detect reorder intent from update payload (`target` when available) +- rebuild full ordered task list in memory +- recompute `sortorder` for all affected tasks +- persist full reordered set +- if hierarchy changes during move, persist `parent_id` together with `sortorder` +- load tasks ordered by `sortorder` + +## Persistence Guardrails + +- Do not assume task updates always contain real `Date` instances. +- Normalize date-like inputs before serialization and persistence. +- Build backend payloads explicitly from normalized task/link models, not from raw callback objects. +- Keep frontend ordering (`sortorder`), backend payloads, and DB schema aligned. +- If IDs are temporary on create, make ID replacement flow explicit and deterministic. +- If the app introduces undo/redo, persistence rules must remain correct after history actions. diff --git a/dhtmlx-angular-gantt/references/known-failures.md b/dhtmlx-angular-gantt/references/known-failures.md new file mode 100644 index 0000000..74e0b86 --- /dev/null +++ b/dhtmlx-angular-gantt/references/known-failures.md @@ -0,0 +1,67 @@ +# Known Failures + +Use this file when debugging incorrect or flaky DHTMLX Angular Gantt integrations. + +## 1. Theme Drift + +Problem: +- the shell and Gantt use different dark-mode sources + +Fix: +- use one shared app theme source +- map that source to the Gantt `theme` input +- do not create separate Gantt-only theme state + +## 2. Date Serialization Bugs + +Problem: +- `data.save` and `data.batchSave` handlers can emit formatted date strings rather than real `Date` instances +- calling `toISOString()` directly can fail or produce unstable persistence behavior + +Fix: +- normalize date inputs before persistence +- handle both `Date` and string inputs in the normalization layer +- keep serialization deterministic in the persistence pipeline (see data-and-crud.md § Date Normalization) + +## 3. Stale Callback State + +Problem: +- `data.save` handlers capture old task/link arrays or old store snapshots + +Fix: +- use latest state/store snapshots at mutation time +- do not build persistence logic from stale captured values + +## 4. Undo/Redo Persistence Gaps + +Problem: +- local undo/redo changes state but not persistence, so reload restores the wrong data + +Fix: +- if the app has local history, undo/redo must also update backend persistence or trigger correct rehydration behavior + +## 5. Wrong Template Callback Signature + +Problem: +- a template callback is wired with the wrong parameter order or wrong argument assumptions + +Fix: +- verify the exact documented signature with MCP +- do not infer template arguments from memory + +## 6. Implicit Height Containers + +Problem: +- Gantt is mounted into a container without real height, so rendering is broken or collapsed + +Fix: +- give the container explicit height through the parent chain + +## 7. Mixed Ownership Bugs + +Problem: +- wrapper inputs/state and imperative `instance` mutations both modify the same data without synchronization + +Fix: +- choose the ownership model first +- if imperative mutations are required, keep wrapper inputs/state synchronized deliberately diff --git a/dhtmlx-angular-gantt/references/styling-and-theming.md b/dhtmlx-angular-gantt/references/styling-and-theming.md new file mode 100644 index 0000000..72889fa --- /dev/null +++ b/dhtmlx-angular-gantt/references/styling-and-theming.md @@ -0,0 +1,218 @@ +# Styling And Theming + +Use this file when theming Gantt, matching an app design system, or styling tasks, links, rows, and resource views. + +## Contents +- Styling Priority +- Theme Variables First +- Use Config For Size And Geometry +- Data-Driven Styling +- Common Selectors And Escape Hatches +- Practical Guardrails + +## Styling Priority + +Use this order by default: +1. CSS variables for global theme alignment +2. config for size and geometry +3. templates for semantic or data-driven styling +4. direct CSS selectors only for structural exceptions + +## Theme Variables First + +CSS variables are the preferred customization path. + +Use app theme as single source of truth and map to Gantt `theme` input: + +Define shared variables at `:root` so inheritance works correctly across the whole component: + +```css +:root { + --dhx-gantt-base-colors-primary: #2563eb; + --dhx-gantt-container-background: #ffffff; + --dhx-gantt-container-color: #0f172a; + --dhx-gantt-task-background: #2563eb; + --dhx-gantt-task-color: #ffffff; +} +``` + +### High-Impact Variables + +Typography and surfaces: +- `--dhx-gantt-font-family` +- `--dhx-gantt-font-size` +- `--dhx-gantt-container-background` +- `--dhx-gantt-container-color` +- `--dhx-gantt-scale-background` +- `--dhx-gantt-scale-color` +- `--dhx-gantt-offtime-background` +- `--dhx-gantt-popup-background` +- `--dhx-gantt-popup-color` +- `--dhx-gantt-popup-border` + +Primary and semantic colors: +- `--dhx-gantt-base-colors-primary` +- `--dhx-gantt-base-colors-warning` +- `--dhx-gantt-base-colors-error` +- `--dhx-gantt-base-colors-success` +- `--dhx-gantt-base-colors-text-base` +- `--dhx-gantt-base-colors-text-on-fill` +- `--dhx-gantt-base-colors-border` +- `--dhx-gantt-base-colors-border-light` +- `--dhx-gantt-base-colors-select` +- `--dhx-gantt-base-colors-hover-color` + +Task and project bars: +- `--dhx-gantt-task-background` +- `--dhx-gantt-task-color` +- `--dhx-gantt-project-background` +- `--dhx-gantt-project-color` +- `--dhx-gantt-milestone-background` + +Rows, links: +- `--dhx-gantt-task-row-border` +- `--dhx-gantt-task-row-background` +- `--dhx-gantt-task-row-background--odd` +- `--dhx-gantt-link-background` + +### Map App Tokens To Gantt Tokens + +Use the app theme as the source of truth instead of inventing Gantt-only colors: +- app accent -> `--dhx-gantt-base-colors-primary` +- app surface -> `--dhx-gantt-container-background` +- app body text -> `--dhx-gantt-container-color` and `--dhx-gantt-base-colors-text-base` +- app border -> `--dhx-gantt-base-colors-border` and `--dhx-gantt-base-colors-border-light` +- app selected state -> `--dhx-gantt-base-colors-select` +- app hover state -> `--dhx-gantt-base-colors-hover-color` +- app on-accent text -> `--dhx-gantt-task-color` and `--dhx-gantt-project-color` + +## Use Config For Size And Geometry + +Some visible styling is controlled by Gantt config, not CSS: +- `config.row_height` +- `config.scale_height` +- `config.link_line_width` +- `config.link_radius` +- `config.link_arrow_size` + +## Data-Driven Styling + +When styling depends on task, link, resource, or calendar data, prefer templates. + +### Tasks + +Use `task_class` for semantic task styling: + +```ts +templates = { + task_class: (_start: Date, _end: Date, task: any) => + task.priority ? `priority_${task.priority}` : "", +}; +``` + +```css +.gantt_task_line.priority_high { + --dhx-gantt-task-background: #dc2626; + --dhx-gantt-task-color: #ffffff; +} +``` + +Supported task shortcut color fields: +- `color` +- `textColor` +- `progressColor` + +Important caveat: +- these fields are applied as inline styles +- inline styles have the highest priority +- they can suppress critical-path styling or other CSS overrides + +Use inline color fields only when the app truly stores per-task visual values as data. For reusable semantic styling, `task_class` is usually safer. + +Advanced pattern: +- if colors come from backend-driven entities such as owners or stages, generate CSS classes from the loaded dataset and return those classes from `task_class` + +### Links + +Use `link_class` to style links by dependency type or link metadata: + +```ts +templates = { + link_class: (link: any) => (link.type === "0" ? "finish_to_start" : ""), +}; +``` + +```css +.gantt_task_link.finish_to_start { + --dhx-gantt-link-background: #2563eb; +} +``` + +Supported link shortcut color field: +- `color` + +The same caveat applies: +- link `color` becomes inline style +- inline style overrides other CSS +- critical-link styling and custom classes may not show as expected when inline color is present + +### Rows, Timeline Cells, Resource Cells + +Use template callbacks first: +- `grid_row_class` +- `timeline_cell_class` +- `resource_cell_class` +- `resource_cell_value` + +Use selectors only when styling is structural rather than data-driven. + +### Angular Template Components + +Use `templateComponent(...)` for Angular-rendered templates. + +```ts +import { templateComponent } from "@dhtmlx/trial-angular-gantt"; + +templates = { + task_text: (_start: Date, _end: Date, task: any) => + templateComponent(TaskBadgeComponent, { task }), +}; +``` + +## Common Selectors And Escape Hatches + +Use these when variables or templates are not enough: + +Task bars: +- `.gantt_task_line` +- `.gantt_task_progress` +- `.gantt_task_line.gantt_bar_project` +- `.gantt_task_line.gantt_selected` + +Grid rows and cells: +- `.gantt_row` +- `.gantt_row.odd` +- `.gantt_row.gantt_selected` +- `.gantt_row .gantt_cell[data-column-name="start_date"]` +- `.gantt_grid_head_cell[data-column-id="start_date"]` + +Timeline cells: +- `.gantt_task_row` +- `.gantt_task_row.odd` +- `.gantt_task_cell` +- `.gantt_scale_cell` + +Resource panel scoping: +- `.resourceGrid_cell` +- `.resourceTimeline_cell` +- `.resourceHistogram_cell` + +Resource views reuse many of the same selectors as the main grid and timeline. Scope overrides with the resource layout cell class when the resource panel should look different from the main chart. + +## Practical Guardrails + +- Prefer CSS variables for theme-wide restyling before touching selectors. +- Prefer templates when styling depends on task, link, resource, or calendar data. +- Prefer scoped selectors over global overrides when changing only resource views or only one structural area. +- Do not change `row_height` or `scale_height` in CSS. +- Use link config for line thickness, arrow size, and corner radius.