ProductArtwork
A product's official mark on a gradient field of its own brand colour, plus AppGlyph, a line-icon tile for modules that have no mark.
Code
import { ProductArtwork } from "@fadymondy/nasaq/web";export function MahaamCover() { return <ProductArtwork brand="mahaam" className="aspect-[16/10] w-80" />;}Brand · beta
Live examples and controls: ProductArtwork in the lab.
Install
npx shadcn@latest add https://docs.nasaqui.com/r/product-artwork.jsonProductArtwork is a cover image for a product: the official mark, centred on a field tinted with the product's
own brand colour. The field is a CSS gradient built from the product manifest, so there are no raster assets, and
it follows light, dark and every brand. AppGlyph is the counterpart for apps or modules that have no official
mark (Inventory, Payments): a line icon on a brand tint.
When to use
- A card cover, store listing hero or banner for a product that has a mark.
- A larger field where a bare
ProductMarkwould float on an empty surface. AppGlyph: a small icon tile for a module or feature that is not a product.
When not to use
- Just the mark, inline or small: use
ProductMark. - A product that has an official mark: never fake it with
AppGlyph. UseProductMarkorProductArtwork. - A launcher or list of installed products: use
ProductSwitcher. - A full listing card with name, price and install action: use
ProductCard.
Import
import { AppGlyph, ProductArtwork } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"Quick start
import { ProductArtwork } from "@fadymondy/nasaq/web";
export function MahaamCover() {
return <ProductArtwork brand="mahaam" className="aspect-[16/10] w-80" />;
}Anatomy
ProductArtwork data-slot="product-artwork", data-brand="<brand>" <div>
├─ ring inset 1px ring in the brand tint, aria-hidden
└─ children default: <ProductMark brand size={markSize} title="" />
AppGlyph data-slot="app-glyph", data-brand="<brand>" <span aria-hidden>
└─ icon lucide icon, sized by `size`API
ProductArtwork
ProductArtworkProps extends ComponentProps<"div">. Remaining props go to the outer <div>.
| Prop | Type | Default | Description |
|---|---|---|---|
brand | BrandKey | (string & {}) | required | The product whose manifest tints the field. Also sets data-brand, so --nq-brand inside is that product's colour. |
markSize? | number | 48 | Size of the centred mark in px. Ignored when children is given. |
children? | ReactNode | ProductMark | Replaces the centred mark: a badge plus the mark, a product glimpse, a whole banner layout. |
className? | string | none | Merged onto the outer div. Give it a size or an aspect-*; the component has no intrinsic size. |
style? | CSSProperties | none | Merged after the gradient, so it can override the field. |
AppGlyph
AppGlyphProps extends Omit<ComponentProps<"span">, "children">.
| Prop | Type | Default | Description |
|---|---|---|---|
icon | LucideIcon | ReactElement | required | A lucide icon component or an element. |
brand? | BrandKey | (string & {}) | surrounding brand | Tint with this product's brand instead of the surrounding one. |
size? | "sm" | "md" | "lg" | "md" | sm is 28px, md 36px, lg 44px. |
className? | string | none | Merged onto the span. |
Examples
Custom content on the field
import { Badge, ProductArtwork, ProductMark } from "@fadymondy/nasaq/web";
export function FeaturedCover() {
return (
<ProductArtwork brand="zekra" className="aspect-[16/10] w-80 flex-col gap-3">
<ProductMark brand="zekra" size={56} title="Zekra" />
<Badge variant="brand">جديد</Badge>
</ProductArtwork>
);
}Glyphs for modules without a mark
import { AppGlyph } from "@fadymondy/nasaq/web";
import { ReceiptText, Users } from "lucide-react";
export function Modules() {
return (
<div className="flex items-center gap-3">
<AppGlyph icon={Users} size="sm" />
<AppGlyph icon={ReceiptText} size="lg" brand="mahaam" />
</div>
);
}Accessibility
ProductArtworkis decorative by default: the default mark is drawn withtitle="", and there is no role. Put the product name in adjacent text (a card title, a heading).- If you pass your own
childrenthat carry meaning, give them their own accessible names. AppGlyphisaria-hidden. Always pair it with a visible label.- Neither component is focusable. There are no keyboard interactions.
RTL & i18n
- The gradient's light source sits at the inline-start top corner. It flips to the left in RTL through the
--art-xvariable, and the softer bounce flips to the opposite corner. - The mark and glyph icons are not directional and are not mirrored.
- No built-in strings.
Styling & tokens
- Tokens:
--nq-brand(fromdata-brand),--nq-surface-raised,text-nq-brand, radiusrounded-card(rounded-controlfor small glyphs). - Target with
[data-slot=product-artwork],[data-slot=app-glyph]or[data-brand=mahaam]. - Extend with
className(size, aspect ratio, radius). Do not recolour with raw hex; the tint comes from the brand manifest.
Do / Don't
- Do let the field come from
brand; it is derived from the manifest. - Do use
AppGlyphonly for modules and apps without a mark. - Don't recolour, crop, stretch, rotate or add effects to
ProductMark. - Don't use
AppGlyphas a stand-in logo for a product that has a mark. - Don't replace the field with a raster or your own gradient.
Related
Lab
https://docs.nasaqui.com/?path=/docs/components-brand-product-artwork--docs
BrandingProvider
Applies a tenant's brand colours at runtime from data (an org's settings, a white-label customer) over the active brand manifest, with readable on-brand text, a derived dark step and the tenant logo and name shared through useBranding.
ProductMark
The official cube-lattice mark of a Nasaq brand, drawn from its MarkSpec, and ProductLogo (mark plus typeset name).