Focus and Active Row

Connect cell clicks to selectedRowKey and visually highlight the currently selected row.

#selectedRowKey#focus#row-click#active-row
Last reviewed: 2026-08-23
LIVE DEMOFocus and Active Row interactive example
Loading the interactive demo…
GitHub
import { t } from './i18n';
import * as React from 'react';
import { BGrid, BGridColumn, BGridDataItem } from 'beautiful-grid';
import DataGridContainer from '../components/DataGridContainer';
import { useContainerSize } from '../hooks/useContainerSize';

interface KnowledgeArticle {
  articleId: number;
  category: string;
  title: string;
  owner: string;
  status: string;
  updatedAt: string;
}

const articleTitles = [
  t('신규 입사자 계정 발급 절차', 'New Employee Account Issuance Procedure'),
  t('법인카드 비용 정산 가이드', 'Corporate Card Expense Settlement Guide'),
  t('고객 데이터 보안 등급 정책', 'Customer Data Security Level Policy'),
  t('원격 근무 VPN 접속 방법', 'Remote Work VPN Access Method'),
  t('장애 상황 긴급 연락 체계', 'Emergency Contact System for Outages'),
  t('구매 요청 및 승인 프로세스', 'Purchase Request and Approval Process'),
];
const categories = [t('인사', 'HR'), t('재무', 'Finance'), t('보안', 'Security'), t('IT 운영', 'IT Operations'), t('고객지원', 'Customer Support')];
const owners = [t('김서준', 'Seojun Kim'), t('이하린', 'Harin Lee'), t('박도윤', 'Doyun Park'), t('최지우', 'Jiwoo Choi')];

const data: BGridDataItem<KnowledgeArticle>[] = Array.from({ length: 120 }, (_, index) => ({
  values: {
    articleId: index + 1,
    category: categories[index % categories.length],
    title: articleTitles[index % articleTitles.length],
    owner: owners[index % owners.length],
    status: index % 7 === 0 ? t('초안', 'Draft') : index % 4 === 0 ? t('검토 중', 'Under Review') : t('게시', 'Publish'),
    updatedAt: `2026-08-${String((index % 23) + 1).padStart(2, '0')}`,
  },
}));

export default function FocusExample() {
  const [selectedRowKey, setSelectedRowKey] = React.useState<number>();
  const [columns, setColumns] = React.useState<BGridColumn<KnowledgeArticle>[]>([
    { key: 'articleId', label: t('문서번호', 'Document Number'), width: 90, align: 'center' },
    { key: 'category', label: t('분류', 'Category'), width: 100, align: 'center' },
    { key: 'title', label: t('문서 제목', 'Document Title'), width: 320 },
    { key: 'owner', label: t('담당자', 'Assignee'), width: 100, align: 'center' },
    { key: 'status', label: t('게시 상태', 'Publish Status'), width: 100, align: 'center' },
    { key: 'updatedAt', label: t('최종 수정일', 'Last Modified Date'), width: 120, align: 'center', sortDisable: true },
  ]);
  const containerRef = React.useRef<HTMLDivElement>(null);
  const { width, height } = useContainerSize(containerRef);
  const selectedArticle = data.find(item => item.values.articleId === selectedRowKey)?.values;

  return (
    <>
      <div data-testid='selected-article' style={{ marginBottom: 10 }}>
        <strong>선택 문서:</strong> {selectedArticle ? `${selectedArticle.articleId}. ${selectedArticle.title}` : t('없음', 'None')}
      </div>
      <DataGridContainer ref={containerRef}>
        <BGrid<KnowledgeArticle>
          width={width}
          height={height}
          headerHeight={35}
          data={data}
          columns={columns}
          rowKey='articleId'
          selectedRowKey={selectedRowKey}
          onChangeColumns={(_columnIndex, { columns }) => setColumns(columns)}
          onClick={({ item }) => setSelectedRowKey(item.articleId)}
        />
      </DataGridContainer>
    </>
  );
}

1. When and why is it needed?

Use selectedRowKey when a clicked row must remain highlighted, such as when connecting a list to a detail panel. This is a controlled pattern: store the original row’s key in state from onClick, then pass that value back through selectedRowKey.


2. Practical example: highlight a row and connect a detail view

import React, { useState } from 'react';
import { BGrid, type BGridColumn, type BGridDataItem } from 'beautiful-grid';

interface ArticleItem {
  id: number;
  title: string;
  author: string;
  createdAt: string;
}

export default function FocusGrid() {
  const [selectedKey, setSelectedKey] = useState<string | number>(2);

  const [data] = useState<BGridDataItem<ArticleItem>[]>([
    { values: { id: 1, title: 'BeautifulGrid v1.11 release notes', author: 'Admin', createdAt: '2026-08-10' } },
    { values: { id: 2, title: 'Tips for optimizing high-performance virtual scrolling', author: 'Engineering', createdAt: '2026-08-12' } },
    { values: { id: 3, title: 'React 19 compatibility and TypeScript support', author: 'Frontend', createdAt: '2026-08-15' } },
  ]);

  const columns: BGridColumn<ArticleItem>[] = [
    { key: 'id', label: 'No.', width: 70, align: 'center' },
    { key: 'title', label: 'Title', width: 320 },
    { key: 'author', label: 'Author', width: 100, align: 'center' },
    { key: 'createdAt', label: 'Published', width: 120, align: 'center' },
  ];

  return (
    <div>
      <BGrid<ArticleItem>
        width={650}
        height={220}
        columns={columns}
        data={data}
        rowKey="id"
        selectedRowKey={selectedKey} // Unique key of the selected row (applies the active style)
        onClick={({ item }) => {
          setSelectedKey(item.id);
        }}
      />
    </div>
  );
}