Photo by Yannis Papanastasopoulos on Unsplash

React Tips

React List Bileşeninde KeyDown/KeyUp ile Elemanlar üzerinde Gezinebilme

⌘ K ile Digital Garden üzerinde Sample Listesini açmak üzerine bir örnek geliştirmiştim. Bu blog önceki yazının devamı niteliğindedir.

3 min readNov 30, 2023

--

Bir önceki yazıda ⌘ K ile Sample Listesi açmayı nasıl gerçekleştirdiğimizi anlatmıştık. Geçmiş yazıda eksik kalan ve ileride iyileştireceğim 2 özellikten bahsetmiştim.

  • Key Up, Key Down düğmeleri ile listede gezme
  • CMD+ K kısayolunun tüm sayfalardan kullanılabilir hale getirebiliriz.

Öncelikle bu geliştirmeleri https://onurdayibasi.dev/ sitesini ziyaret ederke görebilirsiniz.

https://onurdayibasi.dev/

1. Key Up, Key Down düğmeleri ile listede gezme

Açılan ekran üzerinde KeyDown/Up sonrasında list elemanları üzerinde gezme işlemi.

Bunun için Liste üzerinde gezindiğimizde indeksi tutacak bir state ihtiyacımız bulunuyor

const [selectedItem, setSelectedItem] = React.useState(null);

Birde Key eventlerini dinleyecek bunları anlamlandıracak bir fonksiyona ihtiyacımız var. handleKeyDown içerisinde ArrowUp/Down bakarak selectedIndeksi değiştiriyoruz

  const handleKeyDown = (e) => {
const data = searchMatches;
if (e.key === 'Enter') {
history.push(data[selectedItem].path);
} else if (e.key === 'ArrowUp') {
setSelectedItem((prev) => (prev === null ? 0 : Math.max(prev - 1, 0)));
} else if (e.key === 'ArrowDown') {
setSelectedItem((prev) => (prev === null ? 0 : Math.min(prev + 1, data.length - 1)));
}
};

Enter düğmesi ile react-router üzerinden const history = useHistory(); üzerinden istediğimiz navigation gidebiliriz.

searchMatches ise Search alanında yaptığımız sorgular sonucunda kalan sample bilgilerini tutan array’ dir.

  React.useEffect(() => {
setSelectedItem(null);
const matches = Object.values(props.routes)
.sort((a, b) => {
if (a.publishDate < b.publishDate) {
return -1;
}
if (a.publishDate > b.publishDate) {
return 1;
}
return 0;
})
.filter((el) => !el.kMap)
.filter((el) => {
return (
el.title.toLowerCase().includes(searchText?.toLowerCase()) ||
getKnowledgeData(el.path)?.knowledgeTitle.toLowerCase().includes(searchText?.toLowerCase())
);
});
setSearchMatches(matches);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchText]);

Şimdi bu handleKeyDown bir bileşene takmamız lazım. Bu işlemleri SeachInput üzerinden yapacağız çünkü Drawer açıldığında otomatik bu Input içerisine odaklanıyor. Liste tamamen bunun üzerinden kontrol ediliyor.

    return (
<Space direction="vertical">
<Input.Search
style={{width: 300}}
placeholder="Search Samples"
onKeyDown={handleKeyDown}
onChange={(e) => setSearchText(e.target.value)}
ref={searchInputRef}
></Input.Search>
<List size="small" dataSource={NavigationListsJSX} renderItem={renderItem} />
</Space>
);

Highlighting ve Scrolling konusunu Liste üzerinde nasıl gerçekleştireceğiz. renderItem fonksiyonunu inceleyelim.

  const renderItem = (item, index) => {
return (
<List.Item
id={`sampe-list-item${index}`}
key={index}
style={{
display: 'flex',
justifyContent: 'space-between',
backgroundColor: index === selectedItem ? '#e6e6fa' : 'transparent',
}}
>
<Link to={item.path}>
<span style={{cursor: 'pointer'}}>{item.title}</span>
</Link>
{item.knowledgeData && (
<Link to={item.knowledgeData.knowledgePath}>
<Typography.Text ellipsis={true} style={{fontSize: '10px', width: '100'}} type="success">
{item.knowledgeData.knowledgeTitle}
</Typography.Text>
</Link>
)}
</List.Item>
);
};

öncelikle highlight için selectedItem ile indeks eşit olduğunda background rengini farklılaştırarak istediğimiz sonucu alabiliriz.

backgroundColor: index === selectedItem ? '#e6e6fa' : 'transparent',

scroll için element.scrollIntoView fonksiyonunu kullanacağız. Öncelikle list itemlara bir id atamamız gerekiyor

<List.Item
id={`sampe-list-item${index}`}

sonraında selectedItem değişince ilgili elemente odaklayarak scroll işlemini başlatıyoruz.

  React.useEffect(() => {
if (selectedItem !== null) {
const element = document.getElementById(`sampe-list-item${selectedItem}`);
if (element) {
element.scrollIntoView({behavior: 'instant', block: 'nearest', inline: 'nearest'});
}
}
}, [selectedItem]);

2. CMD+ K kısayolunun tüm sayfalardan kullanılabilir hale getirebiliriz

Bunun için Drawer, ve SampleList ayrı ayrı bileşenler haline getirdim.

Drawer

export const SampleLayoutDrawer = (props) => {
return (
<Drawer
afterOpenChange={props.afterOpenChange}
title={props.title}
placement="right"
onClose={props.onClose}
open={props.open}
>
{props.children}
</Drawer>
);
};

Ve tüm Sample örneklerin altyapısında kullandığım DemoManager içerisine aşağıdaki fonksiyonu ekledim.

     {this.renderDrawer()}

Bu fonksiyon SampleLayoutDrawer kullanarak içerisine SampleList render ediyor

  renderDrawer = () => {
const {drawerOpenedCount, drawerOpened} = this.state;

return (
<SampleLayoutDrawer
afterOpenChange={() => {
this.setState({drawerOpenedCount: drawerOpenedCount + 1});
}}
title={'Sample List'}
placement="right"
onClose={this.onDrawerClose}
open={drawerOpened}
>
<SampleList openedId={drawerOpenedCount} routes={routes} knowledgeSampleMap={knowledgeSampleMap} />
</SampleLayoutDrawer>
);
};

bu sayede herhangi bir Sample içerisinden istediğim örneğe kısayol üzerinden rahatlıkla ulaşabiliyorum.

Okumaya Devam Et 😃

Bu yazının devamı veya yazı grubundaki diğer yazılara erişmek için bu linke tıklayabilirsiniz.

--

--