> ## Documentation Index
> Fetch the complete documentation index at: https://learn.nextedy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Customize the Top Panel

> Add custom buttons, filters, document metadata, and JavaScript integrations to the area above the Nextedy RISKSHEET grid using a Velocity template.

export const LastReviewed = ({date}) => {
  if (!date) return null;
  const formatted = new Date(`${date}T00:00:00Z`).toLocaleDateString("en-US", {
    year: "numeric",
    month: "long",
    day: "numeric",
    timeZone: "UTC"
  });
  return <p className="mt-10 text-sm text-gray-400 dark:text-zinc-500 not-prose">
      Last reviewed on {formatted}
    </p>;
};

<Info title="Also known as the attributes panel">
  Referred to as the **Risksheet attributes panel** in the Nextedy Support Portal. *Aliases: attributes panel, risksheet attributes panel.*
</Info>

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/1.png?fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=85046cf089eea5e66bd297b8a590be73" alt="The attributes panel in the Risksheet header showing the document's custom fields above the grid" width="2514" height="300" data-path="risksheet/images/48001172963/1.png" />
</Frame>

## Why a Separate Top Panel? The Two-File Pattern

Risksheet splits configuration across two files:

| File                                                 | Role                                                                          |
| ---------------------------------------------------- | ----------------------------------------------------------------------------- |
| **Sheet configuration** (columns, levels, formulas)  | Declarative — WHAT to show. Auditable structure, easy to diff.                |
| **Top panel configuration** (`risksheetTopPanel.vm`) | Imperative — HOW to compute and render. Velocity + JavaScript, code-reviewed. |

This separation matters for regulated industries: when a risk matrix changes, only the top panel changes, so the declarative sheet configuration stays untouched and the change-control scope stays small. Tooling can validate the sheet configuration without parsing JavaScript, and the same sheet structure can pair with different calculation strategies by swapping the top panel.

For regulated environments, keep formula wrappers in the sheet configuration thin (for example, `initialRE: "(info) => { return getInitialRE(info); }"`) and put the real logic in `risksheetTopPanel.vm`.

## Prerequisites

* Administrator privileges for the Polarion project
* Familiarity with Velocity template syntax
* A Risksheet document or template where you can attach files

## Step 1: Create the Top Panel Template

1. Create a new file named `risksheetTopPanel.vm`
2. Write your Velocity template content (see examples below)
3. Attach the file to your Risksheet document or its template document

The recommended way to edit the top panel is directly from the Risksheet interface, via **Menu > Configuration > Edit Top Panel Configuration**:

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/2.png?fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=4119010d9edfd839261cd325f95373b6" alt="Menu > Configuration > Edit Top Panel Configuration in the Risksheet interface" data-og-width="920" width="920" data-og-height="1006" height="1006" data-path="risksheet/images/48001172963/2.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/2.png?w=280&fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=96e36bc2ef03fadb263fb2f35808a9f6 280w, https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/2.png?w=560&fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=de25e3bc372b991000deb6c960504943 560w, https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/2.png?w=840&fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=5e95c07de17a001963c279301cac0f6b 840w, https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/2.png?w=1100&fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=506ccf61c025cead3ac06c5a6d5b1ce0 1100w, https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/2.png?w=1650&fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=65c176a5c649dea89a3005d19e7e02fc 1650w, https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/2.png?w=2500&fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=282d1e1ab993a22e5e58113e1f41302f 2500w" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/3.png?fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=dc6747e560a9c8a0c1d247fee977fde3" alt="The built-in top-panel configuration editor; save and reload to apply the changes" width="1618" height="1052" data-path="risksheet/images/48001172963/3.png" />
</Frame>

Alternatively, you can access the top-panel file from the document's attachments. Open **Menu > Document > Open Live Document** and find the Attachments section:

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/4.png?fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=1999f609207f62cabee9978d2770d873" alt="Menu > Document > Open Live Document leading to the Attachments section that holds the top-panel file" data-og-width="974" width="974" data-og-height="420" height="420" data-path="risksheet/images/48001172963/4.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/4.png?w=280&fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=184e91d94a8219be7ef023e5b6509ba5 280w, https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/4.png?w=560&fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=93b60db013ebe6b01f130a15ac53200d 560w, https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/4.png?w=840&fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=7c6af38f65bf164c2409dd2a99306db3 840w, https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/4.png?w=1100&fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=71b3ced969d63c542230d98884870dab 1100w, https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/4.png?w=1650&fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=dca305f67b907297060b916494a5cb01 1650w, https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/4.png?w=2500&fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=09783dda5ef27f0fc394d253a959ce79 2500w" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/AIn5YJnEEQyTvSQd/risksheet/images/48001172963/5.png?fit=max&auto=format&n=AIn5YJnEEQyTvSQd&q=85&s=24172ec6458922e33f38f7354f4d856c" alt="Downloading, editing, and re-uploading the top-panel file from the document attachments" width="734" height="152" data-path="risksheet/images/48001172963/5.png" />
</Frame>

Risksheet renders the Velocity template as HTML and inserts it above the grid. The template has access to these Velocity context variables:

| Variable           | Description                                       |
| ------------------ | ------------------------------------------------- |
| `$document`        | The current Polarion document object              |
| `$doc`             | Alias for the document with access to the old API |
| `$transaction`     | The current Polarion transaction                  |
| `$securityService` | Polarion security service (current user, roles)   |
| `$velocityTools`   | Standard Velocity tools                           |

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/yWl5nA2D0IzEnZC1/risksheet/diagrams/guides/customization/top-panel/diagram-1.svg?fit=max&auto=format&n=yWl5nA2D0IzEnZC1&q=85&s=db41ff71fed6b399d51bd086295ea8e3" alt="diagram" style={{ maxWidth: "500px", width: "100%" }} width="500" height="220" data-path="risksheet/diagrams/guides/customization/top-panel/diagram-1.svg" />
</Frame>

## Step 2: Display Document Custom Fields

Show document-level custom fields in the top panel using Velocity expressions:

```velocity theme={null}
<div class="risksheet-panel-info">
  <strong>Product Family:</strong> $document.customFields.productFamily
  <strong>Status:</strong> $document.customFields.approvalStatus
</div>
```

For custom fields that require the old API:

```velocity theme={null}
#set($productFamily = $doc.getOldApi().getValue("productFamily"))
<div class="risksheet-panel-info">
  <strong>Product Family:</strong> $productFamily
</div>
```

<Note title="Read-only access">
  The top panel can display document custom fields but cannot modify them directly. Custom fields must be updated through Polarion's standard document editing interface.
</Note>

## Step 3: Bridge Server-Side Data to Client-Side Formulas

Use the top panel to extract server-side data and make it available to client-side JavaScript. This is essential for formulas and query factories that need document-level context:

```velocity theme={null}
<script>
  #set($productFamily = $doc.getOldApi().getValue("productFamily"))
  window.risksheetContext = {
    productFamily: "$productFamily"
  };
</script>
```

Then reference the value in your sheet configuration formula:

```yaml theme={null}
formulas:
  filterByFamily: "function(info) { return window.risksheetContext.productFamily; }"
```

This is the canonical externalization pattern: the sheet configuration declares a named formula; the actual logic lives in the top panel script block. Only the top panel changes when the calculation evolves.

## Step 4: Filter Item Suggestions Using Top Panel Data

Combine the top panel Velocity script with a `queryFactory` function to dynamically filter linked items based on document-level custom field values:

```velocity theme={null}
<script>
  #set($productFamily = $doc.getOldApi().getValue("productFamily"))

  // Register a custom query factory
  window.risksheet = window.risksheet || {};
  window.risksheet.queryFactories = window.risksheet.queryFactories || {};
  window.risksheet.queryFactories.filterByProductFamily = function(query) {
    return query + ' AND customField.productFamily:"$productFamily"';
  };
</script>
```

Then reference this query factory from a column in your sheet configuration:

```yaml theme={null}
columns:
  - bindings: linkedWorkItems
    header: Requirements
    type: itemLink
    typeProperties:
      queryFactory: filterByProductFamily
```

Note `bindings` (plural) — this is the correct property name for the Polarion field mapping on a column.

<Warning title="queryFactory must live inside typeProperties">
  `queryFactory` only takes effect inside the column's `typeProperties` block (alongside `linkRole`/`linkTypes`). A `queryFactory` placed as a top-level column property is silently ignored — the engine neither keeps it nor moves it, so the filter never applies.
</Warning>

<Tip title="Data flow pattern">
  The top panel Velocity template runs on the server side, extracting document field values. It outputs JavaScript variables into the page. Client-side formulas and query factories then read those variables at runtime. This server-to-client bridge is the standard pattern for document-aware filtering.
</Tip>

## Maximize and Restore the Grid

The top panel includes a built-in toggle to maximize the grid viewing area:

* Click the **maximize** button to hide the top panel and expand the grid to full height
* Click the **restore** button to show the top panel again

This toggle is always available and requires no configuration.

## Error Handling

If the Velocity template contains errors, Risksheet renders a red message box in the top panel area. Common errors include:

* **Syntax errors in Velocity** -- missing `#end` directives or undefined variables
* **Missing custom field** -- referencing a document custom field that does not exist returns `null`
* **JavaScript errors** -- check the browser console for client-side script issues

<Warning title="Template inheritance">
  The `risksheetTopPanel.vm` file follows the same inheritance rules as the sheet configuration. Risksheet first checks the current document, then searches the document's template hierarchy. If you use [Override Template Configuration](/risksheet/guides/configuration/document-config-override), you can have a document-specific top panel that differs from the template.
</Warning>

## Step 5: Verify the Top Panel

After attaching or updating your `risksheetTopPanel.vm`:

1. Open the Risksheet document
2. Verify the top panel area displays your custom content above the grid
3. Check that document custom fields render their current values
4. If using JavaScript bridging, open the browser console and verify `window.risksheetContext` (or your variable name) contains the expected data

You should now see your custom top panel content displayed above the Risksheet grid.

## See Also

* [Customize the Context Menu](/risksheet/guides/customization/context-menu) -- add custom right-click actions
* [Create Custom Renderers](/risksheet/guides/customization/custom-renderers) -- specialized cell display logic
* [Use Query Factory](/risksheet/guides/advanced/query-factory) -- dynamic query generation for autocomplete
* [Configure Queries](/risksheet/guides/advanced/query-configuration) -- item filtering configuration

<LastReviewed date="2026-06-24" />
