| <script lang="ts"> | |
| export type TabId = 'scanner' | 'encounters' | 'pictuary'; | |
| interface Tab { | |
| id: TabId; | |
| label: string; | |
| icon: string; | |
| } | |
| interface Props { | |
| activeTab: TabId; | |
| onTabChange: (tab: TabId) => void; | |
| } | |
| let { activeTab, onTabChange }: Props = $props(); | |
| const tabs: Tab[] = [ | |
| { id: 'scanner', label: 'Scanner', icon: 'https://huggingface.co/spaces/Fraser/piclets/resolve/main/assets/snap_logo.png' }, | |
| { id: 'encounters', label: 'Encounters', icon: 'https://huggingface.co/spaces/Fraser/piclets/resolve/main/assets/encounters_logo.png' }, | |
| { id: 'pictuary', label: 'Pictuary', icon: 'https://huggingface.co/spaces/Fraser/piclets/resolve/main/assets/pictuary_logo.png' } | |
| ]; | |
| function handleTabClick(tabId: TabId) { | |
| onTabChange(tabId); | |
| } | |
| </script> | |
| <nav class="tab-bar"> | |
| <div class="tab-bar-inner"> | |
| {#each tabs as tab} | |
| <button | |
| class="tab-item" | |
| class:active={activeTab === tab.id} | |
| onclick={() => handleTabClick(tab.id)} | |
| > | |
| <div class="icon-wrapper"> | |
| <img | |
| src={tab.icon} | |
| alt={tab.label} | |
| class="tab-icon" | |
| /> | |
| </div> | |
| </button> | |
| {/each} | |
| </div> | |
| </nav> | |
| <style> | |
| .tab-bar { | |
| position: fixed; | |
| bottom: 0; | |
| left: 0; | |
| right: 0; | |
| background: #f5f5f5; | |
| border-top: 1px solid #e0e0e0; | |
| z-index: 1000; | |
| padding-bottom: env(safe-area-inset-bottom, 0); | |
| } | |
| .tab-bar-inner { | |
| display: flex; | |
| justify-content: space-around; | |
| align-items: center; | |
| height: 70px; | |
| } | |
| .tab-item { | |
| flex: 1; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| background: none; | |
| border: none; | |
| padding: 6px; | |
| cursor: pointer; | |
| -webkit-tap-highlight-color: transparent; | |
| } | |
| .icon-wrapper { | |
| position: relative; | |
| width: 48px; | |
| height: 48px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| border-radius: 10px; | |
| } | |
| .tab-item.active .icon-wrapper { | |
| background: rgb(190, 210, 238); | |
| } | |
| .tab-icon { | |
| width: 32px; | |
| height: 32px; | |
| object-fit: contain; | |
| opacity: 0.4; | |
| } | |
| .tab-item.active .tab-icon { | |
| filter: brightness(0) saturate(100%) invert(27%) sepia(51%) saturate(2878%) hue-rotate(192deg) brightness(104%) contrast(97%); | |
| opacity: 1; | |
| } | |
| </style> |