@spatika/react 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/composites/AccentRule.d.ts +6 -0
- package/dist/composites/AccentRule.d.ts.map +1 -0
- package/dist/composites/AccentRule.js +6 -0
- package/dist/composites/AvailabilityBadge.d.ts +9 -0
- package/dist/composites/AvailabilityBadge.d.ts.map +1 -0
- package/dist/composites/AvailabilityBadge.js +9 -0
- package/dist/composites/CareerCard.d.ts +20 -0
- package/dist/composites/CareerCard.d.ts.map +1 -0
- package/dist/composites/CareerCard.js +17 -0
- package/dist/composites/ContactLink.d.ts +15 -0
- package/dist/composites/ContactLink.d.ts.map +1 -0
- package/dist/composites/ContactLink.js +8 -0
- package/dist/composites/DisplayHeading.d.ts +9 -0
- package/dist/composites/DisplayHeading.d.ts.map +1 -0
- package/dist/composites/DisplayHeading.js +6 -0
- package/dist/composites/FloatChip.d.ts +15 -0
- package/dist/composites/FloatChip.d.ts.map +1 -0
- package/dist/composites/FloatChip.js +7 -0
- package/dist/composites/GradientText.d.ts +11 -0
- package/dist/composites/GradientText.d.ts.map +1 -0
- package/dist/composites/GradientText.js +6 -0
- package/dist/composites/IconTile.d.ts +10 -0
- package/dist/composites/IconTile.d.ts.map +1 -0
- package/dist/composites/IconTile.js +7 -0
- package/dist/composites/MetaChip.d.ts +9 -0
- package/dist/composites/MetaChip.d.ts.map +1 -0
- package/dist/composites/MetaChip.js +6 -0
- package/dist/composites/PresenceDot.d.ts +10 -0
- package/dist/composites/PresenceDot.d.ts.map +1 -0
- package/dist/composites/PresenceDot.js +10 -0
- package/dist/composites/ProjectCard.d.ts +12 -0
- package/dist/composites/ProjectCard.d.ts.map +1 -0
- package/dist/composites/ProjectCard.js +9 -0
- package/dist/composites/SectionHeading.d.ts +16 -0
- package/dist/composites/SectionHeading.d.ts.map +1 -0
- package/dist/composites/SectionHeading.js +12 -0
- package/dist/composites/SiteFooter.d.ts +18 -0
- package/dist/composites/SiteFooter.d.ts.map +1 -0
- package/dist/composites/SiteFooter.js +15 -0
- package/dist/composites/SiteNav.d.ts +20 -0
- package/dist/composites/SiteNav.d.ts.map +1 -0
- package/dist/composites/SiteNav.js +40 -0
- package/dist/composites/StatCard.d.ts +6 -1
- package/dist/composites/StatCard.d.ts.map +1 -1
- package/dist/composites/StatCard.js +4 -1
- package/dist/composites/StatusDot.d.ts +1 -1
- package/dist/composites/Tag.d.ts +11 -0
- package/dist/composites/Tag.d.ts.map +1 -0
- package/dist/composites/Tag.js +33 -0
- package/dist/composites/Wordmark.d.ts +19 -0
- package/dist/composites/Wordmark.d.ts.map +1 -0
- package/dist/composites/Wordmark.js +15 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -0
- package/dist/primitives/Button.d.ts +4 -4
- package/dist/primitives/Button.d.ts.map +1 -1
- package/dist/primitives/Button.js +2 -0
- package/package.json +4 -3
- package/src/composites/AccentRule.tsx +12 -0
- package/src/composites/AvailabilityBadge.tsx +32 -0
- package/src/composites/CareerCard.tsx +111 -0
- package/src/composites/ContactLink.tsx +66 -0
- package/src/composites/DisplayHeading.tsx +27 -0
- package/src/composites/FloatChip.tsx +63 -0
- package/src/composites/GradientText.tsx +31 -0
- package/src/composites/IconTile.tsx +33 -0
- package/src/composites/MetaChip.tsx +24 -0
- package/src/composites/PresenceDot.tsx +42 -0
- package/src/composites/ProjectCard.tsx +65 -0
- package/src/composites/SectionHeading.tsx +61 -0
- package/src/composites/SiteFooter.tsx +79 -0
- package/src/composites/SiteNav.tsx +140 -0
- package/src/composites/StatCard.tsx +32 -1
- package/src/composites/Tag.tsx +50 -0
- package/src/composites/Wordmark.tsx +46 -0
- package/src/composites/marketing.test.tsx +188 -0
- package/src/index.ts +23 -0
- package/src/primitives/Button.tsx +3 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
import { GradientText } from "./GradientText";
|
|
4
|
+
const sizeClass = {
|
|
5
|
+
sm: "text-[14px] font-semibold tracking-tight",
|
|
6
|
+
md: "text-xl font-[900] tracking-tight",
|
|
7
|
+
lg: "text-[clamp(1.6rem,3.6vw,2.1rem)] font-[800] tracking-tight",
|
|
8
|
+
display: "text-[clamp(2.5rem,8vw,5.5rem)] font-[900] leading-[0.95] tracking-tight",
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Marketing wordmark: solid name, optional gradient accent, optional primary mark.
|
|
12
|
+
*/
|
|
13
|
+
export function Wordmark({ name, accent, mark, rest, size = "md", as: Tag = "span", className, }) {
|
|
14
|
+
return (_jsxs(Tag, { "data-slot": "wordmark", className: cn(sizeClass[size], className), children: [_jsx("span", { className: "text-foreground", children: name }), accent ? _jsx(GradientText, { children: accent }) : null, mark ? _jsx("span", { className: "text-primary", children: mark }) : null, rest ? _jsx("span", { className: "text-foreground", children: rest }) : null] }));
|
|
15
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -52,6 +52,22 @@ export { PageStickyHeader, PageHeaderBadge, type PageStickyHeaderProps } from ".
|
|
|
52
52
|
export { PageShell, type PageShellProps } from "./composites/PageShell";
|
|
53
53
|
export { SectionPanel, type SectionPanelProps } from "./composites/SectionPanel";
|
|
54
54
|
export { Chip, chipVariants, type ChipProps } from "./composites/Chip";
|
|
55
|
+
export { Tag, tagVariants, type TagProps } from "./composites/Tag";
|
|
56
|
+
export { SectionHeading, type SectionHeadingProps } from "./composites/SectionHeading";
|
|
57
|
+
export { SiteNav, type SiteNavLink, type SiteNavProps } from "./composites/SiteNav";
|
|
58
|
+
export { SiteFooter, type SiteFooterProps } from "./composites/SiteFooter";
|
|
59
|
+
export { GradientText, type GradientTextProps } from "./composites/GradientText";
|
|
60
|
+
export { AccentRule, type AccentRuleProps } from "./composites/AccentRule";
|
|
61
|
+
export { Wordmark, type WordmarkProps } from "./composites/Wordmark";
|
|
62
|
+
export { DisplayHeading, type DisplayHeadingProps } from "./composites/DisplayHeading";
|
|
63
|
+
export { PresenceDot, type PresenceDotProps } from "./composites/PresenceDot";
|
|
64
|
+
export { AvailabilityBadge, type AvailabilityBadgeProps } from "./composites/AvailabilityBadge";
|
|
65
|
+
export { FloatChip, type FloatChipProps } from "./composites/FloatChip";
|
|
66
|
+
export { MetaChip, type MetaChipProps } from "./composites/MetaChip";
|
|
67
|
+
export { IconTile, type IconTileProps } from "./composites/IconTile";
|
|
68
|
+
export { ContactLink, type ContactLinkProps } from "./composites/ContactLink";
|
|
69
|
+
export { CareerCard, CareerTimeline, type CareerCardProps, type CareerTimelineProps, } from "./composites/CareerCard";
|
|
70
|
+
export { ProjectCard, type ProjectCardProps } from "./composites/ProjectCard";
|
|
55
71
|
export { ChipGroup, isOptionSelected, toggleOptionValue, type ChipGroupProps, type ChipOption, } from "./composites/ChipGroup";
|
|
56
72
|
export { EmptyState, type EmptyStateProps } from "./composites/EmptyState";
|
|
57
73
|
export { FormField, type FormFieldProps } from "./composites/FormField";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
/**
|
|
2
3
|
* @spatika/react — Spatika React package
|
|
3
4
|
*
|
|
@@ -52,6 +53,22 @@ export { PageStickyHeader, PageHeaderBadge } from "./composites/PageStickyHeader
|
|
|
52
53
|
export { PageShell } from "./composites/PageShell";
|
|
53
54
|
export { SectionPanel } from "./composites/SectionPanel";
|
|
54
55
|
export { Chip, chipVariants } from "./composites/Chip";
|
|
56
|
+
export { Tag, tagVariants } from "./composites/Tag";
|
|
57
|
+
export { SectionHeading } from "./composites/SectionHeading";
|
|
58
|
+
export { SiteNav } from "./composites/SiteNav";
|
|
59
|
+
export { SiteFooter } from "./composites/SiteFooter";
|
|
60
|
+
export { GradientText } from "./composites/GradientText";
|
|
61
|
+
export { AccentRule } from "./composites/AccentRule";
|
|
62
|
+
export { Wordmark } from "./composites/Wordmark";
|
|
63
|
+
export { DisplayHeading } from "./composites/DisplayHeading";
|
|
64
|
+
export { PresenceDot } from "./composites/PresenceDot";
|
|
65
|
+
export { AvailabilityBadge } from "./composites/AvailabilityBadge";
|
|
66
|
+
export { FloatChip } from "./composites/FloatChip";
|
|
67
|
+
export { MetaChip } from "./composites/MetaChip";
|
|
68
|
+
export { IconTile } from "./composites/IconTile";
|
|
69
|
+
export { ContactLink } from "./composites/ContactLink";
|
|
70
|
+
export { CareerCard, CareerTimeline, } from "./composites/CareerCard";
|
|
71
|
+
export { ProjectCard } from "./composites/ProjectCard";
|
|
55
72
|
export { ChipGroup, isOptionSelected, toggleOptionValue, } from "./composites/ChipGroup";
|
|
56
73
|
export { EmptyState } from "./composites/EmptyState";
|
|
57
74
|
export { FormField } from "./composites/FormField";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type VariantProps } from "class-variance-authority";
|
|
3
3
|
declare const buttonVariants: (props?: ({
|
|
4
|
-
variant?: "default" | "link" | "destructive" | "outline" | "secondary" | "ghost" | "glass" | null | undefined;
|
|
5
|
-
size?: "default" | "icon" | "touch" | "sm" | "lg" | "icon-touch" | null | undefined;
|
|
4
|
+
variant?: "default" | "link" | "destructive" | "outline" | "secondary" | "ghost" | "glass" | "gradient" | null | undefined;
|
|
5
|
+
size?: "default" | "icon" | "touch" | "sm" | "lg" | "xl" | "icon-touch" | null | undefined;
|
|
6
6
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
7
|
declare const Button: React.ForwardRefExoticComponent<Omit<React.ClassAttributes<HTMLButtonElement> & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<(props?: ({
|
|
8
|
-
variant?: "default" | "link" | "destructive" | "outline" | "secondary" | "ghost" | "glass" | null | undefined;
|
|
9
|
-
size?: "default" | "icon" | "touch" | "sm" | "lg" | "icon-touch" | null | undefined;
|
|
8
|
+
variant?: "default" | "link" | "destructive" | "outline" | "secondary" | "ghost" | "glass" | "gradient" | null | undefined;
|
|
9
|
+
size?: "default" | "icon" | "touch" | "sm" | "lg" | "xl" | "icon-touch" | null | undefined;
|
|
10
10
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string> & {
|
|
11
11
|
asChild?: boolean;
|
|
12
12
|
}, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/primitives/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,QAAA,MAAM,cAAc;;;
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/primitives/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,QAAA,MAAM,cAAc;;;8EAkCnB,CAAC;AAEF,QAAA,MAAM,MAAM;;;;cAII,OAAO;mDAYrB,CAAC;AAGH,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -13,11 +13,13 @@ const buttonVariants = cva("inline-flex items-center justify-center gap-2 whites
|
|
|
13
13
|
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
14
14
|
link: "text-primary underline-offset-4 hover:underline",
|
|
15
15
|
glass: "glass border-border/50 text-foreground hover:border-primary/30 hover:text-primary",
|
|
16
|
+
gradient: "rounded-full bg-gradient-to-r from-primary to-[color-mix(in_srgb,var(--primary)_72%,var(--chart-2))] text-primary-foreground shadow-[0_10px_32px_color-mix(in_srgb,var(--primary)_38%,transparent)] hover:brightness-105 hover:-translate-y-0.5 hover:shadow-[0_14px_40px_color-mix(in_srgb,var(--chart-3)_22%,transparent)]",
|
|
16
17
|
},
|
|
17
18
|
size: {
|
|
18
19
|
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
19
20
|
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
20
21
|
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
22
|
+
xl: "h-auto rounded-full px-8 py-4 text-[15px] font-bold has-[>svg]:px-7",
|
|
21
23
|
/** Mobile-first ≥44px touch target */
|
|
22
24
|
touch: "min-h-11 h-11 rounded-md px-5 has-[>svg]:px-4",
|
|
23
25
|
icon: "size-9 rounded-md",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spatika/react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Spatika React primitives and composites",
|
|
6
6
|
"type": "module",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
13
|
"types": "./dist/index.d.ts",
|
|
14
|
-
"import": "./dist/index.js"
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"default": "./dist/index.js"
|
|
15
16
|
},
|
|
16
17
|
"./package.json": "./package.json"
|
|
17
18
|
},
|
|
@@ -34,7 +35,7 @@
|
|
|
34
35
|
"react-dom": "^18.2.0 || ^19.0.0"
|
|
35
36
|
},
|
|
36
37
|
"dependencies": {
|
|
37
|
-
"@spatika/tokens": "1.
|
|
38
|
+
"@spatika/tokens": "1.1.0",
|
|
38
39
|
"class-variance-authority": "^0.7.1",
|
|
39
40
|
"clsx": "^2.1.1",
|
|
40
41
|
"cmdk": "^1.1.1",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { cn } from "../lib/cn";
|
|
2
|
+
|
|
3
|
+
export type AccentRuleProps = {
|
|
4
|
+
className?: string;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
/** Short 4px marketing accent bar used under section titles. */
|
|
8
|
+
export function AccentRule({ className }: AccentRuleProps) {
|
|
9
|
+
return (
|
|
10
|
+
<div data-slot="accent-rule" className={cn("spk-hr-accent", className)} role="presentation" />
|
|
11
|
+
);
|
|
12
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
import { PresenceDot } from "./PresenceDot";
|
|
4
|
+
|
|
5
|
+
export type AvailabilityBadgeProps = {
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
tone?: "primary" | "success";
|
|
8
|
+
className?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/** Pill badge with a live pip — “available for work” treatment. */
|
|
12
|
+
export function AvailabilityBadge({
|
|
13
|
+
children,
|
|
14
|
+
tone = "primary",
|
|
15
|
+
className,
|
|
16
|
+
}: AvailabilityBadgeProps) {
|
|
17
|
+
return (
|
|
18
|
+
<span
|
|
19
|
+
data-slot="availability-badge"
|
|
20
|
+
className={cn(
|
|
21
|
+
"inline-flex items-center gap-2.5 rounded-full border px-4 py-2 text-[12px] font-extrabold uppercase tracking-[0.15em] shadow-sm",
|
|
22
|
+
tone === "success"
|
|
23
|
+
? "border-[color-mix(in_srgb,var(--accent-info)_22%,transparent)] bg-[var(--accent-info-bg)] text-[var(--accent-info)]"
|
|
24
|
+
: "border-primary/20 bg-primary/10 text-primary",
|
|
25
|
+
className,
|
|
26
|
+
)}
|
|
27
|
+
>
|
|
28
|
+
<PresenceDot tone={tone} />
|
|
29
|
+
{children}
|
|
30
|
+
</span>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
import { Badge } from "../primitives/Badge";
|
|
4
|
+
import { Card } from "./Card";
|
|
5
|
+
import { Tag } from "./Tag";
|
|
6
|
+
|
|
7
|
+
export type CareerCardProps = {
|
|
8
|
+
role: ReactNode;
|
|
9
|
+
company: ReactNode;
|
|
10
|
+
location?: ReactNode;
|
|
11
|
+
period?: ReactNode;
|
|
12
|
+
current?: boolean;
|
|
13
|
+
bullets?: ReactNode[];
|
|
14
|
+
tags?: string[];
|
|
15
|
+
className?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type CareerTimelineProps = {
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
className?: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/** Vertical career rail with a hairline and slot for CareerCard rows. */
|
|
24
|
+
export function CareerTimeline({ children, className }: CareerTimelineProps) {
|
|
25
|
+
return (
|
|
26
|
+
<div data-slot="career-timeline" className={cn("relative", className)}>
|
|
27
|
+
<div className="absolute top-2 bottom-2 left-[5px] hidden w-px bg-border sm:block" aria-hidden />
|
|
28
|
+
<div className="space-y-3">{children}</div>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Resume / experience card: role, company, period pill, bullets, tech tags. */
|
|
34
|
+
export function CareerCard({
|
|
35
|
+
role,
|
|
36
|
+
company,
|
|
37
|
+
location,
|
|
38
|
+
period,
|
|
39
|
+
current = false,
|
|
40
|
+
bullets = [],
|
|
41
|
+
tags = [],
|
|
42
|
+
className,
|
|
43
|
+
}: CareerCardProps) {
|
|
44
|
+
return (
|
|
45
|
+
<article data-slot="career-card" className={cn("relative sm:pl-8", className)}>
|
|
46
|
+
<div
|
|
47
|
+
className={cn(
|
|
48
|
+
"absolute top-4 left-0 hidden h-2.5 w-2.5 rounded-full border-2 sm:block",
|
|
49
|
+
current ? "border-primary bg-primary" : "border-border bg-background",
|
|
50
|
+
)}
|
|
51
|
+
aria-hidden
|
|
52
|
+
/>
|
|
53
|
+
<Card
|
|
54
|
+
variant="panel"
|
|
55
|
+
padding="md"
|
|
56
|
+
className={
|
|
57
|
+
current
|
|
58
|
+
? "border-primary/25 bg-gradient-to-br from-[var(--background)] to-primary/[0.04] shadow-[0_8px_28px_color-mix(in_srgb,var(--primary)_7%,transparent)]"
|
|
59
|
+
: "hover:border-primary/20"
|
|
60
|
+
}
|
|
61
|
+
>
|
|
62
|
+
<div className="mb-2.5 flex flex-wrap items-start justify-between gap-2">
|
|
63
|
+
<div className="min-w-0">
|
|
64
|
+
<h3 className="text-[15px] font-[900] leading-snug text-foreground sm:text-[16px]">{role}</h3>
|
|
65
|
+
<p className="mt-0.5 text-[13px] font-bold text-primary">
|
|
66
|
+
{company}
|
|
67
|
+
{location ? (
|
|
68
|
+
<span className="font-semibold text-muted-foreground"> · {location}</span>
|
|
69
|
+
) : null}
|
|
70
|
+
</p>
|
|
71
|
+
</div>
|
|
72
|
+
{period ? (
|
|
73
|
+
<Badge
|
|
74
|
+
variant={current ? "default" : "secondary"}
|
|
75
|
+
className={
|
|
76
|
+
current
|
|
77
|
+
? "rounded-full border-primary bg-primary px-2.5 py-1 text-[11px] font-black text-primary-foreground"
|
|
78
|
+
: "rounded-full px-2.5 py-1 text-[11px] font-black text-muted-foreground"
|
|
79
|
+
}
|
|
80
|
+
>
|
|
81
|
+
{current ? <span className="h-1.5 w-1.5 animate-pulse rounded-full bg-primary-foreground" /> : null}
|
|
82
|
+
{period}
|
|
83
|
+
</Badge>
|
|
84
|
+
) : null}
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
{bullets.length > 0 ? (
|
|
88
|
+
<ul className="mb-3 space-y-1.5">
|
|
89
|
+
{bullets.map((bullet, index) => (
|
|
90
|
+
<li
|
|
91
|
+
key={index}
|
|
92
|
+
className="flex gap-2 text-[13px] leading-relaxed text-muted-foreground"
|
|
93
|
+
>
|
|
94
|
+
<span className="mt-[7px] h-1 w-1 shrink-0 rounded-full bg-primary/50" />
|
|
95
|
+
{bullet}
|
|
96
|
+
</li>
|
|
97
|
+
))}
|
|
98
|
+
</ul>
|
|
99
|
+
) : null}
|
|
100
|
+
|
|
101
|
+
{tags.length > 0 ? (
|
|
102
|
+
<div className="flex flex-wrap gap-1.5">
|
|
103
|
+
{tags.map((tag) => (
|
|
104
|
+
<Tag key={tag}>{tag}</Tag>
|
|
105
|
+
))}
|
|
106
|
+
</div>
|
|
107
|
+
) : null}
|
|
108
|
+
</Card>
|
|
109
|
+
</article>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
import { Card } from "./Card";
|
|
4
|
+
|
|
5
|
+
export type ContactLinkProps = {
|
|
6
|
+
href: string;
|
|
7
|
+
name: ReactNode;
|
|
8
|
+
label?: ReactNode;
|
|
9
|
+
icon: ReactNode;
|
|
10
|
+
iconBg?: string;
|
|
11
|
+
iconColor?: string;
|
|
12
|
+
className?: string;
|
|
13
|
+
target?: string;
|
|
14
|
+
rel?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/** Contact / social row: tinted icon well, name, handle, trailing arrow. */
|
|
18
|
+
export function ContactLink({
|
|
19
|
+
href,
|
|
20
|
+
name,
|
|
21
|
+
label,
|
|
22
|
+
icon,
|
|
23
|
+
iconBg,
|
|
24
|
+
iconColor,
|
|
25
|
+
className,
|
|
26
|
+
target,
|
|
27
|
+
rel,
|
|
28
|
+
}: ContactLinkProps) {
|
|
29
|
+
const external = href.startsWith("http");
|
|
30
|
+
return (
|
|
31
|
+
<a
|
|
32
|
+
data-slot="contact-link"
|
|
33
|
+
href={href}
|
|
34
|
+
target={target ?? (external ? "_blank" : undefined)}
|
|
35
|
+
rel={rel ?? (external ? "noopener noreferrer" : undefined)}
|
|
36
|
+
className={cn("group block rounded-2xl", className)}
|
|
37
|
+
>
|
|
38
|
+
<Card
|
|
39
|
+
variant="panel"
|
|
40
|
+
padding="md"
|
|
41
|
+
className="flex items-center gap-4 p-4 group-hover:border-primary/25 group-hover:shadow-[0_8px_28px_color-mix(in_srgb,var(--chart-3)_18%,transparent)]"
|
|
42
|
+
>
|
|
43
|
+
<div
|
|
44
|
+
className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl transition-transform duration-200 group-hover:scale-110"
|
|
45
|
+
style={{ background: iconBg, color: iconColor }}
|
|
46
|
+
>
|
|
47
|
+
{icon}
|
|
48
|
+
</div>
|
|
49
|
+
<div className="min-w-0 flex-1">
|
|
50
|
+
<p className="text-[13px] font-semibold text-foreground">{name}</p>
|
|
51
|
+
{label ? <p className="truncate text-[12px] text-muted-foreground">{label}</p> : null}
|
|
52
|
+
</div>
|
|
53
|
+
<svg
|
|
54
|
+
className="h-4 w-4 shrink-0 text-muted-foreground transition-colors group-hover:text-primary"
|
|
55
|
+
fill="none"
|
|
56
|
+
viewBox="0 0 24 24"
|
|
57
|
+
stroke="currentColor"
|
|
58
|
+
strokeWidth={2}
|
|
59
|
+
aria-hidden
|
|
60
|
+
>
|
|
61
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M4.5 12h15m0 0l-6.75-6.75M19.5 12l-6.75 6.75" />
|
|
62
|
+
</svg>
|
|
63
|
+
</Card>
|
|
64
|
+
</a>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
|
|
4
|
+
export type DisplayHeadingProps = {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
as?: "h1" | "h2";
|
|
7
|
+
className?: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/** Oversized marketing hero title. Compose with Wordmark / GradientText. */
|
|
11
|
+
export function DisplayHeading({
|
|
12
|
+
children,
|
|
13
|
+
as: Tag = "h1",
|
|
14
|
+
className,
|
|
15
|
+
}: DisplayHeadingProps) {
|
|
16
|
+
return (
|
|
17
|
+
<Tag
|
|
18
|
+
data-slot="display-heading"
|
|
19
|
+
className={cn(
|
|
20
|
+
"text-[clamp(2.5rem,8vw,5.5rem)] font-[900] leading-[0.95] tracking-tight",
|
|
21
|
+
className,
|
|
22
|
+
)}
|
|
23
|
+
>
|
|
24
|
+
{children}
|
|
25
|
+
</Tag>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
import { PresenceDot } from "./PresenceDot";
|
|
4
|
+
|
|
5
|
+
export type FloatChipProps = {
|
|
6
|
+
icon?: ReactNode;
|
|
7
|
+
title?: ReactNode;
|
|
8
|
+
subtitle?: ReactNode;
|
|
9
|
+
/** Compact live row (green pip + uppercase label) instead of title/subtitle. */
|
|
10
|
+
live?: boolean;
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
/** CSS float animation. */
|
|
13
|
+
float?: boolean;
|
|
14
|
+
className?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/** Frosted floating fact chip used around a marketing hero portrait. */
|
|
18
|
+
export function FloatChip({
|
|
19
|
+
icon,
|
|
20
|
+
title,
|
|
21
|
+
subtitle,
|
|
22
|
+
live = false,
|
|
23
|
+
children,
|
|
24
|
+
float = false,
|
|
25
|
+
className,
|
|
26
|
+
}: FloatChipProps) {
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
data-slot="float-chip"
|
|
30
|
+
className={cn(
|
|
31
|
+
"inline-flex items-center gap-2.5 rounded-2xl border border-border bg-[color-mix(in_srgb,var(--background)_90%,transparent)] px-3 py-2.5 shadow-[0_12px_32px_rgba(0,0,0,0.12)] backdrop-blur-md",
|
|
32
|
+
float && "spk-float",
|
|
33
|
+
className,
|
|
34
|
+
)}
|
|
35
|
+
>
|
|
36
|
+
{icon ? (
|
|
37
|
+
<div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-base">
|
|
38
|
+
{icon}
|
|
39
|
+
</div>
|
|
40
|
+
) : null}
|
|
41
|
+
{live ? (
|
|
42
|
+
<div className="flex items-center gap-2">
|
|
43
|
+
<PresenceDot tone="success" />
|
|
44
|
+
<p className="text-[11px] font-black uppercase leading-none tracking-widest text-[var(--accent-info)]">
|
|
45
|
+
{children ?? title}
|
|
46
|
+
</p>
|
|
47
|
+
</div>
|
|
48
|
+
) : (
|
|
49
|
+
<div>
|
|
50
|
+
{title ? (
|
|
51
|
+
<p className="text-[12px] font-black uppercase leading-none tracking-wide text-foreground">
|
|
52
|
+
{title}
|
|
53
|
+
</p>
|
|
54
|
+
) : null}
|
|
55
|
+
{subtitle ? (
|
|
56
|
+
<p className="mt-1 text-[10px] font-bold text-muted-foreground">{subtitle}</p>
|
|
57
|
+
) : null}
|
|
58
|
+
{children}
|
|
59
|
+
</div>
|
|
60
|
+
)}
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
|
|
4
|
+
export type GradientTextProps = {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
/** `static` clips a 3-stop theme gradient; `flow` animates it. */
|
|
7
|
+
variant?: "static" | "flow";
|
|
8
|
+
className?: string;
|
|
9
|
+
as?: "span" | "em" | "strong";
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/** Theme-colored gradient type for wordmarks and display names. */
|
|
13
|
+
export function GradientText({
|
|
14
|
+
children,
|
|
15
|
+
variant = "static",
|
|
16
|
+
className,
|
|
17
|
+
as: Tag = "span",
|
|
18
|
+
}: GradientTextProps) {
|
|
19
|
+
return (
|
|
20
|
+
<Tag
|
|
21
|
+
data-slot="gradient-text"
|
|
22
|
+
data-variant={variant}
|
|
23
|
+
className={cn(
|
|
24
|
+
variant === "flow" ? "spk-gradient-text" : "spk-gradient-text-static",
|
|
25
|
+
className,
|
|
26
|
+
)}
|
|
27
|
+
>
|
|
28
|
+
{children}
|
|
29
|
+
</Tag>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
import { Card } from "./Card";
|
|
4
|
+
|
|
5
|
+
export type IconTileProps = {
|
|
6
|
+
icon: ReactNode;
|
|
7
|
+
title: ReactNode;
|
|
8
|
+
description?: ReactNode;
|
|
9
|
+
className?: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/** Horizontal domain / feature tile: icon well + italic title + caption. */
|
|
13
|
+
export function IconTile({ icon, title, description, className }: IconTileProps) {
|
|
14
|
+
return (
|
|
15
|
+
<div data-slot="icon-tile">
|
|
16
|
+
<Card
|
|
17
|
+
variant="panel"
|
|
18
|
+
padding="md"
|
|
19
|
+
className={cn("group flex items-center gap-5 p-5", className)}
|
|
20
|
+
>
|
|
21
|
+
<div className="flex h-14 w-14 shrink-0 items-center justify-center rounded-2xl border border-border bg-secondary text-3xl">
|
|
22
|
+
{icon}
|
|
23
|
+
</div>
|
|
24
|
+
<div className="min-w-0">
|
|
25
|
+
<p className="text-[16px] font-[900] italic text-foreground">{title}</p>
|
|
26
|
+
{description ? (
|
|
27
|
+
<p className="mt-0.5 text-[12px] font-bold text-muted-foreground">{description}</p>
|
|
28
|
+
) : null}
|
|
29
|
+
</div>
|
|
30
|
+
</Card>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
|
|
4
|
+
export type MetaChipProps = {
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/** Compact “powered by” chip: icon + label with a quiet ring. */
|
|
11
|
+
export function MetaChip({ icon, children, className }: MetaChipProps) {
|
|
12
|
+
return (
|
|
13
|
+
<span
|
|
14
|
+
data-slot="meta-chip"
|
|
15
|
+
className={cn(
|
|
16
|
+
"inline-flex items-center gap-1.5 rounded-lg bg-secondary px-2.5 py-1.5 text-[11px] font-medium text-muted-foreground ring-1 ring-border/80",
|
|
17
|
+
className,
|
|
18
|
+
)}
|
|
19
|
+
>
|
|
20
|
+
{icon ? <span className="inline-flex h-4 w-4 shrink-0 items-center justify-center opacity-90">{icon}</span> : null}
|
|
21
|
+
{children}
|
|
22
|
+
</span>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { cn } from "../lib/cn";
|
|
2
|
+
|
|
3
|
+
export type PresenceDotProps = {
|
|
4
|
+
tone?: "primary" | "success";
|
|
5
|
+
/** Dual-span scale ping. Defaults to true. */
|
|
6
|
+
ping?: boolean;
|
|
7
|
+
className?: string;
|
|
8
|
+
label?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const toneClass = {
|
|
12
|
+
primary: "bg-primary",
|
|
13
|
+
success: "bg-[var(--accent-info)]",
|
|
14
|
+
} as const;
|
|
15
|
+
|
|
16
|
+
/** Live status pip with optional ping halo (availability badges, hero chips). */
|
|
17
|
+
export function PresenceDot({
|
|
18
|
+
tone = "primary",
|
|
19
|
+
ping = true,
|
|
20
|
+
className,
|
|
21
|
+
label,
|
|
22
|
+
}: PresenceDotProps) {
|
|
23
|
+
return (
|
|
24
|
+
<span
|
|
25
|
+
data-slot="presence-dot"
|
|
26
|
+
role={label ? "img" : undefined}
|
|
27
|
+
aria-label={label}
|
|
28
|
+
className={cn("relative flex h-2 w-2", className)}
|
|
29
|
+
>
|
|
30
|
+
{ping ? (
|
|
31
|
+
<span
|
|
32
|
+
className={cn(
|
|
33
|
+
"absolute inline-flex h-full w-full animate-ping rounded-full opacity-75",
|
|
34
|
+
toneClass[tone],
|
|
35
|
+
)}
|
|
36
|
+
aria-hidden
|
|
37
|
+
/>
|
|
38
|
+
) : null}
|
|
39
|
+
<span className={cn("relative inline-flex h-2 w-2 rounded-full", toneClass[tone])} />
|
|
40
|
+
</span>
|
|
41
|
+
);
|
|
42
|
+
}
|