@weavix/tracker-components 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,51 +1,129 @@
1
1
  # PortfolioIcon
2
2
 
3
3
  <!-- description:start -->
4
- Component displaying an icon for a portfolio entity
4
+ Displays a colored icon for a Tracker portfolio entity. The icon color is deterministically derived from the `portfolioId`, so the same portfolio always renders the same color across sessions and environments.
5
5
  <!-- description:end -->
6
6
 
7
+ ## Usage
8
+
9
+ ```tsx
10
+ import {PortfolioIcon} from '@weavix/tracker-components';
11
+
12
+ <PortfolioIcon portfolioId="portfolio-abc" />
13
+ ```
14
+
7
15
  ## Component props
8
16
 
9
17
  <!-- props:start -->
10
18
  ```ts
11
19
  {
12
20
  /**
13
- * Portfolio ID used to generate a deterministic color
21
+ * Portfolio ID used to generate a deterministic color.
22
+ * Typically the string entity ID returned by the Tracker API.
14
23
  */
15
24
  portfolioId: string;
25
+
16
26
  /**
17
- * Additional class
27
+ * Additional CSS class applied to the root element.
18
28
  */
19
29
  className?: string;
30
+
20
31
  /**
21
- * Entity type label (defaults to "portfolio")
32
+ * Entity type label. Defaults to "portfolio".
22
33
  */
23
34
  type?: string;
35
+
24
36
  /**
25
- * Size of the SVG icon inside the container in pixels
37
+ * Size of the SVG icon inside the container in pixels.
26
38
  * @default 16
27
39
  */
28
40
  size?: number;
41
+
29
42
  /**
30
- * Size of the icon container in pixels
43
+ * Size of the icon container (the colored square) in pixels.
31
44
  * @default 24
32
45
  */
33
46
  refugeSize?: number;
47
+
34
48
  /**
35
- * Whether to render a colored background behind the icon
49
+ * Whether to render a colored background behind the icon.
36
50
  * @default false
37
51
  */
38
52
  withBackground?: boolean;
53
+
39
54
  /**
40
- * Border radius variant of the icon container
55
+ * Border radius variant of the icon container.
41
56
  * @default 'm'
42
57
  */
43
58
  radius?: 'm' | 'l';
59
+
44
60
  /**
45
- * Alpha (opacity) of the icon color
61
+ * Alpha (opacity) of the icon foreground color.
46
62
  * @default 1
47
63
  */
48
64
  colorAlpha?: number;
49
65
  }
50
66
  ```
51
67
  <!-- props:end -->
68
+
69
+ ---
70
+
71
+ ## Examples
72
+
73
+ ### Default
74
+
75
+ ```tsx
76
+ import {PortfolioIcon} from '@weavix/tracker-components';
77
+
78
+ <PortfolioIcon portfolioId="portfolio-abc" />
79
+ ```
80
+
81
+ ### With background
82
+
83
+ ```tsx
84
+ <PortfolioIcon portfolioId="portfolio-abc" withBackground />
85
+ ```
86
+
87
+ ### Custom size
88
+
89
+ ```tsx
90
+ <PortfolioIcon portfolioId="portfolio-abc" size={20} refugeSize={32} />
91
+ ```
92
+
93
+ ### Alongside portfolio name
94
+
95
+ ```tsx
96
+ import {PortfolioIcon} from '@weavix/tracker-components';
97
+
98
+ export const PortfolioLabel = ({portfolio}: {portfolio: {id: string; name: string}}) => (
99
+ <div style={{display: 'flex', alignItems: 'center', gap: 8}}>
100
+ <PortfolioIcon portfolioId={portfolio.id} />
101
+ <span>{portfolio.name}</span>
102
+ </div>
103
+ );
104
+ ```
105
+
106
+ ### Multiple portfolios (each gets a unique color)
107
+
108
+ ```tsx
109
+ const portfolios = [
110
+ {id: 'port-1', name: 'Platform'},
111
+ {id: 'port-2', name: 'Growth'},
112
+ {id: 'port-3', name: 'Infrastructure'},
113
+ ];
114
+
115
+ portfolios.map((p) => (
116
+ <div key={p.id} style={{display: 'flex', alignItems: 'center', gap: 8}}>
117
+ <PortfolioIcon portfolioId={p.id} />
118
+ <span>{p.name}</span>
119
+ </div>
120
+ ));
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Notes
126
+
127
+ - Unlike [`ProjectIcon`](../ProjectIcon/README.md) and [`GoalIcon`](../GoalIcon/README.md), `PortfolioIcon` uses the **string `id`** (not `shortId`) for color generation.
128
+ - `withBackground` defaults to `false` for portfolios (vs `true` for projects). Pass `withBackground` explicitly if you want the colored square background.
129
+ - To render the correct icon for an arbitrary meta entity type, use [`MetaEntityIcon`](../MetaEntityIcon/README.md) instead.
@@ -1,51 +1,175 @@
1
1
  # ProjectIcon
2
2
 
3
3
  <!-- description:start -->
4
- Component displaying an icon for a project entity
4
+ Displays a colored icon for a Tracker project entity. The icon color is deterministically derived from the `projectId`, so the same project always renders the same color across sessions and environments.
5
5
  <!-- description:end -->
6
6
 
7
+ ## Usage
8
+
9
+ ```tsx
10
+ import {ProjectIcon} from '@weavix/tracker-components';
11
+
12
+ <ProjectIcon projectId={123} />
13
+ ```
14
+
7
15
  ## Component props
8
16
 
9
17
  <!-- props:start -->
10
18
  ```ts
11
19
  {
12
20
  /**
13
- * Project ID used to generate a deterministic color
21
+ * Project ID used to generate a deterministic color.
22
+ * Accepts either the numeric shortId or a string entity ID.
14
23
  */
15
24
  projectId?: number | string;
25
+
16
26
  /**
17
- * Additional class
27
+ * Additional CSS class applied to the root element.
18
28
  */
19
29
  className?: string;
30
+
20
31
  /**
21
- * Entity type label (defaults to "project")
32
+ * Entity type label. Defaults to "project".
22
33
  */
23
34
  type?: string;
35
+
24
36
  /**
25
- * Size of the SVG icon inside the container in pixels
37
+ * Size of the SVG icon inside the container in pixels.
26
38
  * @default 16
27
39
  */
28
40
  size?: number;
41
+
29
42
  /**
30
- * Size of the icon container in pixels
43
+ * Size of the icon container (the colored square) in pixels.
31
44
  * @default 24
32
45
  */
33
46
  refugeSize?: number;
47
+
34
48
  /**
35
- * Whether to render a colored background behind the icon
49
+ * Whether to render a colored background behind the icon.
36
50
  * @default true
37
51
  */
38
52
  withBackground?: boolean;
53
+
39
54
  /**
40
- * Border radius variant of the icon container
55
+ * Border radius variant of the icon container.
41
56
  * @default 'm'
42
57
  */
43
58
  radius?: 'm' | 'l';
59
+
44
60
  /**
45
- * Alpha (opacity) of the icon color
61
+ * Alpha (opacity) of the icon foreground color.
46
62
  * @default 1
47
63
  */
48
64
  colorAlpha?: number;
49
65
  }
50
66
  ```
51
67
  <!-- props:end -->
68
+
69
+ ---
70
+
71
+ ## Examples
72
+
73
+ ### Default
74
+
75
+ ```tsx
76
+ import {ProjectIcon} from '@weavix/tracker-components';
77
+
78
+ <ProjectIcon projectId={123} />
79
+ ```
80
+
81
+ ### Without background
82
+
83
+ ```tsx
84
+ // Renders only the colored SVG, no background square
85
+ <ProjectIcon projectId={123} withBackground={false} />
86
+ ```
87
+
88
+ ### Custom size
89
+
90
+ ```tsx
91
+ <ProjectIcon projectId={123} size={20} refugeSize={32} />
92
+ ```
93
+
94
+ ### Large radius
95
+
96
+ ```tsx
97
+ <ProjectIcon projectId={123} radius="l" />
98
+ ```
99
+
100
+ ### Alongside project name
101
+
102
+ ```tsx
103
+ import {ProjectIcon} from '@weavix/tracker-components';
104
+
105
+ export const ProjectLabel = ({project}: {project: {shortId: number; name: string}}) => (
106
+ <div style={{display: 'flex', alignItems: 'center', gap: 8}}>
107
+ <ProjectIcon projectId={project.shortId} />
108
+ <span>{project.name}</span>
109
+ </div>
110
+ );
111
+ ```
112
+
113
+ ### Multiple projects (each gets a unique color)
114
+
115
+ ```tsx
116
+ const projects = [
117
+ {shortId: 1, name: 'Backend API'},
118
+ {shortId: 2, name: 'Mobile App'},
119
+ {shortId: 3, name: 'Design System'},
120
+ ];
121
+
122
+ projects.map((p) => (
123
+ <div key={p.shortId} style={{display: 'flex', alignItems: 'center', gap: 8}}>
124
+ <ProjectIcon projectId={p.shortId} />
125
+ <span>{p.name}</span>
126
+ </div>
127
+ ));
128
+ ```
129
+
130
+ ### Rendering from a Tracker API response
131
+
132
+ The Tracker entities search endpoint returns `shortId` as a number — pass it directly:
133
+
134
+ ```tsx
135
+ import React, {useEffect, useState} from 'react';
136
+ import {ProjectIcon} from '@weavix/tracker-components';
137
+ import type {MetaEntityV2} from '@weavix/tracker-api-types';
138
+
139
+ interface Props {
140
+ trackerApi: TrackerApi;
141
+ }
142
+
143
+ export const ProjectList: React.FC<Props> = ({trackerApi}) => {
144
+ const [projects, setProjects] = useState<MetaEntityV2[]>([]);
145
+
146
+ useEffect(() => {
147
+ trackerApi.v3
148
+ .post['/entities/{entityType}/_search']({
149
+ pathParams: {entityType: 'project'},
150
+ queryParams: {fields: ['summary'], page: 1, perPage: 20},
151
+ bodyParams: {filter: {}, filterTypes: ['ALL'], input: ''},
152
+ })
153
+ .then((result) => setProjects(result.data));
154
+ }, [trackerApi]);
155
+
156
+ return (
157
+ <ul>
158
+ {projects.map((project) => (
159
+ <li key={project.id} style={{display: 'flex', alignItems: 'center', gap: 8}}>
160
+ <ProjectIcon projectId={project.shortId} />
161
+ <span>{project.fields?.summary?.value ?? project.id}</span>
162
+ </li>
163
+ ))}
164
+ </ul>
165
+ );
166
+ };
167
+ ```
168
+
169
+ ---
170
+
171
+ ## Notes
172
+
173
+ - `withBackground` defaults to `true` for projects (vs `false` for [`PortfolioIcon`](../PortfolioIcon/README.md)).
174
+ - Pass `projectId` as the **numeric `shortId`** from the Tracker API for consistent color generation. String IDs are also accepted.
175
+ - To render the correct icon for an arbitrary meta entity type, use [`MetaEntityIcon`](../MetaEntityIcon/README.md) instead.
@@ -0,0 +1,205 @@
1
+ # TrackerDisclosure
2
+
3
+ <!-- description:start -->
4
+ A collapsible section component with Tracker-specific styling. Extends Gravity UI [`Disclosure`](https://gravity-ui.com/components/disclosure) with a configurable chevron arrow (position and size), an optional toolbar slot rendered alongside the summary, and BEM class name hooks for fine-grained styling.
5
+ <!-- description:end -->
6
+
7
+ ## Usage
8
+
9
+ ```tsx
10
+ import {TrackerDisclosure} from '@weavix/tracker-components';
11
+
12
+ <TrackerDisclosure summary="Section title" defaultExpanded>
13
+ Content goes here
14
+ </TrackerDisclosure>
15
+ ```
16
+
17
+ ## Component props
18
+
19
+ <!-- props:start -->
20
+ ```ts
21
+ {
22
+ /**
23
+ * Content shown in the clickable summary / header row.
24
+ * Accepts a string or any ReactNode.
25
+ */
26
+ summary?: ReactNode;
27
+
28
+ /**
29
+ * Content rendered inside the collapsible body.
30
+ */
31
+ children?: ReactNode;
32
+
33
+ /**
34
+ * Whether the section is expanded on first render (uncontrolled).
35
+ * @default false
36
+ */
37
+ defaultExpanded?: boolean;
38
+
39
+ /**
40
+ * Controlled expanded state. When provided, you must also handle onUpdate.
41
+ */
42
+ expanded?: boolean;
43
+
44
+ /**
45
+ * Callback fired when the expanded state changes.
46
+ */
47
+ onUpdate?: (expanded: boolean) => void;
48
+
49
+ /**
50
+ * Whether the disclosure is disabled (non-interactive).
51
+ * @default false
52
+ */
53
+ disabled?: boolean;
54
+
55
+ /**
56
+ * Position of the chevron arrow relative to the summary text.
57
+ * @default 'end'
58
+ */
59
+ arrowPosition?: 'start' | 'end';
60
+
61
+ /**
62
+ * Size of the chevron arrow icon in pixels.
63
+ * @default 20
64
+ */
65
+ arrowSize?: number;
66
+
67
+ /**
68
+ * Optional ReactNode rendered to the right of the toggle button inside the
69
+ * summary row. Useful for action buttons (edit, delete, add, …).
70
+ */
71
+ toolbar?: ReactNode;
72
+
73
+ /**
74
+ * Additional CSS class applied to the root element.
75
+ */
76
+ className?: string;
77
+
78
+ /**
79
+ * Additional CSS class applied to the summary row wrapper.
80
+ */
81
+ summaryClassName?: string;
82
+
83
+ /**
84
+ * Additional CSS class applied to the toggle `<button>` element.
85
+ */
86
+ toggleClassName?: string;
87
+
88
+ /**
89
+ * Additional CSS class applied to the chevron arrow icon.
90
+ */
91
+ arrowClassName?: string;
92
+ }
93
+ ```
94
+ <!-- props:end -->
95
+
96
+ > **Note:** `TrackerDisclosure` accepts all props from Gravity UI [`DisclosureProps`](https://gravity-ui.com/components/disclosure) in addition to the Tracker-specific ones listed above.
97
+
98
+ ---
99
+
100
+ ## Examples
101
+
102
+ ### Basic (uncontrolled)
103
+
104
+ ```tsx
105
+ import {TrackerDisclosure} from '@weavix/tracker-components';
106
+
107
+ <TrackerDisclosure summary="Sprint details" defaultExpanded>
108
+ <p>Sprint 42 — 14 issues, 3 in progress.</p>
109
+ </TrackerDisclosure>
110
+ ```
111
+
112
+ ---
113
+
114
+ ### Controlled
115
+
116
+ ```tsx
117
+ import React, {useState} from 'react';
118
+ import {TrackerDisclosure} from '@weavix/tracker-components';
119
+
120
+ export const ControlledExample = () => {
121
+ const [expanded, setExpanded] = useState(false);
122
+
123
+ return (
124
+ <TrackerDisclosure
125
+ summary="Filters"
126
+ expanded={expanded}
127
+ onUpdate={setExpanded}
128
+ >
129
+ <p>Filter content here.</p>
130
+ </TrackerDisclosure>
131
+ );
132
+ };
133
+ ```
134
+
135
+ ---
136
+
137
+ ### Arrow at start
138
+
139
+ ```tsx
140
+ <TrackerDisclosure summary="Description" arrowPosition="start">
141
+ <p>Content with the chevron on the left.</p>
142
+ </TrackerDisclosure>
143
+ ```
144
+
145
+ ---
146
+
147
+ ### With toolbar
148
+
149
+ The `toolbar` prop renders additional content (e.g. action buttons) to the right of the toggle button, inside the summary row but outside the toggle click area.
150
+
151
+ ```tsx
152
+ import {Button} from '@gravity-ui/uikit';
153
+ import {TrackerDisclosure} from '@weavix/tracker-components';
154
+
155
+ <TrackerDisclosure
156
+ summary="Attachments"
157
+ toolbar={
158
+ <Button size="s" view="flat" onClick={() => openUploadDialog()}>
159
+ Add file
160
+ </Button>
161
+ }
162
+ >
163
+ <AttachmentList />
164
+ </TrackerDisclosure>
165
+ ```
166
+
167
+ ---
168
+
169
+ ### Disabled
170
+
171
+ ```tsx
172
+ <TrackerDisclosure summary="Locked section" disabled defaultExpanded>
173
+ <p>This section cannot be collapsed by the user.</p>
174
+ </TrackerDisclosure>
175
+ ```
176
+
177
+ ---
178
+
179
+ ### Multiple sections (accordion-like)
180
+
181
+ ```tsx
182
+ import React, {useState} from 'react';
183
+ import {TrackerDisclosure} from '@weavix/tracker-components';
184
+
185
+ const SECTIONS = ['Details', 'Attachments', 'Comments'];
186
+
187
+ export const AccordionExample = () => {
188
+ const [openIndex, setOpenIndex] = useState<number | null>(0);
189
+
190
+ return (
191
+ <>
192
+ {SECTIONS.map((title, i) => (
193
+ <TrackerDisclosure
194
+ key={title}
195
+ summary={title}
196
+ expanded={openIndex === i}
197
+ onUpdate={(open) => setOpenIndex(open ? i : null)}
198
+ >
199
+ <p>Content for {title}</p>
200
+ </TrackerDisclosure>
201
+ ))}
202
+ </>
203
+ );
204
+ };
205
+ ```
@@ -0,0 +1,123 @@
1
+ # GoalIcon
2
+
3
+ <!-- description:start -->
4
+ Displays a colored icon for a Tracker goal entity. The icon color is deterministically derived from the `goalId`, so the same goal always renders the same color across sessions and environments.
5
+ <!-- description:end -->
6
+
7
+ ## Usage
8
+
9
+ ```tsx
10
+ import {GoalIcon} from '@weavix/tracker-components';
11
+
12
+ <GoalIcon goalId={456} />
13
+ ```
14
+
15
+ ## Component props
16
+
17
+ <!-- props:start -->
18
+ ```ts
19
+ {
20
+ /**
21
+ * Goal ID used to generate a deterministic color.
22
+ * Accepts either a numeric shortId or a string entity ID.
23
+ */
24
+ goalId: number | string;
25
+
26
+ /**
27
+ * Additional CSS class applied to the root element.
28
+ */
29
+ className?: string;
30
+
31
+ /**
32
+ * Entity type label. Defaults to "goal".
33
+ */
34
+ type?: string;
35
+
36
+ /**
37
+ * Size of the SVG icon inside the container in pixels.
38
+ * @default 16
39
+ */
40
+ size?: number;
41
+
42
+ /**
43
+ * Size of the icon container (the colored square) in pixels.
44
+ * @default 24
45
+ */
46
+ refugeSize?: number;
47
+
48
+ /**
49
+ * Whether to render a colored background behind the icon.
50
+ * @default true
51
+ */
52
+ withBackground?: boolean;
53
+
54
+ /**
55
+ * Border radius variant of the icon container.
56
+ * @default 'm'
57
+ */
58
+ radius?: 'm' | 'l';
59
+
60
+ /**
61
+ * Alpha (opacity) of the icon foreground color.
62
+ * @default 1
63
+ */
64
+ colorAlpha?: number;
65
+ }
66
+ ```
67
+ <!-- props:end -->
68
+
69
+ ---
70
+
71
+ ## Examples
72
+
73
+ ### Default
74
+
75
+ ```tsx
76
+ import {GoalIcon} from '@weavix/tracker-components';
77
+
78
+ <GoalIcon goalId={456} />
79
+ ```
80
+
81
+ ### Custom size
82
+
83
+ ```tsx
84
+ // Larger icon container with a larger SVG inside
85
+ <GoalIcon goalId={456} size={20} refugeSize={32} />
86
+ ```
87
+
88
+ ### Without background
89
+
90
+ ```tsx
91
+ // Renders only the colored SVG, no background square
92
+ <GoalIcon goalId={456} withBackground={false} />
93
+ ```
94
+
95
+ ### Alongside goal name
96
+
97
+ ```tsx
98
+ import {GoalIcon} from '@weavix/tracker-components';
99
+
100
+ export const GoalLabel = ({goal}: {goal: {shortId: number; summary: string}}) => (
101
+ <div style={{display: 'flex', alignItems: 'center', gap: 8}}>
102
+ <GoalIcon goalId={goal.shortId} />
103
+ <span>{goal.summary}</span>
104
+ </div>
105
+ );
106
+ ```
107
+
108
+ ### Multiple goals (each gets a unique color)
109
+
110
+ ```tsx
111
+ const goals = [
112
+ {shortId: 1, summary: 'Increase retention'},
113
+ {shortId: 2, summary: 'Launch mobile app'},
114
+ {shortId: 3, summary: 'Reduce churn'},
115
+ ];
116
+
117
+ goals.map((g) => (
118
+ <div key={g.shortId} style={{display: 'flex', alignItems: 'center', gap: 8}}>
119
+ <GoalIcon goalId={g.shortId} />
120
+ <span>{g.summary}</span>
121
+ </div>
122
+ ));
123
+ ```