docs(source): add tags example (#131)

* added tags example

* changed page title

* updated github workflows to test new example

* fixed yaml syntax

* fixed yaml syntax

* fixed packagenames in package.json
This commit is contained in:
Anton Tranelis 2025-02-19 14:58:48 +00:00 committed by GitHub
parent e2beb712bf
commit c02efb9a41
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 5890 additions and 45 deletions

View File

@ -41,7 +41,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
app: [examples/1-basic-map, examples/2-static-layers] # Aktualisierte Pfade der Beispiel-Apps
app: [examples/1-basic-map, examples/2-static-layers, examples/3-tags ]
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.1.7

View File

@ -60,6 +60,20 @@ jobs:
run: npm install && npm run lint
working-directory: ./examples/2-static-layers
lint-example-3-tags:
if: needs.files-changed.outputs.lint == 'true'
name: Lint Example 3 - Tags
needs: files-changed
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.1.7
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.0.3
with:
node-version-file: './.tool-versions'
- name: Lint
run: npm install && npm run lint
working-directory: ./examples/3-tags
# unit:
# if: needs.files-changed.outputs.frontend == 'true'
# name: Unit - Frontend

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>Utopia-UI Example 1</title>
</head>
<body>
<div id="root"></div>

View File

@ -1,5 +1,5 @@
{
"name": "tutorial-1-basic-map",
"name": "1-basic-map",
"private": true,
"version": "0.0.0",
"type": "module",

View File

@ -1,62 +1,81 @@
# Example 2: Static Layers
[Example 1](/1-basic-map) shows us how we create a basic map app with [utopia-ui](https://github.com/utopia-os/utopia-ui). Now we add some static layer.
In [Example 1](/1-basic-map), we learned how to create a basic map app using [utopia-ui](https://github.com/utopia-os/utopia-ui). Now, we'll add **static layers** to our map.
First we put some sample data in a new file called `src/sample-data.ts`
### Adding Sample Data
First, we create a new file called `src/sample-data.ts` and define some sample data:
```javascript
export const places = [{
export const places = [
{
"id": 51,
"name": "Stadtgemüse",
"text": "Stadtgemüse Fulda ist eine Gemüsegärtnerei in Maberzell, die es sich zur Aufgabe gemacht hat, die Stadt und seine Bewohner:innen mit regionalem, frischem und natürlich angebautem Gemüse mittels Gemüsekisten zu versorgen. Es gibt also jede Woche, von Frühjahr bis Herbst, angepasst an die Saison eine Kiste mit schmackhaftem und frischem Gemüse für euch, welche ihr direkt vor Ort abholen könnt. \r\n\r\nhttps://stadtgemuese-fulda.de",
"position": { "type": "Point", "coordinates": [9.632435, 50.560342] },
"text": "Stadtgemüse Fulda ist eine Gemüsegärtnerei in Maberzell, die es sich zur Aufgabe gemacht hat, die Stadt und seine Bewohner:innen mit regionalem, frischem und natürlich angebautem Gemüse mittels Gemüsekisten zu versorgen. Es gibt also jede Woche, von Frühjahr bis Herbst, angepasst an die Saison eine Kiste mit schmackhaftem und frischem Gemüse für euch, welche ihr direkt vor Ort abholen könnt.\r\n\r\nhttps://stadtgemuese-fulda.de",
"position": { "type": "Point", "coordinates": [9.632435, 50.560342] }
},
{
"id": 166,
"name": "Weidendom",
"text": "free camping",
"position": { "type": "Point", "coordinates": [9.438793, 50.560112] },
}];
export const events = [
{
"id": 423,
"name": "Hackathon",
"text": "still in progress",
"position": { "type": "Point", "coordinates": [10.5, 51.62] },
"start": "2022-03-25T12:00:00",
"end": "2022-05-12T12:00:00",
}
]
"text": "Free camping",
"position": { "type": "Point", "coordinates": [9.438793, 50.560112] }
}
];
export const events = [
{
"id": 423,
"name": "Hackathon",
"text": "Still in progress",
"position": { "type": "Point", "coordinates": [10.5, 51.62] },
"start": "2022-03-25T12:00:00",
"end": "2022-05-12T12:00:00"
}
];
```
We want to create two Layers. One we want to call *Places* and the other *Events*
### Creating Layers
we import our sample data to the `src/App.tsx`
We want to create **two layers**:
- A **"Places"** layer for locations
- An **"Events"** layer for scheduled activities.
First, we import our sample data into `src/App.tsx`:
```tsx
import { events, places } from "./sample-data"
```
and than we create our two `<Layer>` inside of our `<UtopiaMap>` component
```tsx
<UtopiaMap center={[50.6, 15.5]} zoom={5} height='100dvh' width="100dvw">
<Layer
name='events'
markerIcon='calendar'
markerShape='square'
markerDefaultColor='#700'
data={events} />
<Layer
name='places'
markerIcon='point'
markerShape='circle'
markerDefaultColor='#007'
data={places} />
</UtopiaMap>
import { events, places } from "./sample-data";
```
And we see our map with two layers:
### Adding Layers to `<UtopiaMap>`
Next, we define our `<Layer>` components inside `<UtopiaMap>`:
```tsx
<UtopiaMap center={[50.6, 15.5]} zoom={5} height="100dvh" width="100dvw">
<Layer
name="events"
markerIcon="calendar"
markerShape="square"
markerDefaultColor="#700"
data={events}
/>
<Layer
name="places"
markerIcon="point"
markerShape="circle"
markerDefaultColor="#007"
data={places}
/>
</UtopiaMap>
```
### Running the Application
Finally, we start our development server to see the **map with two layers**:
```shell
npm run dev
```
➡️ In [Example 3](../3-tags/), we'll add **tags** to our map.

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>Utopia-UI Example 2</title>
</head>
<body>
<div id="root"></div>

View File

@ -1,5 +1,5 @@
{
"name": "tutorial-2-static-layer",
"name": "2-static-layer",
"private": true,
"version": "0.0.0",
"type": "module",

24
examples/3-tags/.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

1
examples/3-tags/.nvmrc Normal file
View File

@ -0,0 +1 @@
v18.19.1

76
examples/3-tags/README.md Normal file
View File

@ -0,0 +1,76 @@
# Example 3: Tags
In [Example 2](/2-static-layers), we learned how to add layers with static data to our map.
Now, we'll introduce **tags** to structure our items and bring some color to the map. Tags allow us to categorize items using a simple **hash syntax**, such as `#utopia #map`, in the text field.
With tags, we can **filter the map** by clicking on them or searching for keywords in the search bar.
### Adding Tags to Our Data
To implement tags, we first define them in our `src/sample-data.ts` file:
```javascript
export const tags: Tag[] = [
{
"id": "e19f46a7-77a4-4a50-99a2-a942dce843a3",
"name": "nature",
"color": "#9bc53d"
},
{
"id": "2c2099a6-23ac-4308-b91c-86eefeff3a1d",
"name": "utopia",
"color": "#c3423f"
},
{
"id": "48b2de97-2b9e-432b-b230-7bdc9a5fb6c0",
"name": "map",
"color": "#5bc0eb"
},
{
"id": "c88f52e6-357b-45fb-a171-9c2b1dceeb8e",
"name": "food",
"color": "#6761a8"
},
{
"id": "8928cb92-a3c1-4d83-9495-c2eb4fac0bbe",
"name": "permaculture",
"color": "#44344f"
},
];
```
and we add some hash tags to our sample items.
### Importing the Tags into Our App
Next, we import our sample data into `src/App.tsx`:
```tsx
import { tags } from "./sample-data";
```
### Integrating Tags into `<UtopiaMap>`
We then add the `<Tags>` component inside `<UtopiaMap>` and pass our `tags` from `sample-data.ts`:
```tsx
function App() {
return (
<UtopiaMap center={[50.6, 15.5]} zoom={5} height="100dvh" width="100dvw">
...
<Tags data={tags} />
</UtopiaMap>
);
}
export default App;
```
### Running the Application
Finally, we start our development server to see the **enhanced map** with tags:
```shell
npm run dev
```

View File

@ -0,0 +1,25 @@
import js from '@eslint/js'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import globals from 'globals'
import tseslint from 'typescript-eslint'
export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
},
},
)

View File

@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Utopia-UI Example 3</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

5490
examples/3-tags/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
{
"name": "3-tags",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1",
"utopia-ui": "latest"
},
"devDependencies": {
"@eslint/js": "^9.17.0",
"@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5",
"@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.17.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.16",
"globals": "^15.14.0",
"typescript": "~5.6.2",
"typescript-eslint": "^8.18.2",
"vite": "^6.0.5"
}
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,24 @@
import { UtopiaMap, Layer, Tags } from "utopia-ui"
import { events, places, tags } from "./sample-data"
function App() {
return (
<UtopiaMap center={[50.6, 15.5]} zoom={5} height='100dvh' width="100dvw">
<Layer
name='events'
markerIcon='calendar'
markerShape='square'
markerDefaultColor='#700'
data={events} />
<Layer
name='places'
markerIcon='point'
markerShape='circle'
markerDefaultColor='#007'
data={places} />
<Tags data={tags}/>
</UtopiaMap>
)
}
export default App

View File

@ -0,0 +1,9 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)

View File

@ -0,0 +1,54 @@
import { Tag } from "utopia-ui";
export const places = [{
"id": "062a1176-f7ee-458d-adba-4a0b3b1ce2a0",
"name": "Stadtgemüse",
"text": "Stadtgemüse Fulda ist eine Gemüsegärtnerei in Maberzell, die es sich zur Aufgabe gemacht hat, die Stadt und seine Bewohner:innen mit regionalem, frischem und natürlich angebautem Gemüse mittels Gemüsekisten zu versorgen. Es gibt also jede Woche, von Frühjahr bis Herbst, angepasst an die Saison eine Kiste mit schmackhaftem und frischem Gemüse für euch, welche ihr direkt vor Ort abholen könnt. \r\n\r\nhttps://stadtgemuese-fulda.de #food #permaculture #nature",
"position": { "type": "Point", "coordinates": [9.632435, 50.560342] },
},
{
"id": "144e379c-b719-4334-9f0e-de277d3b6d0f",
"name": "Weidendom",
"text": "free camping #nature",
"position": { "type": "Point", "coordinates": [9.438793, 50.560112] },
}];
export const events = [
{
"id": "efe00aaa-8b14-47b5-a032-3e0560980c1e",
"name": "Hackathon",
"text": "still in progress #utopia #map",
"position": { "type": "Point", "coordinates": [10.5, 51.62] },
"start": "2022-03-25T12:00:00",
"end": "2022-05-12T12:00:00",
}
]
export const tags : Tag[]= [
{
"id": "e19f46a7-77a4-4a50-99a2-a942dce843a3",
"name": "nature",
"color": "#9bc53d"
},
{
"id": "2c2099a6-23ac-4308-b91c-86eefeff3a1d",
"name": "utopia",
"color": "#c3423f"
},
{
"id": "48b2de97-2b9e-432b-b230-7bdc9a5fb6c0",
"name": "map",
"color": "#5bc0eb"
},
{
"id": "c88f52e6-357b-45fb-a171-9c2b1dceeb8e",
"name": "food",
"color": "#6761a8"
},
{
"id": "8928cb92-a3c1-4d83-9495-c2eb4fac0bbe",
"name": "permaculture",
"color": "#44344f"
},
]

1
examples/3-tags/src/vite-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@ -0,0 +1,26 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src"]
}

View File

@ -0,0 +1,7 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}

View File

@ -0,0 +1,24 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
}

View File

@ -0,0 +1,7 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
})