Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement OnyxDataGridRenderer support component #1851

Closed
16 tasks done
JoCa96 opened this issue Sep 11, 2024 · 2 comments
Closed
16 tasks done

Implement OnyxDataGridRenderer support component #1851

JoCa96 opened this issue Sep 11, 2024 · 2 comments
Assignees
Labels
dev Requires technical expertise
Milestone

Comments

@JoCa96
Copy link
Collaborator

JoCa96 commented Sep 11, 2024

Why?

According to our #1660 we want to abstract the rendering of the OnyxDataGrid. We implement this TableRenderLayer via the OnyxDataGridRenderer support component.

It encompasses a minimal API that renders an HTML compliant table with only permitted content elements:

Permitted content

In this order:

  • an optional element,
  • zero or more elements,
  • an optional element,
  • either one of the following:
    • zero or more elements
    • one or more elements
  • an optional element

The TableRenderLayer must be stateless.
Its main purpose is to create an HTML compliant table structure.
The table should be rendered according to the following rules:

  • columns describes the horizontal layout of the table, every entry MUST result in a column and <th>element
  • rows describe the vertical layout of the table, every entry MUST result in a row and a <tr> element
  • so there should not be any "unused" entries in either column or row
  • extensions should only follow table concepts that are supported/specified by the HTML spec
  • the entry keys of a row must match the specified columns or colgroups
  • the content of the table data cells (<td>...</td>) in a row can be any content

Design

Figma

Acceptance criteria

  • The OnyxDataGridRenderer is implemented:
    • Does not have internal state
    • Renders and supports only compliant HTML
    • Uses and offers BEM classes
    • Is styled according to the Figma design
  • [Can render:
    • table header
    • table rows
    • combined rows
    • column categories

Definition of Done

  • The following component requirements are implemented:
    • density
  • covered by tests
    • functional tests (Playwright or unit test)
    • visual tests (Playwright screenshots)
  • follow-up tickets were created if necessary
  • updated version + documentation is deployed
  • Storybook can show the feature
  • Namings are aligned with Figma

Approval

Implementation details

The following is the code used by the PoC of #1660.
@JoCa96 - I would consider making the id key dynamic. Column and row grouping, as well as styling was not yet considered.

import type { FunctionalComponent, HTMLAttributes, TdHTMLAttributes } from "vue";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AnyKey = keyof any;

export type TableEntry = {
  id: string | number;
  [key: AnyKey]: unknown;
};

export type Metadata = Record<string, unknown>;

export type CellRenderFunc<
  TEntry extends TableEntry,
  TMetadata extends Metadata,
> = FunctionalComponent<RenderCellProps<TEntry, TMetadata>>;

/**
 * Props of the TableRenderLayer
 */
export type RendererProps<TEntry extends TableEntry, TMetadata extends Metadata> = {
  theadProps?: HTMLAttributes;
  tbodyProps?: HTMLAttributes;
  columns: RenderHeader<TEntry>[];
  rows: RenderRow<TEntry, TMetadata>[];
};

export type RenderHeader<
  TEntry extends TableEntry,
  TKey extends keyof TEntry = keyof TEntry,
  TProps extends object = object,
> = {
  /**
   * Key of the column - usually a key of the tabledata.
   * But can also be used for custom columns.
   */
  key: TKey;
  /**
   * Attributes and data that is provided to the component using `v-bind`.
   */
  headerProps: HTMLAttributes & TProps;
  /**
   * The component that renders the header content.
   */
  header: FunctionalComponent<TProps>;
};

export type RenderRow<TEntry extends TableEntry, TMetadata extends Metadata> = {
  /**
   * Unique id of the row.
   */
  id: TableEntry["id"];
  trProps?: HTMLAttributes;
  cells: Record<keyof TEntry, RenderCell<TEntry, TMetadata> | undefined>;
};

export type RenderCell<TEntry extends TableEntry, TMetadata extends Metadata> = {
  props: RenderCellProps<TEntry, TMetadata>;
  tdProps?: TdHTMLAttributes;
  /**
   * The component that renders the actual cell content.
   */
  is: CellRenderFunc<TEntry, TMetadata>;
};

export type RenderCellProps<TEntry extends TableEntry, TMetadata extends Metadata> = {
  /**
   * Complete row data
   */
  row: TEntry;
  /**
   * Data that is provided to the component via the `metadata` prop
   */
  metadata?: TMetadata;
  /**
   * table data that is provided to the component via the `modelValue` prop
   */
  modelValue: TEntry[keyof TEntry];
};

Basic structure:

<template>
  <table>
    <thead v-bind="props.theadProps">
      <tr>
        <th v-for="col in props.columns" :key="col.key">
          <component :is="col.header" v-bind="col.headerProps" />
        </th>
      </tr>
    </thead>
    <tbody v-bind="props.tbodyProps">
      <tr v-for="row in props.rows" :key="row.id" v-bind="row.trProps">
        <td v-for="col in props.columns" :key="col.key" v-bind="row.cells[col.key].tdProps">
          <component :is="row.cells[col.key].is" v-bind="row.cells[col.key].props" />
        </td>
      </tr>
    </tbody>
  </table>
</template>

Applicable ARIA Pattern

@JoCa96 JoCa96 added this to the Tables milestone Sep 11, 2024
@JoCa96 JoCa96 self-assigned this Sep 11, 2024
@JoCa96 JoCa96 added dev Requires technical expertise 0-refinement All issues that can or need to be estimated in our next refinement labels Sep 11, 2024
@mj-hof mj-hof removed the 0-refinement All issues that can or need to be estimated in our next refinement label Sep 11, 2024
@larsrickert larsrickert self-assigned this Sep 13, 2024
@larsrickert
Copy link
Collaborator

@JoCa96 Vacation handover:

larsrickert added a commit that referenced this issue Oct 1, 2024
Relates to #1851

Implement basic `OnyxDataGridRenderer` component

---------

Co-authored-by: Maja Zarkova <[email protected]>
Co-authored-by: Jonathan Carle <[email protected]>
@jannick-ux
Copy link
Contributor

@larsrickert please set "striped" and "vertical border" to true as default for the data grid. Rest looks amazing :D

larsrickert added a commit that referenced this issue Oct 8, 2024
…y default (#1905)

Relates to
#1851 (comment)

As requested from Jannick, changed the default value for the striped and
withVerticalBorders property to `true`.
JoCa96 pushed a commit that referenced this issue Oct 9, 2024
Relates to #1851

Implement Playwright screenshot tests for the OnyxDataGridRenderer.

## Checklist

- [x] If a new component is added, at least one [Playwright screenshot
test](https://github.com/SchwarzIT/onyx/actions/workflows/playwright-screenshots.yml)
is added

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dev Requires technical expertise
Projects
Status: Done
Development

No branches or pull requests

4 participants