UI- en UX -doelwitte
My hoofdoel met 'n oorsigbladsy wat alle kategorieë vir gepubliseerde plasings toon, was om die vindbaarheid van die kategorieë wat werklik beskikbaar is, te verhoog. Ek het hierdie verandering ook gesien as 'n geleentheid om die visuele skoonheid van die bladsy te verbeter, sowel as om die UX in lyn te bring met die ander bladsye op hierdie progressiewe webprogram.
Die volgende skermkiekie wys hoe die bladsy gelyk het voor die herontwerp.
Wat moes verander
Die ou implementering het twee groot probleme gehad. Eerstens was die uitleg eintlik ongeldig, aangesien kategorieë met minder as 5 elemente die beskikbare voorblad-afbeeldings na voorskou afgeskaal het om by die hele breedte te pas. Tweedens was daar geen primêre aksiebalk bo -aan die bladsy nie - daar moet beslis een weergegee word, aangesien dit die belangrikste navigasie -elemente aan die gebruiker bied.
Verder word dit duidelik dat die oorsigbladsy vir kategorieë nie werklik 'n goeie taak was om dit sigbaar te maak nie. In plaas daarvan het die gebruiker hoofsaaklik voorbladbeelde gesien vir plasings wat met elke kategorie verband hou. Slegs as u 'n tweede keer kyk, word die ry met 'n ikoon sowel as die titel van elke kategorie herken. Behalwe dat dit esteties nie aangenaam was nie, was hierdie UI eenvoudig sleg ontwerp.
Foute regstel
Aangesien dit my persoonlike webprogram is, was ek ook die een wat dinge aanvanklik op die kategorie -oorsigbladsy deurmekaar gemaak het. Sonder meer verskonings, het ek dus gaan sit om die hele bladsy te herwerk.
Die nuwe weergawe toon 'n enkele kolom rye, waar elke item 'n groot voorskoubeeld vir 'n kategorie toon. Die pasgemaakte beeld neem die hele toegelate breedte. Die kategorietitel in die middel is op albei asse gesentreer, wat dit onmiddellik sigbaar en herkenbaar maak. Om die leesbaarheid te verbeter, het ek 'n subtiele helling van swart na deursigtig onder die teks bygevoeg.
As u oor die beeld en teks beweeg, word 'n bykomende infoteks sigbaar wat die totale aantal plasings vir hierdie kategorie aandui - 'n inligting wat nie voorheen beskikbaar was nie.
Om die navigasieprobleem op te los, het ek ook die bestaande aksiebalk hergebruik met alle hoofroetes wat die gebruiker beskikbaar het.
Verbeter deur herhaling
Om 'n aangenamer gebruikerservaring te bied, het ek ook 'n subtiele skaalanimasie by die beeld gevoeg toe ek oor 'n kategoriery sweef. Aangesien die beeld binne die oorspronklike grense skaal, groei die uitsig nie onnodig nie.
Boonop word 'n nuwe ry onder die kategoriebeeld sigbaar deur middel van animasie as u daaroor beweeg. Hierdie ry toon 'n seleksie van die nuutste plasings vir die kategorie. Elke voorskou is 'n skakel na die plasing. Elke ander interaktiewe element in die kategoriery maak die detailbladsy vir die kategorie oop.
Om die illusie van meer inhoud te gee as wat daar werklik is, het ek Daisy-UI se "stapel" -klas gebruik om aan elke voorskou 'n vervalste stapel te gee om 'n indruk te gee van meer voorskou-items onder die huidige.
Op klein toestelle word geen voorskoue weergegee nie. 'N Gebruiker kan slegs op die groot kategorie-prent klik om na die detailbladsy te gaan, waar alle plasings verskyn.
Hersien en kyk
Soos u kan sien, kan selfs 'n eenvoudige bladsy wat slegs 'n oorsig van elemente bevat, 'n bron van visuele en konseptuele foute wees, sowel as leermateriaal oor die ontwerp van 'n goeie en werkende UI sowel as UX.
Ek het geen plaaslike tekssoektog vir gebruikers bygevoeg om volgens teksinvoer te filter nie. Ek is voorlopig van plan om die verkenning op die bladsy te bevorder deur te blaai sowel as om te beweeg. As dit in die toekoms 'n probleem word (byvoorbeeld omdat gebruikers nie die inhoud kan vind wat hulle soek nie), sal ek 'n paar filteropsies byvoeg. Dit kan ook nodig word, aangesien die aantal poste sowel as kategorieë steeds toeneem. Natuurlik verwelkom ek u om die bladsy self te probeer.
Die bronkode
Die volgende teks bevat die volledige, onveranderde kode vir beide die bladsyhouer sowel as die kategoriegroepe. Alles is in Typescript geskryf met React.js en Tailwind.css. As u dink dat u 'n paar dele kan hergebruik, is ek bly dat ek u kan help.
//
// Page container.
//
import React from "react";
import { CMSCategoryResolution } from "../../cms/entities/cms.entity.catgory";
import Reveal from "../Reveal/Reveal";
import { BogPostCategoryPostsGroup } from "./BlogPostCategoryPostsGroup";
import BlogPostCategoriesOverviewHero from "./BlogPostCategoriesOverviewHero";
import PrimaryActionBar from "../PrimaryActionsBar/PrimaryActionsBar";
/*
*
* Interfaces.
*
*/
interface Props {
categories: CMSCategoryResolution[];
}
/*
*
* Components.
*
*/
export default function BlogPostCategoriesOverview(props: Props) {
const { categories } = props;
return (
<div className="max-w-6xl mx-auto">
<BlogPostCategoriesOverviewHero />
<div className="mt-10 mb-20">
<PrimaryActionBar isCentered color="white" />
</div>
<div className="px-6 mx-auto space-y-6 lg:px-0 md:space-y-16 lg:space-y-20">
{categories.map((c, i) => (
<Reveal key={i}>
<BogPostCategoryPostsGroup category={c} maxPostsEachThreshold={20} />
</Reveal>
))}
</div>
</div>
);
}
//
// BogPostCategoryPostsGroup.
//
import React from "react";
import { CMSCategoryResolution } from "../../cms/entities/cms.entity.catgory";
import { FLPath } from "../../models/route/model.route";
import { CMSCategoryIconFactory } from "../CMS/CMSCategoryIcon";
import Link from "next/link";
import RiMore from "remixicon-react/MoreLineIcon";
/*
*
* Interfaces.
*
*/
interface Props {
category: CMSCategoryResolution;
maxPostsEachThreshold: number;
}
/*
*
* Components.
*
*/
export const BogPostCategoryPostsGroup = (props: Props) => {
const { category, maxPostsEachThreshold } = props;
const { posts } = category;
if (posts.length === 0) {
return null;
}
const url = `${FLPath.Categories}/${category.slug.current}`;
const Icon = CMSCategoryIconFactory({ variant: category.slug.current });
return (
<div className="flex flex-col items-center group">
<div className="relative max-w-4xl overflow-visible rounded-md">
<div className="absolute items-end justify-start hidden w-full h-full px-6 space-x-4 overflow-x-scroll duration-500 ease-in-out translate-y-12 opacity-0 md:flex pb-14 group-hover:opacity-100 group-hover:translate-y-20">
{posts.slice(0, 4).map((p, i) => (
<span className="stack">
<Link
href={`${FLPath.Posts}/${p.slug.current}`}
aria-label={p.title}
prefetch={false}>
<a className="duration-200 ease-out hover:scale-105">
<img
src={p.imageUrl.jpg}
alt={p.title}
loading="lazy"
className="object-contain h-20 rounded "
/>
</a>
</Link>
{Array.from({ length: 2 }, (_, i) => (
<span key={i} style={{ width: 152, height: 80 }} className="bg-gray-800 rounded" />
))}
</span>
))}
{posts.length >= 5 && (
<Link passHref href={url} aria-label={`Link to ${category.title}`} prefetch={false}>
<a className="flex flex-col items-center justify-center h-20 w-14">
<RiMore />
</a>
</Link>
)}
</div>
<div className="relative flex flex-col items-center overflow-hidden duration-500 ease-in-out rounded-md shadow-xl md:group-hover:-translate-y-20">
<img
className="object-cover w-full duration-500 ease-in-out group-hover:scale-105"
width={960}
height={200}
src={category.imageUrl.webp}
alt={category.title}
loading="lazy"
/>
<Link passHref href={url} aria-label={`Link to ${category.title}`} prefetch={false}>
<a className="absolute flex flex-col items-center justify-center w-full h-full bg-gradient-to-t from-primary">
<span className="flex items-center space-x-2 duration-300 ease-in-out translate-y-2 group-hover:-translate-y-3">
<Icon size="2em" />
<h2 className="text-sm md:text-xl">{category.title}</h2>
</span>
<span className="text-sm font-light text-gray-200 transition duration-500 ease-in-out translate-y-2 opacity-0 group-hover:opacity-100 group-hover:-translate-y-2">
{category.posts.length}
{category.posts.length === maxPostsEachThreshold ? "+" : ""}{" "}
{category.posts.length === 1 ? "post" : "posts"}
</span>
</a>
</Link>
</div>
</div>
</div>
);
};