Skip to content

Commit

Permalink
add even more interactivity
Browse files Browse the repository at this point in the history
  • Loading branch information
danieleguido committed Jan 14, 2025
1 parent 9b470e0 commit 123fe89
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 56 deletions.
51 changes: 1 addition & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,50 +1 @@
# React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

## Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:

- Configure the top-level `parserOptions` property like this:

```js
export default tseslint.config({
languageOptions: {
// other options...
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
},
})
```

- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
- Optionally add `...tseslint.configs.stylisticTypeChecked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:

```js
// eslint.config.js
import react from 'eslint-plugin-react'

export default tseslint.config({
// Set the react version
settings: { react: { version: '18.3' } },
plugins: {
// Add the react plugin
react,
},
rules: {
// other rules...
// Enable its recommended rules
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
},
})
```
# Map of Research Partners
62 changes: 56 additions & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useStore } from './components/QuickMapbox'
import QuickMapbox from './components/QuickMapbox'
import dataset from './data/dataset.json'
import Tooltip from './components/Tooltip'
import { useEffect, useRef } from 'react'

const Labels = dataset.features.reduce((acc, feature) => {
const { city, country } = feature.properties
Expand All @@ -22,8 +23,12 @@ const SortedLabelsByCountry = Object.entries(Labels).sort(([a], [b]) =>
a.localeCompare(b)
)

const featureListWidth = 250

function App() {
const setSelectedFeature = useStore((state) => state.setSelectedFeature)
const asideRef = useRef<HTMLDivElement>(null)
const currentFeatureId = useRef()
const handleFeaturePointClick = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
properties: any
Expand All @@ -33,12 +38,47 @@ function App() {
setSelectedFeature(properties)
}

// Connect to the store on mount, disconnect on unmount, catch state-changes in a reference
useEffect(
() =>
useStore.subscribe((state) => {
if (!state.selectedFeature) {
return
}
const featureId = state.selectedFeature.properties?.id
console.info('[App] selection changed to:', featureId)

if (!asideRef.current) return
if (currentFeatureId.current) {
// remove class
const currentFeatureElement = asideRef.current.querySelector(
`#aside-feature-${currentFeatureId.current}`
)
if (currentFeatureElement) {
currentFeatureElement.classList.remove('active')
}
}
currentFeatureId.current = featureId
const featureElement = asideRef.current.querySelector(
`#aside-feature-${featureId}`
)
if (!featureElement) return
featureElement.scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center',
})
featureElement.classList.add('active')
}),
[]
)

return (
<div className='App'>
<div className='App__background position-fixed top-0 start-0 w-100 p-3' />
<div
className='App__QuickMapbox position-fixed top-0 start-0'
style={{ right: 200, bottom: 0 }}
style={{ right: featureListWidth, bottom: 0 }}
>
<QuickMapbox
mapboxAccessToken={
Expand All @@ -50,22 +90,32 @@ function App() {
</div>
<div
className='App__tooltip position-fixed top-0 start-0 p-3 d-flex justify-contents-center'
style={{ right: 200 }}
style={{ right: featureListWidth }}
>
<Tooltip className='bg-dark text-white p-3' />
</div>
<aside className='p-3 position-absolute' style={{ width: 200, right: 0 }}>
<aside
ref={asideRef}
className='p-0 position-absolute bg-light'
style={{ width: featureListWidth, right: 0 }}
>
{SortedLabelsByCountry.map(([country, cities]) => (
<div key={country}>
<div className='p-2' key={country}>
<h3 className='position-sticky mb-2 border-dark border-bottom top-0 py-2 bg-light'>
{country}
</h3>
{Object.entries(cities).map(([city, features]) => (
<div key={city}>
<h4 className=' border-dark border-bottom py-2'>{city}</h4>
<h4 className='font-size-inherit border-dark border-bottom py-2'>
{city}
</h4>
<ul className='list-unstyled'>
{features.map((feature) => (
<li key={feature.properties.id}>
<li
key={feature.properties.id}
id={`aside-feature-${feature.properties.id}`}
className='mb-2'
>
<button
className='btn btn-link text-start p-0'
onClick={(e) => handleFeaturePointClick(e, feature)}
Expand Down
21 changes: 21 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,24 @@
z-index: 2;
pointer-events: none;
}

.App li {
padding: 5px;
border-radius: 5px;
}
.App li.active {
background-color: var(--bs-dark);
}

.App li.active button {
color: var(--bs-white);
}

.App li button {
text-decoration: none;
color: var(--bs-dark);
}

.font-size-inherit {
font-size: inherit;
}

0 comments on commit 123fe89

Please sign in to comment.