diff --git a/docs/snippets/ClientShowcase.jsx b/docs/snippets/ClientShowcase.jsx index 8ccdf56..753ccae 100644 --- a/docs/snippets/ClientShowcase.jsx +++ b/docs/snippets/ClientShowcase.jsx @@ -1,9 +1,27 @@ {/* Client showcase component. 2-column grid cards with logo on top, links stacked below description. + Defaults to shuffled order for fairness; toggle to switch to alphabetical. */} export const ClientShowcase = ({clients}) => { - const sorted = clients.slice().sort((a, b) => a.name.localeCompare(b.name)); + const shuffle = (arr) => { + const copy = arr.slice(); + for (let i = copy.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [copy[i], copy[j]] = [copy[j], copy[i]]; + } + return copy; + }; + + const sort = (clients) => clients.toSorted((a, b) => a.name.localeCompare(b.name)); + + const [state, dispatch] = React.useReducer((state, action) => { + switch (action) { + case "shuffle": return { mode: "shuffle", clients: shuffle(clients) }; + case "alpha": return { mode: "alpha", clients: sort(clients) }; + default: return state; + } + }, { mode: "shuffle", clients: shuffle(clients) }); const Logo = ({ client }) => ( @@ -12,31 +30,53 @@ export const ClientShowcase = ({clients}) => { ); + const ToggleButton = ({ active, onClick, icon, title }) => ( + + ); + return ( -
- {sorted.map(client => ( -
-
- -
-
{client.name}
-

{client.description}

- {(client.instructionsUrl || client.sourceCodeUrl) && ( -
- {client.instructionsUrl && ( - - Setup instructions - - )} - {client.sourceCodeUrl && ( - - Source code - - )} -
- )} +
+
+
+ dispatch("shuffle")} icon="shuffle" title="Shuffle" /> + dispatch("alpha")} icon="arrow-down-a-z" title="Alphabetical" />
- ))} +
+
+ {state.clients.map(client => ( +
+
+ +
+ +

{client.description}

+ {(client.instructionsUrl || client.sourceCodeUrl) && ( +
+ {client.instructionsUrl && ( + + Setup instructions + + )} + {client.sourceCodeUrl && ( + + Source code + + )} +
+ )} +
+ ))} +
); };