Project: Sierra Capital

Project Overview

A screencapture of the Sierra Capital home page, with a focus on the hero element

Sierra Capital

WebsiteGitHubPrototype

Designed and developed a website using React and TailwindCSS for a business research club called Sierra Capital.

Role: Web Developer/Designer

Date: September 2023

See the Process

Project Process Analysis

Video Walkthrough of Website

The video is a walkthrough of the Sierra Capital website. It starts off by scrolling up and down the home page until clicking on the call to action labelled "go to research" located in the hero. The user is taken to the research page, where clicking on a button labelled "industry" scrolls the page automatically to a subsection of the page called "Industry reports". Clicking on a report opens a PDF in a new tab, and then it is closed. The contact tab at the very top is clicked, and then finally the team tab, where the two team members' profiles are showcased. The video ends back at the home page.

Context

In September of 2023, I designed and developed a website, created with React and TailwindCSS, for a two-person business research club called Sierra Capital. The clients wanted a website to showcase their research reports, their professional profiles, and contact information.

A screencapture of the Sierra Capital research reports page. The window is scrolled to show the Industry reports subsection and the reports within it.
Pictured is a screenshot of part of the Sierra Capital research report page. The reports page features three subsections of research, as each research report, in the form of a PDF, is sorted accordingly based on the type using React.
A screencapture of the Sierra Capital teams page. The window is scrolled to the club members' minimized profiles.
Pictured is a screenshot of part of the Sierra Capital team page. This member showcase component features a minimized state (pictured), and when clicked, a more detailed profile appears.
A screencapture of the Sierra Capital contact page. The window is scrolled to show the club's email and also the members' compacted profiles.
Pictured is a screenshot of part of the Sierra Capital contact page. The page features a hero urging the user to contact them with a link to email the club, and the users' profiles are linked at the bottom as well.

Reasoning

One challenge I faced was showcasing the members' profiles. I aimed to keep the interaction simple, focusing on the members. How could I present each member equally while also highlighting them as needed?

During wireframing, I decided to use compact cards that expand to detailed profiles. This solution allowed both profiles to be displayed equally as a team while giving users the option to expand a profile for more details.

A screencapture of the Sierra Capital team page wireframe. The screenshot features two cards, with a Figma comment from Johann Ferrera saying, "* highlights description when you click on someone".
Pictured is a screenshot of the wireframes for the team members component. The component features two profiles with the members' portrait, name, title, and links to their email and LinkedIn.

After prototyping the component in Figma (link to Figma prototype here), I realized a state-based approach would be best for development with ReactJS. Using the useState hook, I could change the component's state without reloading the entire page.

A screencapture of a Figma file of the Sierra Capital team members component in prototyping mode. There are a total of five frames, with three in the middle being for hover states while the other two are for the expanded profiles for each member.
Pictured is a screenshot of part of the Figma file of the Sierra Capital team members component in prototyping mode. Upon clicking on a member's card/portrait, the corresponding member's profile will expand to reveal more information about them.

Development

I set up the initial state based on the link's hash, allowing direct links to specific member profiles from other pages. Ternary operators were used to avoid using if/else statements, keeping the code concise.

The code for determining the initial state:
export default function TeamProfiles() {
  // 0 is rohit, 1 is antoine, 2 is default
  const { hash } = useLocation();
  const [state, setState] = useState(
    ((hash !== "") ? ((hash === "#antoine") ? 1 : ((hash === "#rohit") ? 0 : 2)) : 2)
  );
...

I implemented the design using only three elements within the container: the first member's portrait, the expanded text container, and the second member's portrait.

I opted for this approach of hiding elements based on the component state and updating the text content on click instead of creating three different states containing similar elements, keeping the code elegant. This also results in enhanced site performance due to no additional elements needed to be rendered or coded after every click.

The code for the component container:
return (
  <div className={`w-screen mb-20 md:h-screen flex flex-col md:flex-row justify-evenly place-items-center ${state !== 1 ? "flex-col" : `flex-col-reverse`}`} id="team">
    ...
  </div>
)
The code for the first member's profile element:
<button onClick={() => setState(0)} className={`flex flex-col place-items-center justify-center md:w-[20%] w-[60%] group ${state !== 1 ? "" : `hidden`}`}>
  <img src={rohit} alt="Portrait of Rohit Deol" className={`my-8 transition ease-in-out duration-200 xl:max-h-[35rem] ${state === 0 ? "grayscale-0 shadow-2xl shadow-accent/10" : `group-hover:grayscale-0 group-hover:shadow-2xl shadow-secondary grayscale-[50%]`}`} id="rohit"/>
  <Link
    text={"Rohit Deol"}
    link={"/team"}
    className={`${styles.heading3} capitalize ${state === 0 ? 'hidden' : ''}`}
  />
  <hr className={`border-accent border-t-2 w-full my-2 ${state === 0 ? 'hidden' : ''}`}></hr>
  <p className={`${styles.caption} py-2 ${state === 0 ? 'hidden' : ''}`}>Co-Founder and Analyst</p>
  <div className={`flex mt-2 ${state === 0 ? 'hidden' : ''}`}>
      {socialMediaRohit.map((soc, index) => (
      <a href={soc.link} key={index}>
        <img className="w-[1.2em] mx-1" src={soc.icon} alt={soc.id}/>
      </a>
    ))}
  </div>
</button>
The code for the expanded details component:
<div className={`flex flex-col items-center max-h-[80%] min-w-[30%] md:max-w-[50%] max-w-[90%] xs:p-[3%] border-accent lg:border-2 group ${state !== 2 ? "" : hidden}`} id={profiles[state].id}>
  <div className="flex justify-between w-full">
    <h1 className={`${styles.heading2}`}>{profiles[state].name}</h1>
    <div className="flex items-center">
    {profiles[state].socials.map((soc, index) => (
        <a href={soc.link} key={index}>
        <img className="w-[1.5em] mx-1" src={soc.icon} alt={soc.id}/>
      </a>
    ))}
    </div>
  </div>
  <hr className="border-accent border-t-2 w-full my-5"></hr>
  <p className={`${styles.caption}`}>{profiles[state].title}</p>
  <p className={`${styles.body} max-w-prose my-5`}>
    {profiles[state].bio}
  </p>
  <Button
    onClick={() => setState(2)}
    className={state !== 2 ? "" : `hidden`}
    text={"Back"}
    width={100}
  />
</div>
The code for the second member's profile element:
<button onClick={() => setState(1)} className={`flex flex-col place-items-center justify-center md:w-[20%] w-[60%] group ${state !== 0 ? "" : `hidden`}`} id="antoine">
  <img src={antoine} alt="Portrait of Antoine Au Yeung" className={`my-8 transition ease-in-out duration-200 xxl:max-h-[35rem] ${state === 1 ? "grayscale-0 shadow-2xl shadow-accent/10" : `group-hover:grayscale-0 group-hover:shadow-2xl shadow-secondary grayscale-[50%]`}`}/>
  <Link
    text={"Antoine Au Yeung"}
    link={"/team"}
    className={`${styles.heading3} capitalize ${state === 1 ? 'hidden' : ''}`}
  />
  <hr className={`border-accent border-t-2 w-full my-2 ${state === 1 ? 'hidden' : ''}`}></hr>
  <p className={`${styles.caption} py-2 ${state === 1 ? 'hidden' : ''}`}>Co-Founder and Analyst</p>
  <div className={`flex mt-2 ${state === 1 ? 'hidden' : ''}`}>
    {socialMediaAntoine.map((soc, index) => (
        <a href={soc.link} key={index}>
        <img className="w-[1.2em] mx-1" src={soc.icon} alt={soc.id}/>
      </a>
    ))}
  </div>
</button>

Conclusion

This solution demonstrates my ability to create elegant, interactive code using ReactJS. However, I realize the limitations on accessibility now that I've learned more about it.

In future React projects, I would improve my code by incorporating ARIA for accessibility, designing clearer hover and focus states, and simplifying keyboard navigation to address these accessibility concerns.

See Similar Projects

Sauder Club

Club Website as a Web Designer/Developer

Aug 2024

Burst

Company Website as a Main Developer

Jun 2024