Skip to content

Commit fd8e4bc

Browse files
authored
Merge pull request BruceDevices#1721 from emericklaw/compatible-devices
Updated compatability table with correct data and added detailed view
2 parents 765c9ed + 4be0bfd commit fd8e4bc

File tree

2 files changed

+305
-101
lines changed

2 files changed

+305
-101
lines changed
Lines changed: 121 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<script lang="ts">
22
import type { DeviceCompatibility, FeatureRow } from '$lib/types/device';
33
import devicesData from '$lib/data/devices.json';
4+
import { onMount } from 'svelte';
5+
import { fade } from 'svelte/transition';
46
57
const compatibilityData: DeviceCompatibility[] = devicesData;
68
@@ -9,38 +11,117 @@
911
if (compatibilityData.length > 0) {
1012
features = Object.keys(compatibilityData[0]).filter((k) => k !== 'device') as (keyof FeatureRow)[];
1113
}
14+
15+
let scrollContainer: HTMLElement;
16+
let showGradient = false;
17+
18+
function toggleDetailedView() {
19+
const detailedRows = document.querySelectorAll('.detailed');
20+
detailedRows.forEach((row) => {
21+
row.classList.toggle('hidden');
22+
});
23+
document.getElementById('toggleDetailedView')!.textContent = detailedRows[0].classList.contains('hidden')
24+
? 'Show Detailed View'
25+
: 'Hide Detailed View';
26+
27+
// Recheck gradient visibility after toggling detailed view
28+
setTimeout(checkGradientVisibility, 100);
29+
}
30+
31+
function checkGradientVisibility() {
32+
if (!scrollContainer) return;
33+
34+
const isScrollable = scrollContainer.scrollWidth > scrollContainer.clientWidth;
35+
const isScrolledToEnd = scrollContainer.scrollLeft + scrollContainer.clientWidth >= scrollContainer.scrollWidth - 1;
36+
37+
showGradient = isScrollable && !isScrolledToEnd;
38+
}
39+
40+
function handleScroll() {
41+
checkGradientVisibility();
42+
}
43+
44+
onMount(() => {
45+
checkGradientVisibility();
46+
47+
// Also check on window resize
48+
const handleResize = () => checkGradientVisibility();
49+
window.addEventListener('resize', handleResize);
50+
51+
return () => {
52+
window.removeEventListener('resize', handleResize);
53+
};
54+
});
1255
</script>
1356

1457
<div class="container">
1558
<div class="mx-auto mt-10 w-[90%] text-center">
1659
<h1 class="mb-5 text-3xl font-bold text-white">Compatible Devices</h1>
17-
<div class="w-full overflow-x-auto whitespace-nowrap">
18-
<table class="w-full border-collapse rounded-lg bg-neutral-900">
19-
<thead>
20-
<tr>
21-
<th class="px-4 py-3 text-center text-base text-white">Device</th>
22-
{#each features as feat}
23-
<th class="px-4 py-3 text-center text-base text-white">{feat.replace('_', ' ')}</th>
24-
{/each}
25-
</tr>
26-
</thead>
27-
<tbody>
28-
{#each compatibilityData as row}
29-
<tr class="even:bg-neutral-800 hover:bg-neutral-700">
30-
<td class="border-b border-neutral-800 px-4 py-3 text-center text-base text-white">{row.device}</td>
31-
{#each features as key}
32-
<td class={row[key] === true ? 'success' : row[key] === false ? 'fail' : ''}>
33-
{#if key === 'Speaker' && typeof row[key] === 'string'}
34-
{row[key]}
35-
{:else}
36-
{row[key] === true ? '' : row[key] === false ? '' : ''}
37-
{/if}
38-
</td>
60+
<h2 class="mb-5 text-lg text-white">
61+
This table shows the compatibility of various devices with Bruce's features. Click the button to toggle detailed view for more information.
62+
</h2>
63+
<button
64+
id="toggleDetailedView"
65+
class="mb-5 rounded bg-[#9B51E0] px-4 py-2 font-semibold text-white hover:bg-[#8033C7]"
66+
on:click={toggleDetailedView}
67+
>
68+
Show Detailed View
69+
</button>
70+
<div class="table-wrapper relative">
71+
<div class="w-full overflow-x-auto whitespace-nowrap" bind:this={scrollContainer} on:scroll={handleScroll}>
72+
<table class="w-full border-collapse rounded-lg bg-neutral-900">
73+
<thead>
74+
<tr>
75+
<th class="sticky left-0 z-10 bg-neutral-900 px-4 py-3 text-center text-base text-white">Device</th>
76+
{#each features as feat}
77+
<th
78+
class="px-4 py-3 text-center text-base text-white {feat === 'Screen' ||
79+
feat === 'ESP' ||
80+
feat === 'Battery' ||
81+
feat === 'Flash' ||
82+
feat === 'PSRAM'
83+
? 'detailed hidden'
84+
: ''}">{feat.replace('_', ' ')}</th
85+
>
3986
{/each}
4087
</tr>
41-
{/each}
42-
</tbody>
43-
</table>
88+
</thead>
89+
<tbody>
90+
{#each compatibilityData as row, index}
91+
<tr class="group even:bg-neutral-800 hover:bg-neutral-700">
92+
<td
93+
class="sticky left-0 z-10 px-4 py-3 text-center text-base text-white {index % 2 === 0
94+
? 'bg-neutral-900'
95+
: 'bg-neutral-800'} group-hover:bg-neutral-700">{row.device}</td
96+
>
97+
{#each features as key}
98+
<td
99+
title={typeof row[key] === 'string' ? row[key] : ''}
100+
class={key === 'Screen' || key === 'ESP' || key === 'Battery' || key === 'Flash' || key === 'PSRAM' ? 'detailed hidden' : ''}
101+
>
102+
{#if (key === 'Screen' || key === 'ESP' || key === 'Battery' || key === 'Flash' || key === 'PSRAM') && typeof row[key] === 'string'}
103+
{row[key]}
104+
{:else if key === 'NFC' && typeof row[key] === 'string' && row[key] !== 'Module Required'}
105+
106+
{:else if key === 'Mic'}
107+
{typeof row[key] === 'string' ? '' : ''}
108+
{#if typeof row[key] === 'string'}<span class="detailed hidden">{row[key]}</span>{/if}
109+
{:else if key === 'Audio'}
110+
{row[key] === 'Tone' ? '🔈' : typeof row[key] === 'string' ? '🔊' : ''}
111+
{#if typeof row[key] === 'string'}<span class="detailed hidden">{row[key] !== 'Tone' ? 'Full - ' : ''}{row[key]}</span>{/if}
112+
{:else}
113+
{row[key] === true ? '' : row[key] === false ? '' : row[key] === 'Module Required' ? 'ℹ️' : ''}
114+
{/if}
115+
</td>
116+
{/each}
117+
</tr>
118+
{/each}
119+
</tbody>
120+
</table>
121+
</div>
122+
{#if showGradient}
123+
<div class="scroll-gradient" transition:fade={{ duration: 300 }}></div>
124+
{/if}
44125
</div>
45126
<br />
46127
<h2 class="text-lg">
@@ -58,4 +139,19 @@
58139
max-width: 100%;
59140
margin: 0 auto;
60141
}
142+
143+
.table-wrapper {
144+
position: relative;
145+
}
146+
147+
.scroll-gradient {
148+
position: absolute;
149+
top: 0;
150+
right: 0;
151+
bottom: 0;
152+
width: 100px;
153+
background: linear-gradient(to left, rgba(0, 0, 0, 0.9), transparent);
154+
pointer-events: none;
155+
z-index: 5;
156+
}
61157
</style>

0 commit comments

Comments
 (0)