Skip to content

Commit

Permalink
feat: TagList molecule
Browse files Browse the repository at this point in the history
  • Loading branch information
alexgoff committed Dec 18, 2024
1 parent 05e8d18 commit f2a3a9d
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 26 deletions.
38 changes: 38 additions & 0 deletions components/molecules/TagList/TagList.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import TagList from "./index";

const tags = [
{ name: "Static Tag" },
{ name: "Linked Tag", destination: "https://rubinobservatory.org" },
];

describe("<TagList>", () => {
it("should render an unordered list", () => {
cy.mount(<TagList />);
cy.get("ul").should("exist");
});

it("should render tag names with a pound symbol by default", () => {
cy.mount(<TagList tags={tags} />);
cy.get("ul > li").each(($el, i) => {
cy.wrap($el).contains(`#${tags[i].name}`);
});
});

it("should omit pound symbol if specified", () => {
cy.mount(<TagList tags={tags} showPound={false} />);
cy.get("ul > li").each(($el, i) => {
cy.wrap($el).contains(tags[i].name);
});
});

it("should render links if provided", () => {
cy.mount(<TagList tags={tags} />);
cy.get("ul > li").each(($el, i) => {
if (tags[i].destination) {
cy.wrap($el).children("a").should("exist");
} else {
cy.wrap($el).children("a").should("not.exist");
}
});
});
});
49 changes: 49 additions & 0 deletions components/molecules/TagList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { FunctionComponent } from "react";
import classNames from "classnames";
import Link from "next/link";
import styles from "./styles.module.css";

export type Tag = {
name: string;
destination?: string;
};
interface TagListProps {
tags: Array<Tag>;
showPound?: boolean;
withLinebreaks?: boolean;
className?: string;
}

const TagList: FunctionComponent<TagListProps> = ({
tags = [],
showPound = true,
withLinebreaks = false,
className,
}) => {
return (
<ul
data-no-break={!withLinebreaks}
className={classNames(styles.tagList, className)}
>
{tags.map(({ name, destination }) => {
const tagName = showPound ? `#${name}` : name;

return (
<li className={styles.tag} data-no-break={!withLinebreaks} key={name}>
{destination ? (
<Link href={destination} rel="tag">
{tagName}
</Link>
) : (
tagName
)}
</li>
);
})}
</ul>
);
};

TagList.displayName = "Molecule.TagList";

export default TagList;
18 changes: 18 additions & 0 deletions components/molecules/TagList/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.tagList {
&[data-no-break="true"] {
display: flex;
flex-wrap: wrap;
column-gap: 1ex;
}
}

.tag {
& a {
color: var(--color-font-accent);
}

&[data-no-break="true"] {
display: inline-block;
white-space: nowrap;
}
}
27 changes: 9 additions & 18 deletions components/page/Aside/Tags/index.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,24 @@
import PropTypes from "prop-types";
import Link from "next/link";
import { useTranslation } from "react-i18next";
import AsideSection from "../Section";
import * as Styled from "./styles";
import TagList from "@/components/molecules/TagList";

export default function Tags({ tags, rootHomeLink }) {
const { t } = useTranslation();

if (!tags) return null;
if (tags.length <= 0) return null;

const tagsWithLinks = tags.map(({ slug, title }) => {
return {
name: title,
destination: `/${rootHomeLink?.uri}?search=${slug}`,
};
});

return (
<AsideSection title={t(`tags`)}>
<Styled.TagList>
{tags.map((tag, i) => {
if (rootHomeLink?.uri && tag.slug) {
return (
<Styled.Tag key={i}>
<Link
prefetch={false}
href={`/${rootHomeLink?.uri}?search=${tag.slug}`}
>
{`#${tag.title}`}
</Link>
</Styled.Tag>
);
}
})}
</Styled.TagList>
<TagList tags={tagsWithLinks} />
</AsideSection>
);
}
Expand Down
8 changes: 0 additions & 8 deletions components/page/Aside/Tags/styles.js

This file was deleted.

0 comments on commit f2a3a9d

Please sign in to comment.