From d926afdf6157e9acf8fff335c8adf18ba695eae9 Mon Sep 17 00:00:00 2001 From: GotPop Date: Sun, 4 Jan 2026 17:52:29 +0000 Subject: [PATCH 1/4] Adding filter icons --- packages/system/package.json | 2 +- .../CardsClientFilter/CardsClientFilter.tsx | 15 +++++++++++- .../ui/CardsControl/CardsControl.tsx | 10 +++++++- .../system/src/components/ui/Icon/Icon.tsx | 23 +++++++++++-------- yarn.lock | 2 +- 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/packages/system/package.json b/packages/system/package.json index 987b6f2..8a110af 100644 --- a/packages/system/package.json +++ b/packages/system/package.json @@ -1,6 +1,6 @@ { "name": "@gotpop/system", - "version": "0.1.284", + "version": "0.1.285", "description": "React design system components for gotpop", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/system/src/components/storyblok/CardsClientFilter/CardsClientFilter.tsx b/packages/system/src/components/storyblok/CardsClientFilter/CardsClientFilter.tsx index 5035164..676ab2f 100644 --- a/packages/system/src/components/storyblok/CardsClientFilter/CardsClientFilter.tsx +++ b/packages/system/src/components/storyblok/CardsClientFilter/CardsClientFilter.tsx @@ -9,11 +9,19 @@ import type { import { getMeta } from "../../../utils/card-utils" import { CardsControl } from "../../ui/CardsControl/CardsControl" import { CustomElement } from "../../ui/CustomElement" +import type { IconName } from "../../ui/Icon/Icon" import { Card, type CardBlokProps } from "../Card/Card" import { CardImage } from "../CardImage" import { useCardsFilter } from "./use-cards-filter" import "./CardsClientFilter.css" +const SORT_ICON_MAP: Record = { + published_desc: "calendar-arrow-down", + published_asc: "calendar-arrow-up", + name_asc: "arrow-down-az", + name_desc: "arrow-up-za", +} + const SORT_OPTIONS = [ { value: "published_desc", label: "Newest First" }, { value: "published_asc", label: "Oldest First" }, @@ -83,6 +91,11 @@ export function CardsClientFilter({ ...availableTagOptions, ] + const sortOptions = SORT_OPTIONS.map((option) => ({ + ...option, + icon: SORT_ICON_MAP[option.value], + })) + const output = filteredAndSortedPosts.length > 0 && filteredAndSortedPosts.map((blok) => @@ -107,7 +120,7 @@ export function CardsClientFilter({ label="Sort" value={currentSort} onChange={handleSortChange} - options={SORT_OPTIONS} + options={sortOptions} /> diff --git a/packages/system/src/components/ui/CardsControl/CardsControl.tsx b/packages/system/src/components/ui/CardsControl/CardsControl.tsx index 2a1e1e2..8741d80 100644 --- a/packages/system/src/components/ui/CardsControl/CardsControl.tsx +++ b/packages/system/src/components/ui/CardsControl/CardsControl.tsx @@ -2,13 +2,20 @@ import { useId } from "react" import { CustomElement } from "../../ui/CustomElement" +import { Icon, type IconName } from "../Icon/Icon" import "./CardsControl.css" +export interface CardsControlOption { + value: string + label: string + icon?: IconName +} + interface CardsControlProps { label: string value: string onChange: (value: string) => void - options: { value: string; label: string }[] + options: CardsControlOption[] className?: string style?: React.CSSProperties } @@ -38,6 +45,7 @@ export function CardsControl({ .filter((option) => option.value && option.label) .map((option) => ( ))} diff --git a/packages/system/src/components/ui/Icon/Icon.tsx b/packages/system/src/components/ui/Icon/Icon.tsx index d952955..9c631dd 100644 --- a/packages/system/src/components/ui/Icon/Icon.tsx +++ b/packages/system/src/components/ui/Icon/Icon.tsx @@ -1,5 +1,11 @@ import { + ArrowDownAZ, + ArrowDownZA, + ArrowUpAZ, + ArrowUpZA, BriefcaseBusiness, + CalendarArrowDown, + CalendarArrowUp, ChevronLeft, ChevronRight, ExternalLink, @@ -17,13 +23,6 @@ import { X, } from "lucide-react" -/** - * Icon registry - single source of truth for available icons. - * Only icons listed here will be bundled (tree-shaking optimization). - * Add new icons here and run `yarn sync-icons` to update Storyblok datasource. - * - * Keys match the CMS datasource values (kebab-case) - */ const ICON_REGISTRY = { mail: Mail, newspaper: Newspaper, @@ -41,14 +40,18 @@ const ICON_REGISTRY = { star: Star, x: X, user: User, + "arrow-down-az": ArrowDownAZ, + "arrow-up-az": ArrowUpAZ, + "arrow-down-za": ArrowDownZA, + "arrow-up-za": ArrowUpZA, + "calendar-arrow-down": CalendarArrowDown, + "calendar-arrow-up": CalendarArrowUp, } as const -// Export for sync scripts and type generation export const AVAILABLE_ICONS = Object.keys(ICON_REGISTRY) as Array< keyof typeof ICON_REGISTRY > -// Type-safe icon names export type IconName = keyof typeof ICON_REGISTRY interface IconProps { @@ -76,7 +79,7 @@ export function Icon({ "Icon not found:", JSON.stringify({ name, availableIcons: AVAILABLE_ICONS }, null, 2) ) - // render a safe fallback so consumers still get an icon + return ( diff --git a/yarn.lock b/yarn.lock index 81d46a5..805ce6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -938,7 +938,7 @@ "@storyblok/react" "5.4.20" "@gotpop/system@*", "@gotpop/system@file:/Users/minivan/web/sites/platform/system/packages/system": - version "0.1.284" + version "0.1.285" resolved "file:packages/system" dependencies: "@next/font" "^14.2.15" From 937a953c66b73d4e8e6ce5a1a6e9459273378e2e Mon Sep 17 00:00:00 2001 From: GotPop Date: Mon, 5 Jan 2026 16:05:35 +0000 Subject: [PATCH 2/4] Adding picker styling --- .../ui/CardsControl/CardsControl.css | 116 +++++++++++++++--- .../ui/CardsControl/CardsControl.tsx | 3 + .../system/src/types/custom-elements.d.ts | 8 ++ 3 files changed, 110 insertions(+), 17 deletions(-) diff --git a/packages/system/src/components/ui/CardsControl/CardsControl.css b/packages/system/src/components/ui/CardsControl/CardsControl.css index 86b11ee..ae9fe69 100644 --- a/packages/system/src/components/ui/CardsControl/CardsControl.css +++ b/packages/system/src/components/ui/CardsControl/CardsControl.css @@ -1,42 +1,124 @@ @scope (select-option) { & { align-items: center; - background: var(--dark-500); + background: var(--light-100); display: grid; grid-column: var(--grid-column, auto); grid-template-columns: auto 1fr; min-width: var(--round-up); + border: 1px solid var(--light-300); + height: 3rem; + } + + .select { + appearance: none; + background-image: none; + border-radius: 0px; + box-sizing: border-box; + color: var(--dark-500); + font-size: var(--text-xs); + outline: none; + padding: 0.5rem 1.5rem; + cursor: pointer; + border: none; + height: 46px; + display: flex; + align-items: center; + + @supports (appearance: base-select) { + appearance: base-select; + } } .select-label { align-items: center; - color: white; + color: var(--dark-800); + font-size: var(--text-xs); display: flex; height: max-content; justify-content: center; min-height: 2rem; - min-width: 6rem; + min-width: 5rem; width: max-content; - padding-inline: 1rem; + cursor: pointer; + border-right: 1px solid var(--light-300); } - .select { - appearance: none; - background-image: none; - background: var(--light-100); - border-radius: 0px; + .selected-content { + display: flex; + min-width: 8rem; + align-items: end; + gap: 1rem; + + span { + color: var(--secondary-700); + } + } + + select::picker-icon { + color: var(--dark-500); + transition: 0.4s rotate; + } + + select:open::picker-icon { + rotate: 180deg; + } + + ::picker(select) { + opacity: 0; + transition: all 0.2s allow-discrete; + translate: 0 50px; + scale: 0.7; border: 1px solid var(--light-300); - box-sizing: border-box; + + &:popover-open { + opacity: 1; + translate: 0 0; + scale: 1; + + @starting-style { + translate: 0 50px; + opacity: 0; + scale: 0.5; + } + } + } + + option::checkmark { + display: none; + } + + option:checked { + font-weight: bold; + } + + option { color: var(--dark-500); - display: flex; + background-color: var(--light-100); font-size: var(--text-sm); - height: 2rem; - line-height: 0.8; - outline: none; - padding: 0.5rem 0.75rem; + padding: 0 1.5rem; + display: flex; + align-items: center; + gap: 1rem; + justify-content: start; + height: 3rem; + font-size: var(--text-xs); + transition: color 0.3s ease-in-out; + cursor: pointer; + border-bottom: 1px solid var(--light-200); - @supports (appearance: base-select) { - appearance: base-select; + &:last-child { + border-bottom: none; + } + + span { + display: flex; + align-items: center; + } + + &:hover, + &:focus-visible { + color: var(--primary-400); } } } diff --git a/packages/system/src/components/ui/CardsControl/CardsControl.tsx b/packages/system/src/components/ui/CardsControl/CardsControl.tsx index 8741d80..e2f63e0 100644 --- a/packages/system/src/components/ui/CardsControl/CardsControl.tsx +++ b/packages/system/src/components/ui/CardsControl/CardsControl.tsx @@ -41,6 +41,9 @@ export function CardsControl({ onChange={(e) => onChange(e.target.value)} className="select" > + {options .filter((option) => option.value && option.label) .map((option) => ( diff --git a/packages/system/src/types/custom-elements.d.ts b/packages/system/src/types/custom-elements.d.ts index 3719d24..8acfd94 100644 --- a/packages/system/src/types/custom-elements.d.ts +++ b/packages/system/src/types/custom-elements.d.ts @@ -48,6 +48,14 @@ declare module "react" { React.HTMLAttributes, HTMLElement > + "select-option": React.DetailedHTMLProps< + React.HTMLAttributes, + HTMLElement + > + selectedcontent: React.DetailedHTMLProps< + React.HTMLAttributes, + HTMLElement + > } } } From 1419040c823ca261d9602b9b3b942b82ca894a8e Mon Sep 17 00:00:00 2001 From: GotPop Date: Mon, 5 Jan 2026 16:38:11 +0000 Subject: [PATCH 3/4] Adding picker styling & icons --- packages/system/package.json | 3 ++- .../storyblok/CardsClientFilter/CardsClientFilter.tsx | 10 +++++++++- packages/system/src/components/ui/Icon/Icon.tsx | 6 ++++++ yarn.lock | 10 ++++++++-- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/packages/system/package.json b/packages/system/package.json index 8a110af..e280e60 100644 --- a/packages/system/package.json +++ b/packages/system/package.json @@ -1,6 +1,6 @@ { "name": "@gotpop/system", - "version": "0.1.285", + "version": "0.1.286", "description": "React design system components for gotpop", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -68,6 +68,7 @@ "publish:github": "npm version patch && yarn build && npm publish && cd ../.. && rm -f package-lock.json" }, "dependencies": { + "@icons-pack/react-simple-icons": "^13.8.0", "@next/font": "^14.2.15", "lucide-react": "^0.469.0", "motion": "^12.23.26", diff --git a/packages/system/src/components/storyblok/CardsClientFilter/CardsClientFilter.tsx b/packages/system/src/components/storyblok/CardsClientFilter/CardsClientFilter.tsx index 676ab2f..428dc5e 100644 --- a/packages/system/src/components/storyblok/CardsClientFilter/CardsClientFilter.tsx +++ b/packages/system/src/components/storyblok/CardsClientFilter/CardsClientFilter.tsx @@ -22,6 +22,13 @@ const SORT_ICON_MAP: Record = { name_desc: "arrow-up-za", } +const TAG_ICON_MAP: Record = { + all: "tag", + css: "css", + javascript: "javascript", + html: "html5", +} + const SORT_OPTIONS = [ { value: "published_desc", label: "Newest First" }, { value: "published_asc", label: "Oldest First" }, @@ -84,10 +91,11 @@ export function CardsClientFilter({ .map((tag) => ({ value: tag.value, label: tag.name, + icon: TAG_ICON_MAP[tag.value.toLowerCase()], })) const tagOptions = [ - { value: "all", label: "All Posts" }, + { value: "all", label: "All Posts", icon: TAG_ICON_MAP.all }, ...availableTagOptions, ] diff --git a/packages/system/src/components/ui/Icon/Icon.tsx b/packages/system/src/components/ui/Icon/Icon.tsx index 9c631dd..43079b7 100644 --- a/packages/system/src/components/ui/Icon/Icon.tsx +++ b/packages/system/src/components/ui/Icon/Icon.tsx @@ -1,3 +1,4 @@ +import { SiCss, SiHtml5, SiJavascript } from "@icons-pack/react-simple-icons" import { ArrowDownAZ, ArrowDownZA, @@ -19,6 +20,7 @@ import { Phone, Search, Star, + Tag, User, X, } from "lucide-react" @@ -40,12 +42,16 @@ const ICON_REGISTRY = { star: Star, x: X, user: User, + tag: Tag, "arrow-down-az": ArrowDownAZ, "arrow-up-az": ArrowUpAZ, "arrow-down-za": ArrowDownZA, "arrow-up-za": ArrowUpZA, "calendar-arrow-down": CalendarArrowDown, "calendar-arrow-up": CalendarArrowUp, + css: SiCss, + javascript: SiJavascript, + html5: SiHtml5, } as const export const AVAILABLE_ICONS = Object.keys(ICON_REGISTRY) as Array< diff --git a/yarn.lock b/yarn.lock index 805ce6a..25404d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -938,9 +938,10 @@ "@storyblok/react" "5.4.20" "@gotpop/system@*", "@gotpop/system@file:/Users/minivan/web/sites/platform/system/packages/system": - version "0.1.285" + version "0.1.286" resolved "file:packages/system" dependencies: + "@icons-pack/react-simple-icons" "^13.8.0" "@next/font" "^14.2.15" lucide-react "^0.469.0" motion "^12.23.26" @@ -950,6 +951,11 @@ simple-icons "^16.3.0" storyblok-rich-text-react-renderer "^3.0.1" +"@icons-pack/react-simple-icons@^13.8.0": + version "13.8.0" + resolved "https://registry.npmjs.org/@icons-pack/react-simple-icons/-/react-simple-icons-13.8.0.tgz" + integrity sha512-iZrhL1fSklfCCVn68IYHaAoKfcby3RakUTn2tRPyHBkhr2tkYqeQbjJWf+NizIYBzKBn2IarDJXmTdXd6CuEfw== + "@img/colour@^1.0.0": version "1.0.0" resolved "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz" @@ -3971,7 +3977,7 @@ react-refresh@^0.14.0, "react-refresh@>=0.10.0 <1.0.0": resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz" integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== -"react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react@^17 || ^18 || ^19", "react@^18.0.0 || ^19.0.0", "react@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react@^19.2.0, react@^19.2.3, "react@>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0", react@>=16.0.0, react@>=19.2.3, react@19.2.3: +"react@^16.13 || ^17 || ^18 || ^19", "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react@^17 || ^18 || ^19", "react@^18.0.0 || ^19.0.0", "react@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react@^19.2.0, react@^19.2.3, "react@>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0", react@>=16.0.0, react@>=19.2.3, react@19.2.3: version "19.2.3" resolved "https://registry.npmjs.org/react/-/react-19.2.3.tgz" integrity sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA== From c994bb5ac15ce83c069a14e66b07d7b4caa773ec Mon Sep 17 00:00:00 2001 From: GotPop Date: Mon, 5 Jan 2026 18:16:30 +0000 Subject: [PATCH 4/4] Adding work icons --- packages/system/package.json | 2 +- .../CardsClientFilter/CardsClientFilter.tsx | 12 +++ .../ui/CardsControl/CardsControl.css | 89 +++++++++---------- .../system/src/components/ui/Icon/Icon.tsx | 26 +++++- yarn.lock | 2 +- 5 files changed, 83 insertions(+), 48 deletions(-) diff --git a/packages/system/package.json b/packages/system/package.json index e280e60..fd672bb 100644 --- a/packages/system/package.json +++ b/packages/system/package.json @@ -1,6 +1,6 @@ { "name": "@gotpop/system", - "version": "0.1.286", + "version": "0.1.287", "description": "React design system components for gotpop", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/system/src/components/storyblok/CardsClientFilter/CardsClientFilter.tsx b/packages/system/src/components/storyblok/CardsClientFilter/CardsClientFilter.tsx index 428dc5e..7b7e24b 100644 --- a/packages/system/src/components/storyblok/CardsClientFilter/CardsClientFilter.tsx +++ b/packages/system/src/components/storyblok/CardsClientFilter/CardsClientFilter.tsx @@ -27,6 +27,18 @@ const TAG_ICON_MAP: Record = { css: "css", javascript: "javascript", html: "html5", + react: "react", + angular: "angular", + vuejs: "vuedotjs", + next: "nextdotjs", + nextjs: "nextdotjs", + node: "nodedotjs", + nodejs: "nodedotjs", + typescript: "typescript", + graphql: "graphql", + cloudflare: "cloudflare", + accessibility: "accessibility", + aws: "cloud", } const SORT_OPTIONS = [ diff --git a/packages/system/src/components/ui/CardsControl/CardsControl.css b/packages/system/src/components/ui/CardsControl/CardsControl.css index ae9fe69..9430e96 100644 --- a/packages/system/src/components/ui/CardsControl/CardsControl.css +++ b/packages/system/src/components/ui/CardsControl/CardsControl.css @@ -2,28 +2,38 @@ & { align-items: center; background: var(--light-100); + border: 1px solid var(--light-300); display: grid; grid-column: var(--grid-column, auto); grid-template-columns: auto 1fr; + height: var(--spacing-lg); min-width: var(--round-up); - border: 1px solid var(--light-300); - height: 3rem; } .select { + align-items: center; appearance: none; background-image: none; border-radius: 0px; + border: none; box-sizing: border-box; color: var(--dark-500); + cursor: pointer; + display: flex; font-size: var(--text-xs); + height: 46px; outline: none; padding: 0.5rem 1.5rem; - cursor: pointer; - border: none; - height: 46px; - display: flex; - align-items: center; + + &::picker-icon { + color: var(--dark-500); + transition: 0.4s rotate; + transition-delay: 0.25s; + } + + &:open::picker-icon { + rotate: -180deg; + } @supports (appearance: base-select) { appearance: base-select; @@ -32,85 +42,74 @@ .select-label { align-items: center; + border-right: 1px solid var(--light-300); color: var(--dark-800); - font-size: var(--text-xs); + cursor: pointer; display: flex; + font-size: var(--text-xs); height: max-content; justify-content: center; - min-height: 2rem; + min-height: var(--spacing-md); min-width: 5rem; width: max-content; - cursor: pointer; - border-right: 1px solid var(--light-300); } .selected-content { + align-items: end; display: flex; + gap: var(--spacing-base); min-width: 8rem; - align-items: end; - gap: 1rem; span { color: var(--secondary-700); } } - select::picker-icon { - color: var(--dark-500); - transition: 0.4s rotate; - } - - select:open::picker-icon { - rotate: 180deg; - } - ::picker(select) { - opacity: 0; - transition: all 0.2s allow-discrete; - translate: 0 50px; - scale: 0.7; border: 1px solid var(--light-300); + opacity: 0; + scale: 0.5; + transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1) allow-discrete; + transform-origin: top center; &:popover-open { opacity: 1; - translate: 0 0; scale: 1; @starting-style { - translate: 0 50px; opacity: 0; scale: 0.5; } } } - option::checkmark { - display: none; - } - - option:checked { - font-weight: bold; - } - option { - color: var(--dark-500); + align-items: center; background-color: var(--light-100); - font-size: var(--text-sm); - padding: 0 1.5rem; + border-bottom: 1px solid var(--light-200); + color: var(--dark-500); + cursor: pointer; display: flex; - align-items: center; - gap: 1rem; - justify-content: start; - height: 3rem; + font-size: var(--text-sm); font-size: var(--text-xs); + gap: var(--spacing-base); + height: var(--spacing-lg); + justify-content: start; + padding: 0 1.5rem; transition: color 0.3s ease-in-out; - cursor: pointer; - border-bottom: 1px solid var(--light-200); + + &::checkmark { + display: none; + } &:last-child { border-bottom: none; } + &:checked { + font-weight: bold; + } + span { display: flex; align-items: center; diff --git a/packages/system/src/components/ui/Icon/Icon.tsx b/packages/system/src/components/ui/Icon/Icon.tsx index 43079b7..2aaa8df 100644 --- a/packages/system/src/components/ui/Icon/Icon.tsx +++ b/packages/system/src/components/ui/Icon/Icon.tsx @@ -1,5 +1,18 @@ -import { SiCss, SiHtml5, SiJavascript } from "@icons-pack/react-simple-icons" import { + SiAngular, + SiCloudflare, + SiCss, + SiGraphql, + SiHtml5, + SiJavascript, + SiNextdotjs, + SiNodedotjs, + SiReact, + SiTypescript, + SiVuedotjs, +} from "@icons-pack/react-simple-icons" +import { + Accessibility, ArrowDownAZ, ArrowDownZA, ArrowUpAZ, @@ -9,6 +22,7 @@ import { CalendarArrowUp, ChevronLeft, ChevronRight, + Cloud, ExternalLink, Github, HelpCircle, @@ -52,6 +66,16 @@ const ICON_REGISTRY = { css: SiCss, javascript: SiJavascript, html5: SiHtml5, + react: SiReact, + angular: SiAngular, + vuedotjs: SiVuedotjs, + nextdotjs: SiNextdotjs, + nodedotjs: SiNodedotjs, + typescript: SiTypescript, + graphql: SiGraphql, + cloudflare: SiCloudflare, + accessibility: Accessibility, + cloud: Cloud, } as const export const AVAILABLE_ICONS = Object.keys(ICON_REGISTRY) as Array< diff --git a/yarn.lock b/yarn.lock index 25404d2..3f48bf9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -938,7 +938,7 @@ "@storyblok/react" "5.4.20" "@gotpop/system@*", "@gotpop/system@file:/Users/minivan/web/sites/platform/system/packages/system": - version "0.1.286" + version "0.1.287" resolved "file:packages/system" dependencies: "@icons-pack/react-simple-icons" "^13.8.0"