@hiver/skills 1.0.1 → 1.0.3
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.
- package/collections/common/skills/discuss-problem/SKILL.md +2 -2
- package/collections/extension/agents/build-feature.md +41 -0
- package/collections/extension/agents/build-milestone.md +62 -0
- package/collections/extension/skills/build-backbone-component/SKILL.md +100 -0
- package/collections/extension/skills/build-backbone-component/references/backbone-scaffolds.md +162 -0
- package/collections/extension/skills/build-backbone-component/references/react-mount-path.md +93 -0
- package/collections/extension/skills/build-component/SKILL.md +33 -0
- package/collections/extension/skills/build-component/palette/README.md +3 -0
- package/collections/extension/skills/build-component/palette/colors.md +87 -0
- package/collections/extension/skills/build-component/references/best-practices.md +8 -0
- package/collections/extension/skills/build-component/references/component-organization.md +21 -0
- package/collections/extension/skills/build-component/references/figma-integration.md +5 -0
- package/collections/extension/skills/build-component/references/icons/brand-icons.png +0 -0
- package/collections/extension/skills/build-component/references/icons/mui-icons.png +0 -0
- package/collections/extension/skills/build-component/references/icons.md +81 -0
- package/collections/extension/skills/build-component/references/layout-and-structure.md +8 -0
- package/collections/extension/skills/build-component/references/state-management.md +25 -0
- package/collections/extension/skills/build-component/references/ui-kit-and-styling.md +13 -0
- package/collections/extension/skills/build-component/typography/README.md +3 -0
- package/collections/extension/skills/build-component/typography/variants.md +139 -0
- package/collections/extension/skills/ci-cd/SKILL.md +67 -0
- package/collections/extension/skills/ci-cd/references/bundle-and-troubleshooting.md +50 -0
- package/collections/extension/skills/ci-cd/references/file-registry.md +28 -0
- package/collections/extension/skills/connect-api/SKILL.md +23 -0
- package/collections/extension/skills/connect-api/references/api-call-structure.md +84 -0
- package/collections/extension/skills/connect-api/references/best-practices.md +10 -0
- package/collections/extension/skills/connect-api/references/data-fetchers.md +52 -0
- package/collections/extension/skills/connect-api/references/error-handling.md +34 -0
- package/collections/extension/skills/connect-api/references/hook-organization.md +11 -0
- package/collections/extension/skills/connect-api/references/query-keys.md +21 -0
- package/collections/extension/skills/connect-api/references/react-query-usage.md +83 -0
- package/collections/extension/skills/connect-api/references/url-placeholders.md +17 -0
- package/collections/extension/skills/modify-extension/SKILL.md +110 -0
- package/collections/extension/skills/modify-extension/references/architecture.md +55 -0
- package/collections/extension/skills/modify-extension/references/implementation-patterns.md +180 -0
- package/collections/extension/skills/scaffold-react-feature/SKILL.md +141 -0
- package/collections/extension/skills/write-test-cases/SKILL.md +93 -0
- package/collections/web/skills/build-component/references/icons/brand-icons.png +0 -0
- package/collections/web/skills/build-component/references/icons/mui-icons.png +0 -0
- package/collections/web/skills/build-component/references/icons.md +79 -6
- package/collections/web/skills/build-component/typography/variants.md +62 -2
- package/package.json +1 -1
|
@@ -36,8 +36,8 @@ Help the user to grill down on a problem to its core discussing all sorts of the
|
|
|
36
36
|
|
|
37
37
|
1. Take input from the user related to the problem they want to discuss or grill down
|
|
38
38
|
2. If the problem is related to building a new feature, check with the user if prototype designs are available
|
|
39
|
-
3. If Figma designs are available, use the Figma MCP tool to get the prototype details and analyze them
|
|
40
|
-
4. Keep asking if the user has more Figma designs available until all designs are provided; keep using the Figma MCP tool to load them into memory
|
|
39
|
+
3. If Figma designs are available, use the claude Figma desktop MCP tool to get the prototype details and analyze them
|
|
40
|
+
4. Keep asking if the user has more Figma designs available until all designs are provided; keep using the claude Figma desktop MCP tool to load them into memory
|
|
41
41
|
5. Analyze the problem statement in context of the current codebase — use read and search tools to explore, never write tools
|
|
42
42
|
6. Ask the right questions until you are clear on the problem statement
|
|
43
43
|
7. Go through the codebase and figure out how the problem can be solved — discussion only
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-feature
|
|
3
|
+
model: default
|
|
4
|
+
description: Senior Manager owning a PRD to build the feature from end to end
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are a Senior Manager who has owned a PRD to develop the feature or issue mentioned inside it from end to end.
|
|
8
|
+
|
|
9
|
+
> **HARD RULE — NEVER VIOLATE:**
|
|
10
|
+
> You are a **manager**, not an implementer. You MUST NEVER write, edit, or implement code yourself. Every milestone MUST be implemented exclusively by spawning a `build-milestone` subagent. Skipping subagent spawning and implementing directly is strictly forbidden, regardless of how simple a milestone appears.
|
|
11
|
+
|
|
12
|
+
**Token efficiency rules:**
|
|
13
|
+
- **Do NOT re-read milestone documents** after the initial analysis — you already know the scope.
|
|
14
|
+
- **Keep review conversations brief** — when presenting milestones to the user, summarize the changes in 3-5 bullet points instead of replaying the full milestone doc.
|
|
15
|
+
- **Spawn independent milestones in parallel** to avoid sequential context accumulation.
|
|
16
|
+
|
|
17
|
+
When invoked:
|
|
18
|
+
1. Ask for the directory path for the milestones implementation documents.
|
|
19
|
+
2. Analyze the documents inside that directory.
|
|
20
|
+
3. Create a `progress.md` in the same directory if not already present, listing all milestones in table format with status `Pending`:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
| Milestone | Status |
|
|
24
|
+
|-----------|--------|
|
|
25
|
+
| M1: <name> | Pending |
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Valid statuses: `Pending` | `In Progress` | `Review Required` | `Completed`
|
|
29
|
+
|
|
30
|
+
4. Pick the next milestone(s) that are not `Completed`. Start with all independent milestones first (they can be spawned in parallel). Dependent milestones only start after their dependencies are `Completed`.
|
|
31
|
+
5. **MANDATORY:** Spawn a `build-milestone` subagent in **normal mode** for each ready milestone, passing the milestone document path. You MUST spawn the subagent — do not implement the milestone yourself under any circumstances.
|
|
32
|
+
6. Wait for the subagent(s) to finish, then re-read `progress.md`.
|
|
33
|
+
7. If the milestone status is `Review Required`:
|
|
34
|
+
a. Present the milestone to the user with a brief summary (3-5 bullets of what changed) and ask for approval.
|
|
35
|
+
b. **If approved:** update `progress.md` → `Completed`. Repeat from step 4.
|
|
36
|
+
c. **If rejected:** collect the user's feedback. Write it to `milestone-feedbacks/<milestone-name>-feedback.md` in the same root directory (create the file if it doesn't exist; if it exists, mark all current active feedback entries as stale and append the new feedback as the active entry). **MANDATORY:** Spawn a `build-milestone` subagent in **fix mode**, passing both the milestone document path and the feedback file path. Repeat from step 6.
|
|
37
|
+
8. Once all milestones are `Completed`, run the following post-processing steps in order:
|
|
38
|
+
a. **Prettify** — get the list of all modified files via `git diff --name-only` and run the project formatter (Prettier / ESLint `--fix`) on them.
|
|
39
|
+
b. **Lint check** — run the linter on the same file set and surface any remaining errors to the user.
|
|
40
|
+
c. **Remove debug artifacts** — scan all modified files for leftover `console.log`, `debugger` statements, and agent-added `TODO` comments. Remove them.
|
|
41
|
+
9. Exit.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-milestone
|
|
3
|
+
model: sonnet
|
|
4
|
+
description: Senior Frontend specialist helping to complete a milestone from the PRD document.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are a Senior frontend developer with years of experience in frontend development, debugging issues and developing features from end to end.
|
|
8
|
+
|
|
9
|
+
**Source of truth principle:**
|
|
10
|
+
- The milestone document is the authority on **WHAT** — goal, architectural approach, feature flag, affected areas, skills to activate, and acceptance criteria.
|
|
11
|
+
- The `milestone-tests/<milestone-name>-tests.md` file is the authority on **test progress** — it is the single source of truth for what has been verified and what remains pending.
|
|
12
|
+
- The skills are the authority on **HOW** — exact files to create, exact registration lines, exact wiring and scaffolding. Never override a skill's output with anything written in the milestone doc. If there is a conflict, the skill wins.
|
|
13
|
+
|
|
14
|
+
**Token efficiency rules:**
|
|
15
|
+
- **Only load skills listed in the milestone doc's "Skills to activate" section.** Do NOT read or reference skills that are not listed. If the milestone says `skills: [build-component, connect-api]`, do NOT load `modify-extension`, `ci-cd`, `build-backbone-component`, or any other skill.
|
|
16
|
+
- **Within each skill, load reference files lazily** — only when you are about to perform the specific task that reference covers. Do NOT read all reference files upfront.
|
|
17
|
+
- **Minimize file re-reads** — read a file once, retain key details in your reasoning, do not re-read unless the file was modified.
|
|
18
|
+
|
|
19
|
+
**Invocation modes:**
|
|
20
|
+
|
|
21
|
+
## Normal Mode
|
|
22
|
+
Invoked with: milestone document path only.
|
|
23
|
+
|
|
24
|
+
1. Ask for the path to the milestone document.
|
|
25
|
+
2. Read the milestone document thoroughly. Extract: goal, architectural approach, feature flag decision, skills to activate, and acceptance criteria.
|
|
26
|
+
3. Update `progress.md` → status: **In Progress** for the current milestone.
|
|
27
|
+
4. **Invoke the `write-test-cases` skill (Normal Mode)** — pass the milestone document path. Wait for the skill to finish writing all test cases to `milestone-tests/<milestone-name>-tests.md` before proceeding. Do not write any implementation code before this step completes.
|
|
28
|
+
5. **Batched TDD loop** — read `milestone-tests/<milestone-name>-tests.md` **once** and load all `⬜ Pending` TCs into memory. Do NOT re-read the file on each iteration. **Group related TCs** (e.g., TCs that test the same component, same API, or same user flow) and implement them together in batches:
|
|
29
|
+
a. Pick the next batch of related `⬜ Pending` TCs from the in-memory list (2-4 TCs per batch when they share implementation scope).
|
|
30
|
+
b. If none remain → all TCs pass → go to step 6.
|
|
31
|
+
c. Reason: "what code do I need to write to make this batch of TCs pass?" — think before acting.
|
|
32
|
+
d. Implement using **only** the skills listed in the milestone doc's "Skills to activate" section, invoking them in this order as needed:
|
|
33
|
+
- `build-backbone-component` → scaffolding, Model/Collection/View/Controller/template/SASS, React-into-Backbone mount
|
|
34
|
+
- `scaffold-react-feature` → folder structure, wiring, feature flag boilerplate
|
|
35
|
+
- `build-component` → UI (React path)
|
|
36
|
+
- `connect-api` → data fetching and mutations
|
|
37
|
+
- `ci-cd` → read and follow **before** any pipeline/build script changes
|
|
38
|
+
- `modify-extension` → read and follow before touching any Chrome extension layer code
|
|
39
|
+
e. Trace through the implemented code — do the `Then` conditions of all TCs in the batch hold?
|
|
40
|
+
- All pass → update all statuses to `✅ Pass` in the test file (single write) → go to step (a)
|
|
41
|
+
- Some fail → re-think → fix code → trace again → update statuses → go to step (a)
|
|
42
|
+
6. Once every test case passes, update `progress.md` → status: **Review Required** and exit.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Fix Mode
|
|
47
|
+
Invoked with: milestone document path + feedback file path.
|
|
48
|
+
|
|
49
|
+
1. Read the milestone document to understand the goal and scope.
|
|
50
|
+
2. Read the feedback file. Identify the **active** (non-stale) feedback entry — this is the only feedback to address.
|
|
51
|
+
3. Update `progress.md` → status: **In Progress** for the current milestone.
|
|
52
|
+
4. **Invoke the `write-test-cases` skill (Feedback Mode)** — pass the milestone document path and feedback file path. Wait for the skill to finish appending the new feedback-scoped TCs under `## Feedback Round N` in the existing `milestone-tests/<milestone-name>-tests.md`.
|
|
53
|
+
5. **Batched TDD loop** — read `milestone-tests/<milestone-name>-tests.md` **once**, load the `⬜ Pending` TCs from the current Feedback Round section into memory. Group related TCs and implement in batches:
|
|
54
|
+
a. Pick the next batch of related `⬜ Pending` TCs from the in-memory list.
|
|
55
|
+
b. If none remain → go to step 6.
|
|
56
|
+
c. Reason: "what change do I need to make to satisfy this batch of TCs?" — think before acting.
|
|
57
|
+
d. Apply only the changes needed to address the active feedback. Do **not** re-scaffold or re-implement what is already done. Load **only** the skills needed for the fix.
|
|
58
|
+
e. Trace through the changed code — do the `Then` conditions hold?
|
|
59
|
+
- All pass → update statuses in the test file → go to step (a)
|
|
60
|
+
- Some fail → re-think → fix → trace again → update statuses → go to step (a)
|
|
61
|
+
6. Once all feedback TCs pass, mark the active feedback entry in the feedback file as stale (strikethrough heading and body, append `(stale)` label). Keep the entry — do not delete it.
|
|
62
|
+
7. Update `progress.md` → status: **Review Required** and exit.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-backbone-component
|
|
3
|
+
description: Scaffold and build UI components and logic in the Backbone module system. Covers Model, Collection, View, Controller, templates, SASS, and optionally mounting a React component into a Backbone View. Use when the task involves building a new Backbone module or adding to an existing one.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Build Backbone Component
|
|
7
|
+
|
|
8
|
+
**Scope:** Building UI and logic inside `src/modules/<featureName>/` — Models, Collections, Views,
|
|
9
|
+
Controllers, Underscore templates, and SASS. Also covers the React-into-Backbone mounting path
|
|
10
|
+
when the UI is better built in React.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Step 1 — Understand the Requirement
|
|
15
|
+
|
|
16
|
+
Read the input carefully. Identify:
|
|
17
|
+
- What data does this component need? Where does it live?
|
|
18
|
+
- Does the UI slot naturally into an existing HTML template, or is it a standalone interactive widget?
|
|
19
|
+
- Does it need to share its logic/API with other modules?
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Step 2 — Choose the Rendering Path
|
|
24
|
+
|
|
25
|
+
### Backbone Template path (default)
|
|
26
|
+
Use when:
|
|
27
|
+
- The data the component needs lives on the Backbone side (models, collections, `grexit.*` globals)
|
|
28
|
+
- The UI slots naturally into an existing HTML template — inserting a `<div>` and rendering into it is simpler than wiring a React mount point
|
|
29
|
+
- Interactivity can be handled with Backbone `events` + jQuery
|
|
30
|
+
|
|
31
|
+
### React Mount path
|
|
32
|
+
Use when:
|
|
33
|
+
- The component is complex and interactive: needs hooks, React Query, or local React state
|
|
34
|
+
- The data it needs already lives in the Redux store or comes from React Query
|
|
35
|
+
- Building the equivalent insertion/wiring logic in React is simpler than doing it in Backbone
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Step 3 — Determine Which Files to Create
|
|
40
|
+
|
|
41
|
+
| File | When to create |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `<FeatureName>Model.js` | When the component has meaningful state or data attributes |
|
|
44
|
+
| `<FeatureName>Collection.js` | When working with a list of models |
|
|
45
|
+
| `<FeatureName>View.js` | Always |
|
|
46
|
+
| `<FeatureName>Controller.js` | Only when logic needs to be exposed to other modules |
|
|
47
|
+
| `templates.html` | Always on the Backbone Template path |
|
|
48
|
+
| `src/sass/framework_revamp/<featureName>.sass` | Always |
|
|
49
|
+
|
|
50
|
+
For the React Mount path, additionally:
|
|
51
|
+
|
|
52
|
+
| File | Purpose |
|
|
53
|
+
|---|---|
|
|
54
|
+
| `react-extn/src/<FeatureName>/<FeatureName>.jsx` | React component |
|
|
55
|
+
| `react-extn/src/<FeatureName>/mounter.js` | Mount factory |
|
|
56
|
+
| `react-extn/src/ReactBackboneModules/index.js` | Registration (add import + entry) |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Step 4 — Create the Module Folder
|
|
61
|
+
|
|
62
|
+
Create `src/modules/<featureName>/`. The gulp build auto-discovers all folders under `src/modules/`
|
|
63
|
+
via `build_utils.getModules()` — no manual webpack alias registration is needed.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Step 5 — Scaffold the Files
|
|
68
|
+
|
|
69
|
+
### Conventions
|
|
70
|
+
- **CommonJS only** (`require` / `module.exports`) for all Backbone files
|
|
71
|
+
- **IIFE pattern** wrapping `Backbone.Model.extend` / `Backbone.Collection.extend`
|
|
72
|
+
- **Plain IIFE singleton** for Controllers — not a Backbone class
|
|
73
|
+
- **Template IDs** → `h-<feature-name>-<element>` (must be globally unique across the app)
|
|
74
|
+
- **`destroyView`** is the standard teardown method — not `close` or `remove` alone
|
|
75
|
+
|
|
76
|
+
## Reference files
|
|
77
|
+
|
|
78
|
+
**Load lazily — only read a reference file when you are about to perform that specific task. Do NOT read all files upfront.**
|
|
79
|
+
|
|
80
|
+
| Topic | File | When to load |
|
|
81
|
+
|-------|------|--------------|
|
|
82
|
+
| Backbone scaffolds (Model, Collection, View, Controller, Template, SASS) | [references/backbone-scaffolds.md](references/backbone-scaffolds.md) | When creating Backbone files |
|
|
83
|
+
| React mount path (mounter, registration, wiring) | [references/react-mount-path.md](references/react-mount-path.md) | Only when using React Mount path |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Checklist
|
|
88
|
+
|
|
89
|
+
- [ ] Rendering path chosen (Backbone template or React mount) with clear reasoning
|
|
90
|
+
- [ ] `src/modules/<featureName>/` folder created
|
|
91
|
+
- [ ] Model created (if needed)
|
|
92
|
+
- [ ] Collection created (if needed)
|
|
93
|
+
- [ ] View created with `destroyView`
|
|
94
|
+
- [ ] Controller created only if logic is shared externally
|
|
95
|
+
- [ ] `templates.html` created with `h-` prefixed IDs (Backbone path)
|
|
96
|
+
- [ ] `src/sass/framework_revamp/<featureName>.sass` created and `@import` added to `style.sass`
|
|
97
|
+
- [ ] React component + mounter created (React path)
|
|
98
|
+
- [ ] Mounter registered in `ReactBackboneModules/index.js` (React path)
|
|
99
|
+
- [ ] `window.react?.modules.<name>.mount(...)` called in View with `this.reactRoot` stored (React path)
|
|
100
|
+
- [ ] `this.reactRoot.unmount()` called in `destroyView` before `this.remove()` (React path)
|
package/collections/extension/skills/build-backbone-component/references/backbone-scaffolds.md
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Backbone Scaffolds — Code Templates
|
|
2
|
+
|
|
3
|
+
## Model (`<FeatureName>Model.js`)
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
var Backbone = require('backbone');
|
|
7
|
+
var _ = require('underscore-new');
|
|
8
|
+
|
|
9
|
+
var <FeatureName>Model = (function() {
|
|
10
|
+
return Backbone.Model.extend({
|
|
11
|
+
defaults: function() {
|
|
12
|
+
return {
|
|
13
|
+
// default attributes
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
})();
|
|
18
|
+
|
|
19
|
+
module.exports = <FeatureName>Model;
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Collection (`<FeatureName>Collection.js`)
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
var Backbone = require('backbone');
|
|
28
|
+
var <ItemModel> = require('<ItemModel>');
|
|
29
|
+
|
|
30
|
+
var <FeatureName>Collection = (function() {
|
|
31
|
+
'use strict';
|
|
32
|
+
return Backbone.Collection.extend({
|
|
33
|
+
model: <ItemModel>,
|
|
34
|
+
comparator: function(m) {
|
|
35
|
+
// optional: return the value to sort by
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
})();
|
|
39
|
+
|
|
40
|
+
module.exports = <FeatureName>Collection;
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## View (`<FeatureName>View.js`)
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
var Backbone = require('backbone');
|
|
49
|
+
var $ = require('jquery');
|
|
50
|
+
var _ = require('underscore-new');
|
|
51
|
+
|
|
52
|
+
var <FeatureName>View = Backbone.View.extend({
|
|
53
|
+
|
|
54
|
+
template: _.template($('#h-<feature-name>-container').html()),
|
|
55
|
+
|
|
56
|
+
initialize: function(options) {
|
|
57
|
+
this.options = options;
|
|
58
|
+
this.listenTo(this.model, 'change:<attr>', this.render);
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
events: {
|
|
62
|
+
'click .h-<feature-name>-btn': 'handleClick',
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
render: function() {
|
|
66
|
+
this.$el.html(this.template(this.model.toJSON()));
|
|
67
|
+
return this;
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
handleClick: function(e) {
|
|
71
|
+
// event handler
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
destroyView: function() {
|
|
75
|
+
this.undelegateEvents();
|
|
76
|
+
this.model.unbind(); // omit if no model
|
|
77
|
+
this.$el.removeData().unbind();
|
|
78
|
+
// remove external listeners: document.removeEventListener(...)
|
|
79
|
+
// unmount React children: this.reactRoot && this.reactRoot.unmount()
|
|
80
|
+
this.remove();
|
|
81
|
+
Backbone.View.prototype.remove.call(this);
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
module.exports = <FeatureName>View;
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Controller (`<FeatureName>Controller.js`)
|
|
91
|
+
|
|
92
|
+
Only create when this module's logic or state needs to be accessed by other modules.
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
var $ = require('jquery');
|
|
96
|
+
var _ = require('underscore-new');
|
|
97
|
+
var <FeatureName>Model = require('<FeatureName>Model');
|
|
98
|
+
var <FeatureName>View = require('<FeatureName>View');
|
|
99
|
+
|
|
100
|
+
var <FeatureName>Controller = (function() {
|
|
101
|
+
'use strict';
|
|
102
|
+
|
|
103
|
+
var viewInstance = null;
|
|
104
|
+
|
|
105
|
+
function render(el, data) {
|
|
106
|
+
var model = new <FeatureName>Model();
|
|
107
|
+
model.set(data);
|
|
108
|
+
viewInstance = new <FeatureName>View({ model: model, el: el });
|
|
109
|
+
viewInstance.render();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function clearView() {
|
|
113
|
+
if (viewInstance) {
|
|
114
|
+
viewInstance.destroyView();
|
|
115
|
+
viewInstance = null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function init() {
|
|
120
|
+
// subscribe to pubsub events if needed
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
init();
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
render: render,
|
|
127
|
+
clearView: clearView,
|
|
128
|
+
};
|
|
129
|
+
})();
|
|
130
|
+
|
|
131
|
+
module.exports = <FeatureName>Controller;
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Template (`templates.html`)
|
|
137
|
+
|
|
138
|
+
```html
|
|
139
|
+
<script type="text/template" id="h-<feature-name>-container">
|
|
140
|
+
<div class="h-<feature-name>">
|
|
141
|
+
<!--
|
|
142
|
+
Underscore template syntax:
|
|
143
|
+
<%= value %> escaped output
|
|
144
|
+
<%- value %> unescaped output
|
|
145
|
+
<% code %> logic / conditionals
|
|
146
|
+
-->
|
|
147
|
+
</div>
|
|
148
|
+
</script>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The gulp `build_template_files` task auto-picks up `templates.html` from every module folder —
|
|
152
|
+
no manual registration needed.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## SASS (`src/sass/framework_revamp/<featureName>.sass`)
|
|
157
|
+
|
|
158
|
+
Create the file, then add one line to `src/sass/framework_revamp/style.sass`:
|
|
159
|
+
|
|
160
|
+
```sass
|
|
161
|
+
@import '<featureName>'
|
|
162
|
+
```
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# React Mount Path — Mounting React Inside Backbone
|
|
2
|
+
|
|
3
|
+
## React Component + Mounter
|
|
4
|
+
|
|
5
|
+
**Without Redux** (component uses React Query only or is stateless):
|
|
6
|
+
|
|
7
|
+
```jsx
|
|
8
|
+
// react-extn/src/<FeatureName>/mounter.js
|
|
9
|
+
import { createRoot } from 'react-dom/client';
|
|
10
|
+
import { HiverProvider } from '@hiver/hiver-ui-kit';
|
|
11
|
+
import HiverQueryClientProvider from '../../reactQueryClient.js';
|
|
12
|
+
import { <FeatureName> } from './<FeatureName>';
|
|
13
|
+
|
|
14
|
+
export const mount<FeatureName> = (container, props) => {
|
|
15
|
+
const root = createRoot(container);
|
|
16
|
+
root.render(
|
|
17
|
+
<HiverProvider>
|
|
18
|
+
<HiverQueryClientProvider>
|
|
19
|
+
<FeatureName> {...props} unmount={() => root.unmount()} />
|
|
20
|
+
</HiverQueryClientProvider>
|
|
21
|
+
</HiverProvider>
|
|
22
|
+
);
|
|
23
|
+
return root.unmount.bind(root);
|
|
24
|
+
};
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**With Redux** (component reads from or dispatches to the Redux store):
|
|
28
|
+
|
|
29
|
+
```jsx
|
|
30
|
+
// react-extn/src/<FeatureName>/mounter.js
|
|
31
|
+
import { createRoot } from 'react-dom/client';
|
|
32
|
+
import { Provider } from 'react-redux';
|
|
33
|
+
import { HiverProvider } from '@hiver/hiver-ui-kit';
|
|
34
|
+
import HiverQueryClientProvider from '../../reactQueryClient.js';
|
|
35
|
+
import { <FeatureName> } from './<FeatureName>';
|
|
36
|
+
|
|
37
|
+
export const mount<FeatureName> = (store) => (container, props) => {
|
|
38
|
+
const root = createRoot(container);
|
|
39
|
+
root.render(
|
|
40
|
+
<HiverProvider>
|
|
41
|
+
<HiverQueryClientProvider>
|
|
42
|
+
<Provider store={store}>
|
|
43
|
+
<FeatureName> {...props} unmount={() => root.unmount()} />
|
|
44
|
+
</Provider>
|
|
45
|
+
</HiverQueryClientProvider>
|
|
46
|
+
</HiverProvider>
|
|
47
|
+
);
|
|
48
|
+
return root.unmount.bind(root);
|
|
49
|
+
};
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Register in `ReactBackboneModules/index.js`
|
|
53
|
+
|
|
54
|
+
Add the import at the top of the file:
|
|
55
|
+
```js
|
|
56
|
+
import { mount<FeatureName> } from '../<FeatureName>/mounter';
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Inside `appendReactBackboneModules()`, add to the `modules` object:
|
|
60
|
+
```js
|
|
61
|
+
// without Redux:
|
|
62
|
+
<featureName>: createModule(mount<FeatureName>),
|
|
63
|
+
|
|
64
|
+
// with Redux:
|
|
65
|
+
<featureName>: createModule(mount<FeatureName>(store)),
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Use camelCase for the module key.
|
|
69
|
+
|
|
70
|
+
## Wire mount/unmount in the Backbone View
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
// in initialize or render — create container and mount:
|
|
74
|
+
var container = document.createElement('div');
|
|
75
|
+
container.id = 'h-<feature-name>-react-root';
|
|
76
|
+
this.$el.find('.h-<feature-name>-mount-point').append(container);
|
|
77
|
+
this.reactRoot = window.react?.modules.<featureName>.mount(container, {
|
|
78
|
+
prop1: this.model.get('attr1'),
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// in destroyView — unmount before remove:
|
|
82
|
+
destroyView: function() {
|
|
83
|
+
this.undelegateEvents();
|
|
84
|
+
this.model.unbind();
|
|
85
|
+
this.$el.removeData().unbind();
|
|
86
|
+
if (this.reactRoot) {
|
|
87
|
+
this.reactRoot.unmount();
|
|
88
|
+
this.reactRoot = null;
|
|
89
|
+
}
|
|
90
|
+
this.remove();
|
|
91
|
+
Backbone.View.prototype.remove.call(this);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-component
|
|
3
|
+
description: Build UI React components following Hiver design system and patterns
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Build Component
|
|
7
|
+
|
|
8
|
+
**Scope:** Pure UI concerns only — Figma → React component, Hiver UI kit, layout, icons, typography, component organization, and UI-level state management.
|
|
9
|
+
|
|
10
|
+
**Out of scope:** Feature folder structure, Backbone mounting, `ReactBackboneModules` registration, lazy imports in `index.js`, and feature flag wiring. Those belong in the `scaffold-react-feature` skill.
|
|
11
|
+
|
|
12
|
+
When building UI React components, use the currently selected Figma node as the design reference and follow the Hiver design system. Use `@hiver/hiver-ui-kit` for all components; prefer `Stack` for layout and MUI/SVG for icons. Map Figma colors and text styles using the **palette** and **typography** references below.
|
|
13
|
+
|
|
14
|
+
## Reference files
|
|
15
|
+
|
|
16
|
+
**Load lazily — only read a reference file when you are about to perform that specific task. Do NOT read all files upfront.**
|
|
17
|
+
|
|
18
|
+
| Topic | File | When to load |
|
|
19
|
+
|-------|------|--------------|
|
|
20
|
+
| Figma integration | [references/figma-integration.md](references/figma-integration.md) | Only when a Figma link is present |
|
|
21
|
+
| UI Kit and styling | [references/ui-kit-and-styling.md](references/ui-kit-and-styling.md) | Before writing component JSX/styles |
|
|
22
|
+
| Layout and structure | [references/layout-and-structure.md](references/layout-and-structure.md) | Only when laying out a new screen/panel |
|
|
23
|
+
| Icons | [references/icons.md](references/icons.md) | Only when adding icons |
|
|
24
|
+
| Component organization | [references/component-organization.md](references/component-organization.md) | Only when splitting into sub-components |
|
|
25
|
+
| State management | [references/state-management.md](references/state-management.md) | Only when adding local or shared state |
|
|
26
|
+
| Best practices | [references/best-practices.md](references/best-practices.md) | Only when uncertain about a pattern |
|
|
27
|
+
|
|
28
|
+
### Figma → design tokens (map colors and type from Figma here)
|
|
29
|
+
|
|
30
|
+
| Topic | File |
|
|
31
|
+
|-------|------|
|
|
32
|
+
| **Palette** (colors) | [palette/README.md](palette/README.md) |
|
|
33
|
+
| **Typography** (variants) | [typography/README.md](typography/README.md) |
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Palette reference (`@hiver/hiver-ui-kit`)
|
|
2
|
+
|
|
3
|
+
Use this to map Figma fill/text colors to theme tokens. Prefer `theme.palette.*` or `sx={{ color: '...' }}` with these tokens.
|
|
4
|
+
|
|
5
|
+
## Semantic / brand colors
|
|
6
|
+
|
|
7
|
+
| Token | Hex | Usage |
|
|
8
|
+
|-------|-----|--------|
|
|
9
|
+
| `palette.yellow.primary` | `#FFE250` | Primary yellow |
|
|
10
|
+
| `palette.yellow.hover` | `#FCCF59` | Yellow hover |
|
|
11
|
+
| `palette.yellow.light` | `#FFF0D3` | Yellow light bg |
|
|
12
|
+
| `palette.blue.primary` | `#196FE0` | Primary blue |
|
|
13
|
+
| `palette.blue.hover` | `#0456C2` | Blue hover |
|
|
14
|
+
| `palette.blue.light` | `#E2F1FF` | Blue light bg |
|
|
15
|
+
| `palette.purple.primary` | `#506DFF` | Primary purple (theme primary) |
|
|
16
|
+
| `palette.purple.hover` | `#4763F0` | Purple hover |
|
|
17
|
+
| `palette.purple.light` | `#F0F3FF` | Purple light bg |
|
|
18
|
+
| `palette.green.primary` | `#00BC7E` | Success / green |
|
|
19
|
+
| `palette.green.hover` | `#05A570` | Green hover |
|
|
20
|
+
| `palette.green.light` | `#E3FCF4` | Green light bg |
|
|
21
|
+
| `palette.red.primary` | `#CD3746` | Error / red |
|
|
22
|
+
| `palette.red.hover` | `#D24B58` | Red hover |
|
|
23
|
+
| `palette.red.light` | `#FFE0E3` | Red light bg |
|
|
24
|
+
| `palette.orange.primary` | `#FF8B00` | Warning / orange |
|
|
25
|
+
| `palette.orange.hover` | `#DE7D0A` | Orange hover |
|
|
26
|
+
| `palette.orange.light` | `#FFEFE0` | Orange light bg |
|
|
27
|
+
|
|
28
|
+
## Gray scale
|
|
29
|
+
|
|
30
|
+
| Token | Hex | Usage |
|
|
31
|
+
|-------|-----|--------|
|
|
32
|
+
| `palette.gray.gray1` | `#3E4C5A` | Darkest gray |
|
|
33
|
+
| `palette.gray.gray2` | `#4D596C` | Text primary |
|
|
34
|
+
| `palette.gray.gray3` | `#6F7C90` | |
|
|
35
|
+
| `palette.gray.gray4` | `#97A3B7` | Text secondary, disabled |
|
|
36
|
+
| `palette.gray.gray5` | `#D6DDE8` | |
|
|
37
|
+
| `palette.gray.gray6` | `#ECEFF6` | Borders, dividers |
|
|
38
|
+
| `palette.gray.gray6a` | `#F6F8FC` | |
|
|
39
|
+
| `palette.gray.gray7` | `#0F13160A` | Subtle overlay |
|
|
40
|
+
| `palette.gray.background` | `#FCFCFF` | Page background |
|
|
41
|
+
| `palette.gray.white16` | `rgba(255, 255, 255, 0.16)` | White 16% opacity |
|
|
42
|
+
| `palette.gray.white` | `#FFFFFF` | White |
|
|
43
|
+
| `palette.gray.black` | `#343C45` | Black / primary text |
|
|
44
|
+
|
|
45
|
+
## Tag colors
|
|
46
|
+
|
|
47
|
+
| Token | Hex |
|
|
48
|
+
|-------|-----|
|
|
49
|
+
| `palette.tag.gray` | `#90A4AE` |
|
|
50
|
+
| `palette.tag.green` | `#81C784` |
|
|
51
|
+
| `palette.tag.red` | `#E57373` |
|
|
52
|
+
| `palette.tag.yellow` | `#FFC107` |
|
|
53
|
+
| `palette.tag.blue` | `#64B5F6` |
|
|
54
|
+
| `palette.tag.teal` | `#4DD0E1` |
|
|
55
|
+
| `palette.tag.brown` | `#A1887F` |
|
|
56
|
+
| `palette.tag.pink` | `#FF5B92` |
|
|
57
|
+
| `palette.tag.purpleDark` | `#9575CD` |
|
|
58
|
+
| `palette.tag.purpleLight` | `#CE93D8` |
|
|
59
|
+
|
|
60
|
+
## Avatar colors (array)
|
|
61
|
+
|
|
62
|
+
Use `palette.avatar[index]` for avatar backgrounds (e.g. by user index).
|
|
63
|
+
|
|
64
|
+
| Index | Hex |
|
|
65
|
+
|-------|-----|
|
|
66
|
+
| 0 | `#F05388` |
|
|
67
|
+
| 1 | `#BE75CA` |
|
|
68
|
+
| 2 | `#E57373` |
|
|
69
|
+
| 3 | `#9575CD` |
|
|
70
|
+
| 4 | `#68B66B` |
|
|
71
|
+
| 5 | `#19ABBE` |
|
|
72
|
+
| 6 | `#A1887F` |
|
|
73
|
+
| 7 | `#64B5F6` |
|
|
74
|
+
|
|
75
|
+
## MUI theme mapping
|
|
76
|
+
|
|
77
|
+
Use these when wiring to MUI theme (e.g. `color="primary"`, `color="text.secondary"`).
|
|
78
|
+
|
|
79
|
+
- **Primary**: purple (main `#506DFF`)
|
|
80
|
+
- **Secondary**: yellow
|
|
81
|
+
- **Text primary**: `gray.gray2`
|
|
82
|
+
- **Text secondary**: `gray.gray4`
|
|
83
|
+
- **Success**: green
|
|
84
|
+
- **Error**: red
|
|
85
|
+
- **Info**: blue
|
|
86
|
+
- **Warning**: orange
|
|
87
|
+
- **Divider**: `gray.gray6`
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Best Practices
|
|
2
|
+
|
|
3
|
+
- **Follow existing code patterns** in the codebase
|
|
4
|
+
- **Use TypeScript/PropTypes** if the project uses them
|
|
5
|
+
- **Handle loading and error states** appropriately
|
|
6
|
+
- **Keep components focused** - single responsibility principle
|
|
7
|
+
- **Use meaningful variable and function names**
|
|
8
|
+
- **Add comments** for complex logic or non-obvious decisions
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Component Organization
|
|
2
|
+
|
|
3
|
+
- **Small sub-components** (less than ~50 lines, simple logic):
|
|
4
|
+
- Define them in the same file, outside the main component
|
|
5
|
+
- Place them above the main component export
|
|
6
|
+
- Example structure:
|
|
7
|
+
```javascript
|
|
8
|
+
const SubComponent = ({ prop1, prop2 }) => {
|
|
9
|
+
// component logic
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const MainComponent = () => {
|
|
13
|
+
// main component logic
|
|
14
|
+
return <SubComponent />;
|
|
15
|
+
};
|
|
16
|
+
```
|
|
17
|
+
- **Large sub-components** (complex logic, reusable, >50 lines):
|
|
18
|
+
- Extract to separate files in the same directory or `components/` subdirectory
|
|
19
|
+
- Reference example: `react-extn/src/AiCopilot/Pages/Chat/components/` or `react-extn/src/AiCopilot/Pages/Tags/components/`
|
|
20
|
+
- Follow the pattern: `ComponentName/index.js` for main component, `ComponentName/SubComponent.js` for sub-components
|
|
21
|
+
- **File naming**: Use PascalCase for component files (e.g., `TagItem.js`, `ModifyTagDialog.js`)
|
|
Binary file
|