Text
Typography roles (display to code) as one polymorphic component, plus the Kbd keyboard-key chip.
Code
import { Text } from "@fadymondy/nasaq/web";export function Intro() { return ( <> <Text variant="eyebrow">Overview</Text> <Text variant="h1">One product language.</Text> <Text variant="body">Every surface, in English and Arabic.</Text> </> );}Typography · stable
Live examples and controls: Text in the lab.
Install
npx shadcn@latest add https://docs.nasaqui.com/r/text.jsonOne component for every typographic role in Nasaq. variant picks the role (size, line height, weight,
colour); as picks the element. Latin and Arabic metrics resolve from the nearest lang, so the same
role is correct in both scripts. Kbd renders a keyboard key such as ⌘ K.
When to use
- Headings, body copy, labels, captions and inline code, instead of hand-picking
text-*classes. - Showing shortcuts:
Kbd.
When not to use
- Formatted numbers, currency, percent: use
NuminsideText. - Form labels tied to a control: use
FieldLabelfrom Field. - Isolating LTR runs inside Arabic: use
Ltr/Bdifrom icon.
Import
import { Text, Kbd, type TextRole, type TextProps } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"Quick start
import { Text } from "@fadymondy/nasaq/web";
export function Intro() {
return (
<>
<Text variant="eyebrow">Overview</Text>
<Text variant="h1">One product language.</Text>
<Text variant="body">Every surface, in English and Arabic.</Text>
</>
);
}Anatomy
Text data-slot="text" (element from `as`, else the variant's default)
Kbd data-slot="kbd" (<kbd dir="ltr">)API
Text
Text<E extends ElementType = "span">(props: TextProps<E>): JSX.Element
type TextProps<E extends ElementType = "span"> = { variant?: TextRole; as?: E } & Omit<ComponentProps<E>, "as">| Prop | Type | Default | Description |
|---|---|---|---|
variant? | TextRole | "body" | The typography role. |
as? | ElementType | the variant's default element | Element or component to render. Props are typed from it. |
className? | string | none | Merged after the role classes. |
| any element prop | from as | none | Forwarded (id, lang, dir, onClick, ...). |
TextRole
"display" | "h1" | "h2" | "h3" | "body" | "body-sm" | "label" | "caption" | "eyebrow" | "code"
| Role | Default element | Classes | Use |
|---|---|---|---|
display | h1 | text-display text-foreground | Hero and landing headline. |
h1 | h1 | text-h1 text-foreground | Page title. |
h2 | h2 | text-h2 text-foreground | Section title. |
h3 | h3 | text-h3 text-foreground | Sub-section title. |
body | p | text-body text-nq-fg-body | Paragraphs. |
body-sm | p | text-body-sm text-nq-fg-body | Dense UI copy. |
label | span | text-label text-foreground | Control and row labels. |
caption | span | text-caption text-muted-foreground | Hints, metadata. |
eyebrow | span | eyebrow | Small uppercase overline (Latin only; Arabic has no case or tracking). |
code | code | font-mono text-code | Inline code. |
Kbd
ComponentProps<"kbd">. Renders a 20px-high chip with dir="ltr", font-mono, text-[11px].
| Prop | Type | Default | Description |
|---|---|---|---|
aria-label? | string | none | Names a glyph key (⌘ → "Command"). When set, the chip gets role="img" so the name is announced. |
className? | string | none | Merged onto the chip. |
any <kbd> prop | none | Forwarded. dir can be overridden because props spread last. |
Examples
Semantic element differs from visual role
import { Text } from "@fadymondy/nasaq/web";
export function SectionTitle() {
return (
<Text as="h2" variant="h3">
Billing
</Text>
);
}Shortcut hint
import { Kbd, Text } from "@fadymondy/nasaq/web";
export function Hint() {
return (
<Text variant="body-sm">
Open the command menu with <Kbd>⌘</Kbd> <Kbd>K</Kbd>
</Text>
);
}Arabic copy with an LTR shortcut and figure
import { Kbd, Ltr, Num, Text } from "@fadymondy/nasaq/web";
export function ArabicHint() {
return (
<div dir="rtl" lang="ar" className="flex max-w-md flex-col gap-2">
<Text variant="h2">لوحة الأوامر</Text>
<Text variant="body-sm">
افتح القائمة بالضغط على <Kbd>Ctrl</Kbd> + <Kbd>K</Kbd>، أو استخدم الرمز <Ltr>nq-cmd</Ltr>.
</Text>
<Text variant="caption">
لديك <Num value={1284} /> عنصرًا.
</Text>
</div>
);
}Every role
import { Text, type TextRole } from "@fadymondy/nasaq/web";
const ROLES: TextRole[] = ["display", "h1", "h2", "h3", "body", "body-sm", "label", "caption", "eyebrow", "code"];
export function Roles() {
return (
<div className="flex flex-col gap-4">
{ROLES.map((role) => (
<Text key={role} variant={role} as="div">
{role}: One product language.
</Text>
))}
</div>
);
}Accessibility
Textadds no ARIA. Chooseasfor document structure:displayandh1default to<h1>, so useas="h2"(or another element) when a page already has anh1, and keep heading levels in order.Kbdrenders a native<kbd>, which screen readers read as text. For glyph keys passaria-label(<Kbd aria-label="Command">⌘</Kbd>); localise it.- Contrast:
bodyusestext-nq-fg-body,captionusestext-muted-foreground. Do not restyle them lighter.
RTL & i18n
- Latin and Arabic type metrics resolve from the nearest
lang; setlang="ar"on the Arabic container (NasaqProviderdoes this from the locale). eyebrowis uppercase mono at 11px for Latin. Arabic has no case, so it is set without tracking at 13px.Kbdis alwaysdir="ltr"soCtrl+Kkeeps its order inside Arabic text.- For an LTR run in Arabic prose (codes, emails) use
Ltr; for user-supplied names useBdi(icon). For figures useNum.
Styling & tokens
- Roles come from the typography tokens (
text-display,text-h1...text-code,eyebrow) and colour tokenstext-foreground,text-nq-fg-body,text-muted-foreground. Kbd:border-border,bg-card,text-muted-foreground,rounded-[4px].- Target
[data-slot=text]and[data-slot=kbd]. Extend withclassName; do not override colours with raw hex.
Do / Don't
- Do pick the role by meaning, and the element by document structure.
- Do keep sizes at or above the 12px floor; use the roles rather than ad-hoc sizes.
- Don't use
eyebrowfor Arabic copy that needs emphasis: there is no uppercase to lean on. - Don't put more than one
h1on a page.
Related
- Num · Icon, Ltr, Bdi · Field
Lab
https://docs.nasaqui.com/?path=/docs/foundations-typography--docs
SectionHeader
Title row of a page section: heading, one line of context and an optional action at the inline end. Separates sections without bordered cards.
Text effects
Small motion effects for words on marketing and product pages, a flipping phrase, a shimmer, a marquee, a word by word reveal and handwritten notes and marks. All of them hold still under reduced motion and never split Arabic into letters.