trc-ui 0.0.0-stage → 0.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/CHANGELOG.md +14 -0
- package/LICENSE +21 -0
- package/README.md +120 -2
- package/dist/index.cjs +737 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +300 -0
- package/dist/index.d.ts +300 -0
- package/dist/index.js +685 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +1 -0
- package/package.json +78 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/cx.ts","../src/components/typography.tsx","../src/components/pill.tsx","../src/utils/icons.tsx","../src/components/surfaces.tsx","../src/components/field.tsx","../src/components/toggle.tsx","../src/components/site-header.tsx","../src/hooks/use-modal.ts","../src/components/site-footer.tsx","../src/components/hero.tsx","../src/components/back-to-top.tsx"],"sourcesContent":["/** Joins CSS class names, skipping empty values. */\nexport function cx(...classes: (string | false | null | undefined)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n","import type { ComponentPropsWithoutRef, ElementType, ReactNode } from \"react\";\nimport { cx } from \"../utils/cx\";\n\n/**\n * Colors the words between asterisks with the accent: \"How it *works*\".\n * Without asterisks, `accentLast` colors the last words (titles coming from a CMS).\n */\nexport function AccentText({ text, accentLast = 0 }: { text: string; accentLast?: number }) {\n if (text.includes(\"*\")) {\n return (\n <>\n {text.split(\"*\").map((part, i) =>\n i % 2 === 1 ? (\n <span key={i} className=\"trc-accent\">\n {part}\n </span>\n ) : (\n part\n ),\n )}\n </>\n );\n }\n const words = text.split(\" \");\n if (!accentLast || words.length < 2) return <>{text}</>;\n const n = Math.min(accentLast, words.length - 1);\n return (\n <>\n {words.slice(0, -n).join(\" \")} <span className=\"trc-accent\">{words.slice(-n).join(\" \")}</span>\n </>\n );\n}\n\n/** Plain text of a marked-up title, for attributes (`alt`, `title`, metadata). */\nexport const plainText = (text: string) => text.replaceAll(\"*\", \"\");\n\nexport type HeadingSize = \"display\" | \"xl\" | \"lg\" | \"md\" | \"sm\";\n\nexport type HeadingProps = Omit<ComponentPropsWithoutRef<\"h2\">, \"children\"> & {\n /** Rendered tag; the visual size is set separately with `size`. */\n as?: \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | \"span\";\n size?: HeadingSize;\n /** When `children` is a string without asterisks, number of trailing words in the accent color. */\n accentLast?: number;\n children: ReactNode;\n};\n\n/** Thin Montserrat 400 heading; a string may contain an *accent word* between asterisks. */\nexport function Heading({ as: Tag = \"h2\", size = \"xl\", accentLast, className, children, ...props }: HeadingProps) {\n return (\n <Tag className={cx(\"trc-display\", `trc-heading--${size}`, className)} {...props}>\n {typeof children === \"string\" ? <AccentText text={children} accentLast={accentLast} /> : children}\n </Tag>\n );\n}\n\nexport type TextProps<C extends ElementType = \"p\"> = {\n as?: C;\n size?: \"lg\" | \"md\" | \"sm\";\n tone?: \"default\" | \"muted\" | \"subtle\";\n} & Omit<ComponentPropsWithoutRef<C>, \"as\" | \"size\">;\n\n/** Body text; `tone=\"muted\"` (default) so that it does not compete with headings. */\nexport function Text<C extends ElementType = \"p\">({ as, size = \"md\", tone = \"muted\", className, ...props }: TextProps<C>) {\n const Tag: ElementType = as ?? \"p\";\n return <Tag className={cx(\"trc-text\", `trc-text--${size}`, `trc-text--${tone}`, className)} {...props} />;\n}\n\n/** Large thin number in the accent color (\"01\", \"02\"…), reserved for steps in a real order. */\nexport function StepNumber({ n, size = \"md\", className }: { n: number; size?: \"md\" | \"sm\"; className?: string }) {\n return (\n <span aria-hidden className={cx(\"trc-step-number\", size === \"sm\" && \"trc-step-number--sm\", className)}>\n {String(n).padStart(2, \"0\")}\n </span>\n );\n}\n","import {\n forwardRef,\n type ComponentPropsWithoutRef,\n type ElementType,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { cx } from \"../utils/cx\";\nimport { ArrowRight, Spinner } from \"../utils/icons\";\n\ntype PillStyle = {\n /** White background: the main action of a screen. */\n solid?: boolean;\n /** Compact version (header, toolbars). */\n size?: \"md\" | \"sm\";\n /** Replaces the dot's arrow (for instance a left arrow for \"Back\"). */\n icon?: ReactNode;\n};\n\nconst pillClass = ({ solid, size }: PillStyle, className?: string) =>\n cx(\"trc-pill\", size === \"sm\" && \"trc-pill--sm\", solid && \"trc-pill--solid\", className);\n\n/** The dot and the fill are one shape: it stretches on hover without a visible circle. */\nfunction PillInner({ icon, children }: { icon?: ReactNode; children: ReactNode }) {\n return (\n <>\n <span aria-hidden className=\"trc-pill__fill\" />\n <span aria-hidden className=\"trc-pill__icon\">\n {icon ?? <ArrowRight />}\n </span>\n <span className=\"trc-pill__label\">{children}</span>\n </>\n );\n}\n\nexport type PillButtonProps = ComponentPropsWithoutRef<\"button\"> &\n PillStyle & {\n /** Replaces the icon with a spinner and disables the button. */\n loading?: boolean;\n };\n\n/** Pill button: thin border, accent dot with an arrow that stretches on hover. */\nexport const PillButton = forwardRef<HTMLButtonElement, PillButtonProps>(function PillButton(\n { solid, size = \"md\", icon, loading = false, disabled, type = \"button\", className, children, ...props },\n ref,\n) {\n return (\n <button\n ref={ref}\n type={type}\n disabled={disabled || loading}\n aria-busy={loading || undefined}\n className={pillClass({ solid, size }, className)}\n {...props}\n >\n <PillInner icon={loading ? <Spinner className=\"trc-spin\" /> : icon}>{children}</PillInner>\n </button>\n );\n});\n\nexport type PillLinkProps<C extends ElementType = \"a\"> = PillStyle & {\n /** Router link component (Next.js or React Router `Link`…); `<a>` by default. */\n as?: C;\n} & Omit<ComponentPropsWithoutRef<C>, \"as\" | keyof PillStyle>;\n\n/** Same pill as a link. With a router: `<PillLink as={Link} href=\"/\">`. */\nexport const PillLink = forwardRef(function PillLink(\n { as, solid, size = \"md\", icon, className, children, ...props }: PillLinkProps<ElementType>,\n ref: Ref<HTMLAnchorElement>,\n) {\n const Tag: ElementType = as ?? \"a\";\n return (\n <Tag ref={ref} className={pillClass({ solid, size }, className)} {...props}>\n <PillInner icon={icon}>{children}</PillInner>\n </Tag>\n );\n}) as <C extends ElementType = \"a\">(props: PillLinkProps<C> & { ref?: Ref<HTMLAnchorElement> }) => ReactNode;\n","import type { SVGProps } from \"react\";\n\ntype IconProps = SVGProps<SVGSVGElement>;\n\nconst base = {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n \"aria-hidden\": true,\n} as const;\n\nexport const ArrowRight = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M5 12h14M13 6l6 6-6 6\" />\n </svg>\n);\n\nexport const ArrowLeft = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M19 12H5M11 18l-6-6 6-6\" />\n </svg>\n);\n\nexport const Spinner = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M21 12a9 9 0 1 1-6.22-8.56\" />\n </svg>\n);\n\nexport const ChevronDown = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n);\n\nexport const Check = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n);\n\nexport const Menu = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M4 7h16M4 12h16M4 17h16\" />\n </svg>\n);\n\nexport const Close = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n);\n\nexport const ArrowUp = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M12 19V5M6 11l6-6 6 6\" />\n </svg>\n);\n","import type { ComponentPropsWithoutRef, ElementType, ReactNode } from \"react\";\nimport { cx } from \"../utils/cx\";\n\ntype Polymorphic<C extends ElementType, P> = P & { as?: C } & Omit<ComponentPropsWithoutRef<C>, \"as\" | keyof P>;\n\nexport type ContainerProps<C extends ElementType = \"div\"> = Polymorphic<\n C,\n {\n /** `default`: 1280 px, for text and grids; `wide`: 1600 px, for full-width cards; `narrow`: 768 px. */\n size?: \"default\" | \"wide\" | \"narrow\";\n }\n>;\n\n/** Centered max width, with side gutters that grow with the screen. */\nexport function Container<C extends ElementType = \"div\">({ as, size = \"default\", className, ...props }: ContainerProps<C>) {\n const Tag: ElementType = as ?? \"div\";\n return <Tag className={cx(\"trc-container\", size !== \"default\" && `trc-container--${size}`, className)} {...props} />;\n}\n\nexport type SectionProps<C extends ElementType = \"section\"> = Polymorphic<\n C,\n {\n /** Vertical spacing. */\n spacing?: \"sm\" | \"md\" | \"lg\" | \"none\";\n /**\n * Card inset from the screen edges (\"magazine\" effect): graphite background and rounded corners,\n * for banners, calls to action and heroes.\n */\n inset?: boolean;\n }\n>;\n\n/** Vertical block of a page. With `inset`, it becomes a large rounded card a few pixels from the edges. */\nexport function Section<C extends ElementType = \"section\">({\n as,\n spacing = \"md\",\n inset = false,\n className,\n children,\n ...props\n}: SectionProps<C>) {\n const Tag: ElementType = as ?? \"section\";\n if (inset) {\n return (\n <Tag className={cx(\"trc-section-inset\", className)} {...props}>\n <div className={cx(\"trc-section-inset__card\", spacing !== \"none\" && `trc-section--${spacing}`)}>{children}</div>\n </Tag>\n );\n }\n return (\n <Tag className={cx(spacing !== \"none\" && `trc-section--${spacing}`, className)} {...props}>\n {children}\n </Tag>\n );\n}\n\nexport type CardProps<C extends ElementType = \"div\"> = Polymorphic<\n C,\n {\n /** `alt`: a slightly lighter grey, to tell two side-by-side blocks apart. */\n tone?: \"default\" | \"alt\";\n padding?: \"none\" | \"sm\" | \"md\" | \"lg\";\n /** Lightens on hover (clickable cards: links, buttons). */\n interactive?: boolean;\n /** Decorative watermark icon: very large, thin stroke, half out of the corner; wakes up on hover. */\n watermark?: ReactNode;\n }\n>;\n\n/** Graphite card, rounded corners, no shadow: depth comes from shades of grey. */\nexport function Card<C extends ElementType = \"div\">({\n as,\n tone = \"default\",\n padding = \"md\",\n interactive = false,\n watermark,\n className,\n children,\n ...props\n}: CardProps<C>) {\n const Tag: ElementType = as ?? \"div\";\n return (\n <Tag\n className={cx(\n \"trc-card\",\n tone === \"alt\" && \"trc-card--alt\",\n padding !== \"none\" && `trc-card--pad-${padding}`,\n interactive && \"trc-card--interactive\",\n !!watermark && \"trc-card--watermark\",\n className,\n )}\n {...props}\n >\n {!!watermark && (\n <span aria-hidden className=\"trc-card__watermark\">\n {watermark}\n </span>\n )}\n {children}\n </Tag>\n );\n}\n","\"use client\";\n\nimport { createContext, forwardRef, useContext, useId, type ComponentPropsWithoutRef, type ReactNode } from \"react\";\nimport { cx } from \"../utils/cx\";\nimport { ChevronDown } from \"../utils/icons\";\n\ntype FieldContextValue = { id: string; describedBy?: string; invalid: boolean; required: boolean };\n\nconst FieldContext = createContext<FieldContextValue | null>(null);\n\nexport type FieldProps = {\n label: ReactNode;\n /** Hint shown under the control. */\n hint?: ReactNode;\n /** Error message: replaces the hint and marks the control as invalid. */\n error?: ReactNode;\n required?: boolean;\n /** Control id; generated when omitted. */\n id?: string;\n className?: string;\n children: ReactNode;\n};\n\n/**\n * Label, hint and error of a form control. The control placed inside (`Input`, `Textarea`, `Select`)\n * automatically receives its `id`, `aria-describedby` and `aria-invalid`.\n */\nexport function Field({ label, hint, error, required = false, id, className, children }: FieldProps) {\n const generated = useId();\n const fieldId = id ?? generated;\n const messageId = `${fieldId}-message`;\n const message = error ?? hint;\n return (\n <FieldContext.Provider\n value={{ id: fieldId, describedBy: message ? messageId : undefined, invalid: error != null, required }}\n >\n <div className={cx(\"trc-field\", className)}>\n <label htmlFor={fieldId} className=\"trc-field__label\">\n {label}\n {required && (\n <span aria-hidden className=\"trc-field__required\">\n {\" \"}\n *\n </span>\n )}\n </label>\n {children}\n {message != null && (\n <p id={messageId} className={cx(\"trc-field__message\", error != null && \"trc-field__message--error\")}>\n {message}\n </p>\n )}\n </div>\n </FieldContext.Provider>\n );\n}\n\n/** Accessibility attributes from the parent `Field`, without overriding those passed to the control. */\nfunction useFieldProps(props: { id?: string; required?: boolean; invalid?: boolean; \"aria-describedby\"?: string }) {\n const field = useContext(FieldContext);\n const invalid = props.invalid ?? field?.invalid ?? false;\n return {\n id: props.id ?? field?.id,\n required: props.required ?? field?.required,\n \"aria-describedby\": cx(field?.describedBy, props[\"aria-describedby\"]) || undefined,\n \"aria-invalid\": invalid || undefined,\n };\n}\n\ntype ControlProps = { invalid?: boolean };\n\nexport type InputProps = ComponentPropsWithoutRef<\"input\"> & ControlProps;\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input({ invalid, className, ...props }, ref) {\n const a11y = useFieldProps({ ...props, invalid });\n return <input ref={ref} className={cx(\"trc-control\", className)} {...props} {...a11y} />;\n});\n\nexport type TextareaProps = ComponentPropsWithoutRef<\"textarea\"> & ControlProps;\n\nexport const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(function Textarea(\n { invalid, rows = 4, className, ...props },\n ref,\n) {\n const a11y = useFieldProps({ ...props, invalid });\n return (\n <textarea\n ref={ref}\n rows={rows}\n className={cx(\"trc-control\", \"trc-control--textarea\", className)}\n {...props}\n {...a11y}\n />\n );\n});\n\nexport type SelectProps = ComponentPropsWithoutRef<\"select\"> &\n ControlProps & {\n /** Empty option shown until something is chosen. */\n placeholder?: string;\n };\n\n/** Native select (accessible and mobile friendly), dressed with a thin chevron. */\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(function Select(\n { invalid, placeholder, defaultValue, className, children, ...props },\n ref,\n) {\n const a11y = useFieldProps({ ...props, invalid });\n // Without a given value, keep the empty option shown (otherwise the browser picks the first enabled option).\n const initial = defaultValue ?? (props.value === undefined && placeholder != null ? \"\" : undefined);\n return (\n <span className={cx(\"trc-select\", className)}>\n <select ref={ref} className=\"trc-control trc-control--select\" defaultValue={initial} {...props} {...a11y}>\n {placeholder != null && (\n <option value=\"\" disabled>\n {placeholder}\n </option>\n )}\n {children}\n </select>\n <ChevronDown className=\"trc-select__chevron\" />\n </span>\n );\n});\n","import { forwardRef, type ComponentPropsWithoutRef, type ReactNode } from \"react\";\nimport { cx } from \"../utils/cx\";\nimport { Check } from \"../utils/icons\";\n\ntype ToggleProps = Omit<ComponentPropsWithoutRef<\"input\">, \"type\"> & {\n label: ReactNode;\n /** Extra detail under the label. */\n description?: ReactNode;\n};\n\n/** The label wraps the control: the whole block is clickable. */\nfunction ToggleLabel({\n kind,\n label,\n description,\n className,\n children,\n}: {\n kind: \"checkbox\" | \"switch\";\n label: ReactNode;\n description?: ReactNode;\n className?: string;\n children: ReactNode;\n}) {\n return (\n <label className={cx(\"trc-toggle\", `trc-toggle--${kind}`, className)}>\n {children}\n <span className=\"trc-toggle__text\">\n <span className=\"trc-toggle__label\">{label}</span>\n {description != null && <span className=\"trc-toggle__description\">{description}</span>}\n </span>\n </label>\n );\n}\n\nexport type CheckboxProps = ToggleProps;\n\n/** Native checkbox, filled with the accent color once checked. */\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(\n { label, description, className, ...props },\n ref,\n) {\n return (\n <ToggleLabel kind=\"checkbox\" label={label} description={description} className={className}>\n <span className=\"trc-checkbox\">\n <input ref={ref} type=\"checkbox\" className=\"trc-checkbox__input\" {...props} />\n <Check className=\"trc-checkbox__check\" />\n </span>\n </ToggleLabel>\n );\n});\n\nexport type SwitchProps = ToggleProps;\n\n/** Switch: a native checkbox announced as a `switch` to screen readers. */\nexport const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch(\n { label, description, className, ...props },\n ref,\n) {\n return (\n <ToggleLabel kind=\"switch\" label={label} description={description} className={className}>\n <span className=\"trc-switch\">\n <input ref={ref} type=\"checkbox\" role=\"switch\" className=\"trc-switch__input\" {...props} />\n <span aria-hidden className=\"trc-switch__thumb\" />\n </span>\n </ToggleLabel>\n );\n});\n","\"use client\";\n\nimport { useEffect, useId, useRef, useState, type ElementType, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useModal } from \"../hooks/use-modal\";\nimport { cx } from \"../utils/cx\";\nimport { ChevronDown, Close, Menu } from \"../utils/icons\";\nimport { PillLink } from \"./pill\";\n\nexport type NavLink = {\n label: ReactNode;\n href: string;\n /** Current page: marked with an accent dot. */\n active?: boolean;\n};\n\nexport type NavMenu = {\n label: ReactNode;\n /** Dropdown items, with an optional short description (no numbers). */\n items: (NavLink & { description?: ReactNode })[];\n};\n\nexport type NavItem = NavLink | NavMenu;\n\nexport type SiteHeaderProps = {\n /** Logo (white), wrapped in a link to `homeHref`. */\n logo: ReactNode;\n /** Accessible name of the logo link, usually the brand name. */\n logoLabel: string;\n homeHref?: string;\n nav?: NavItem[];\n /** Main action, shown as a compact pill (and a large one in the mobile menu). */\n cta?: { label: ReactNode; href: string };\n /** Extra elements on the right on large screens (language switcher…). */\n actions?: ReactNode;\n /** Content added at the bottom of the mobile menu. */\n mobileFooter?: ReactNode;\n /** Router link component (Next.js `Link`…); `<a>` by default. */\n linkAs?: ElementType;\n /** Scroll offset (px) from which the bar becomes blurred graphite. */\n scrollThreshold?: number;\n menuLabel?: string;\n closeLabel?: string;\n className?: string;\n};\n\nconst isMenu = (item: NavItem): item is NavMenu => \"items\" in item;\n\n/**\n * Floating header: transparent over the hero at the top of the page, it becomes a blurred\n * graphite bar as soon as the page scrolls. Dropdowns on large screens, side panel on mobile.\n */\nexport function SiteHeader({\n logo,\n logoLabel,\n homeHref = \"/\",\n nav = [],\n cta,\n actions,\n mobileFooter,\n linkAs: LinkTag = \"a\",\n scrollThreshold = 24,\n menuLabel = \"Menu\",\n closeLabel = \"Close\",\n className,\n}: SiteHeaderProps) {\n const [scrolled, setScrolled] = useState(false);\n const [open, setOpen] = useState(false);\n\n // Read after hydration: same render on the server and on the client.\n useEffect(() => {\n const update = () => setScrolled(window.scrollY > scrollThreshold);\n update();\n window.addEventListener(\"scroll\", update, { passive: true });\n return () => window.removeEventListener(\"scroll\", update);\n }, [scrollThreshold]);\n\n return (\n <header className={cx(\"trc-header\", className)}>\n <div className={cx(\"trc-header__bar\", scrolled && \"trc-header__bar--scrolled\")}>\n <LinkTag href={homeHref} aria-label={logoLabel} className=\"trc-header__logo\">\n {logo}\n </LinkTag>\n\n {nav.length > 0 && (\n <nav className=\"trc-header__nav\">\n {nav.map((item, i) =>\n isMenu(item) ? (\n <NavDropdown key={i} menu={item} linkAs={LinkTag} />\n ) : (\n <LinkTag\n key={i}\n href={item.href}\n aria-current={item.active ? \"page\" : undefined}\n className={cx(\"trc-header__link\", item.active && \"trc-header__link--active\")}\n >\n {item.label}\n </LinkTag>\n ),\n )}\n </nav>\n )}\n\n <div className=\"trc-header__end\">\n {actions && <div className=\"trc-header__actions\">{actions}</div>}\n {cta && (\n <PillLink as={LinkTag} href={cta.href} size=\"sm\" className=\"trc-header__cta\">\n {cta.label}\n </PillLink>\n )}\n {(nav.length > 0 || cta || mobileFooter) && (\n <button\n type=\"button\"\n className=\"trc-header__burger\"\n aria-label={menuLabel}\n aria-expanded={open}\n onClick={() => setOpen(true)}\n >\n <Menu />\n </button>\n )}\n </div>\n </div>\n\n <MobileMenu\n open={open}\n onClose={() => setOpen(false)}\n nav={nav}\n cta={cta}\n footer={mobileFooter}\n linkAs={LinkTag}\n title={menuLabel}\n closeLabel={closeLabel}\n />\n </header>\n );\n}\n\n/**\n * Dropdown menu (large screens): opens on hover or click, closes on leave, with Escape,\n * when keyboard focus leaves the menu, or after a choice.\n */\nfunction NavDropdown({ menu, linkAs: LinkTag }: { menu: NavMenu; linkAs: ElementType }) {\n const id = useId();\n const [open, setOpen] = useState(false);\n const closeTimer = useRef<number | undefined>(undefined);\n const button = useRef<HTMLButtonElement>(null);\n\n const show = () => {\n window.clearTimeout(closeTimer.current);\n setOpen(true);\n };\n // Short delay: the pointer may cross the gap between the button and the panel.\n const hide = () => {\n closeTimer.current = window.setTimeout(() => setOpen(false), 120);\n };\n useEffect(() => () => window.clearTimeout(closeTimer.current), []);\n\n return (\n <div\n className=\"trc-dropdown\"\n onMouseEnter={show}\n onMouseLeave={hide}\n onKeyDown={(e) => {\n if (e.key === \"Escape\" && open) {\n setOpen(false);\n button.current?.focus();\n }\n }}\n onBlur={(e) => !e.currentTarget.contains(e.relatedTarget) && setOpen(false)}\n >\n <button\n ref={button}\n type=\"button\"\n aria-expanded={open}\n aria-controls={id}\n onClick={() => setOpen((o) => !o)}\n className={cx(\"trc-header__link\", \"trc-dropdown__trigger\", open && \"trc-dropdown__trigger--open\")}\n >\n {menu.label}\n <ChevronDown className=\"trc-dropdown__chevron\" />\n </button>\n <div id={id} className={cx(\"trc-dropdown__panel\", open && \"trc-dropdown__panel--open\")}>\n <ul className=\"trc-dropdown__list\">\n {menu.items.map((item, i) => (\n <li key={i}>\n <LinkTag\n href={item.href}\n aria-current={item.active ? \"page\" : undefined}\n onClick={() => setOpen(false)}\n className=\"trc-dropdown__item\"\n >\n <span className=\"trc-dropdown__label\">{item.label}</span>\n {item.description != null && <span className=\"trc-dropdown__description\">{item.description}</span>}\n </LinkTag>\n </li>\n ))}\n </ul>\n </div>\n </div>\n );\n}\n\n/**\n * Side panel of the mobile menu, rendered into `document.body`: otherwise the header's blurred bar\n * (`backdrop-filter`) would trap a `fixed` element within its own bounds.\n */\nfunction MobileMenu({\n open,\n onClose,\n nav,\n cta,\n footer,\n linkAs: LinkTag,\n title,\n closeLabel,\n}: {\n open: boolean;\n onClose: () => void;\n nav: NavItem[];\n cta?: SiteHeaderProps[\"cta\"];\n footer?: ReactNode;\n linkAs: ElementType;\n title: string;\n closeLabel: string;\n}) {\n const titleId = useId();\n const panel = useRef<HTMLDivElement>(null);\n const [mounted, setMounted] = useState(false);\n useEffect(() => setMounted(true), []);\n useModal(open, panel, onClose);\n\n if (!mounted) return null;\n return createPortal(\n <div className={cx(\"trc-drawer\", open && \"trc-drawer--open\")} aria-hidden={!open}>\n <div className=\"trc-drawer__overlay\" onClick={onClose} />\n <div\n ref={panel}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n tabIndex={-1}\n className=\"trc-drawer__panel\"\n >\n <div className=\"trc-drawer__head\">\n <p id={titleId} className=\"trc-drawer__title\">\n {title}\n </p>\n <button type=\"button\" className=\"trc-drawer__close\" aria-label={closeLabel} onClick={onClose}>\n <Close />\n </button>\n </div>\n <nav className=\"trc-mobile-nav\">\n {nav.map((item, i) =>\n isMenu(item) ? (\n <div key={i} className=\"trc-mobile-nav__group\">\n <p className=\"trc-mobile-nav__heading\">{item.label}</p>\n <ul className=\"trc-mobile-nav__sub\">\n {item.items.map((sub, j) => (\n <li key={j}>\n <LinkTag\n href={sub.href}\n aria-current={sub.active ? \"page\" : undefined}\n onClick={onClose}\n className=\"trc-mobile-nav__sublink\"\n >\n {sub.label}\n </LinkTag>\n </li>\n ))}\n </ul>\n </div>\n ) : (\n <LinkTag\n key={i}\n href={item.href}\n aria-current={item.active ? \"page\" : undefined}\n onClick={onClose}\n className={cx(\"trc-mobile-nav__link\", item.active && \"trc-mobile-nav__link--active\")}\n >\n {item.label}\n </LinkTag>\n ),\n )}\n </nav>\n {cta && (\n <PillLink as={LinkTag} href={cta.href} onClick={onClose} className=\"trc-drawer__cta\">\n {cta.label}\n </PillLink>\n )}\n {footer != null && <div className=\"trc-drawer__footer\">{footer}</div>}\n </div>\n </div>,\n document.body,\n );\n}\n","import { useEffect, useRef, type RefObject } from \"react\";\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Behavior of an open modal panel: focus moved inside and kept there (Tab / Shift+Tab),\n * closes with Escape, page scroll locked, focus returned to the original element on close.\n */\nexport function useModal(open: boolean, panelRef: RefObject<HTMLElement | null>, onClose: () => void) {\n // Latest close callback, without re-running the effect on every render.\n const close = useRef(onClose);\n close.current = onClose;\n\n useEffect(() => {\n const panel = panelRef.current;\n if (!open || !panel) return;\n\n const previous = document.activeElement as HTMLElement | null;\n const overflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n (\n panel.querySelector<HTMLElement>(\"[data-autofocus]\") ??\n panel.querySelector<HTMLElement>(FOCUSABLE) ??\n panel\n ).focus();\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.stopPropagation();\n close.current();\n return;\n }\n if (e.key !== \"Tab\") return;\n const items = [...panel.querySelectorAll<HTMLElement>(FOCUSABLE)].filter((el) => el.offsetParent !== null);\n const first = items[0];\n const last = items[items.length - 1];\n if (!first || !last) {\n e.preventDefault();\n return;\n }\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n };\n document.addEventListener(\"keydown\", onKeyDown);\n\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n document.body.style.overflow = overflow;\n previous?.focus();\n };\n }, [open, panelRef]);\n}\n","import type { ElementType, ReactNode } from \"react\";\nimport { cx } from \"../utils/cx\";\n\nexport type FooterLink = { label: ReactNode; href: string };\n\nexport type SiteFooterProps = {\n /** Logo (white), wrapped in a link to `homeHref`. */\n logo?: ReactNode;\n logoLabel?: string;\n homeHref?: string;\n /** Short sentence under the logo. */\n tagline?: ReactNode;\n /** Under the sentence: a pill, a contact… */\n children?: ReactNode;\n /** Site map in columns, each with a spaced small-caps title. */\n columns?: { title: ReactNode; links: FooterLink[] }[];\n /** Accessible name of the site map. */\n columnsLabel?: string;\n /** Bottom line (copyright, credits…). */\n copyright?: ReactNode;\n /** Legal links, aligned right on large screens. */\n legal?: FooterLink[];\n legalLabel?: string;\n /** Router link component (Next.js `Link`…); `<a>` by default. */\n linkAs?: ElementType;\n className?: string;\n};\n\n/** Graphite card footer: brand and call to action, site map in columns, legal links. */\nexport function SiteFooter({\n logo,\n logoLabel,\n homeHref = \"/\",\n tagline,\n children,\n columns = [],\n columnsLabel = \"Site map\",\n copyright,\n legal = [],\n legalLabel = \"Legal\",\n linkAs: LinkTag = \"a\",\n className,\n}: SiteFooterProps) {\n return (\n <footer className={cx(\"trc-footer\", className)}>\n <div className=\"trc-footer__card\">\n <div className=\"trc-footer__main\">\n <div className=\"trc-footer__brand\">\n {logo != null && (\n <LinkTag href={homeHref} aria-label={logoLabel} className=\"trc-footer__logo\">\n {logo}\n </LinkTag>\n )}\n {tagline != null && <p className=\"trc-footer__tagline\">{tagline}</p>}\n {children != null && <div className=\"trc-footer__extra\">{children}</div>}\n </div>\n\n {columns.length > 0 && (\n <nav className=\"trc-footer__columns\" aria-label={columnsLabel}>\n {columns.map((col, i) => (\n <div key={i}>\n <p className=\"trc-footer__heading\">{col.title}</p>\n <ul className=\"trc-footer__list\">\n {col.links.map((link, j) => (\n <li key={j}>\n <LinkTag href={link.href} className=\"trc-footer__link\">\n {link.label}\n </LinkTag>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </nav>\n )}\n </div>\n\n {(copyright != null || legal.length > 0) && (\n <div className=\"trc-footer__bottom\">\n {copyright != null && <p className=\"trc-footer__copyright\">{copyright}</p>}\n {legal.length > 0 && (\n <nav aria-label={legalLabel} className=\"trc-footer__legal\">\n {legal.map((link, i) => (\n <LinkTag key={i} href={link.href} className=\"trc-footer__legal-link\">\n {link.label}\n </LinkTag>\n ))}\n </nav>\n )}\n </div>\n )}\n </div>\n </footer>\n );\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState, type CSSProperties, type ReactNode } from \"react\";\nimport { cx } from \"../utils/cx\";\nimport { AccentText } from \"./typography\";\n\n/** Delay of an entrance (`.trc-enter`) in milliseconds. */\nconst delay = (ms: number) => ({ \"--trc-delay\": `${ms}ms` }) as CSSProperties;\n\nexport type PageHeroProps = {\n /** Title; the words between *asterisks* take the accent, otherwise the last words (`accentLast`). */\n title: string;\n /** Number of trailing words in the accent color when the title has no asterisks (2 for a long title, 1 otherwise). */\n accentLast?: number;\n description?: ReactNode;\n /** Discreet line under the description (last updated date, breadcrumb…). */\n meta?: ReactNode;\n /**\n * Background photo, heavily darkened: a URL, or a ready-made element (Next.js `<Image fill />`…).\n * Without a photo, a subtle accent glow on a graphite background.\n */\n image?: string | ReactNode;\n /** Photo position (`object-position`). */\n imagePosition?: string;\n /** Content under the text (pills…). */\n children?: ReactNode;\n className?: string;\n};\n\n/**\n * Header of inner pages: rounded card inset from the edges, darkened background photo,\n * thin title whose last words take the accent. Leaves room for the floating header above.\n */\nexport function PageHero({\n title,\n accentLast,\n description,\n meta,\n image,\n imagePosition = \"50% 50%\",\n children,\n className,\n}: PageHeroProps) {\n const words = title.split(\" \").length;\n return (\n <section className={cx(\"trc-hero-inset\", className)}>\n <div className=\"trc-page-hero\">\n <div aria-hidden className=\"trc-hero__media\">\n {typeof image === \"string\" ? (\n <img src={image} alt=\"\" className=\"trc-hero__image\" style={{ objectPosition: imagePosition }} />\n ) : image != null ? (\n image\n ) : (\n <div className=\"trc-page-hero__glow\" />\n )}\n </div>\n <div aria-hidden className=\"trc-page-hero__veil\" />\n <div className=\"trc-page-hero__content\">\n <h1 className=\"trc-display trc-page-hero__title trc-enter\" style={delay(150)}>\n <AccentText text={title} accentLast={accentLast ?? (words > 3 ? 2 : 1)} />\n </h1>\n {description != null && (\n <p className=\"trc-page-hero__description trc-enter\" style={delay(250)}>\n {description}\n </p>\n )}\n {meta != null && (\n <div className=\"trc-page-hero__meta trc-enter\" style={delay(350)}>\n {meta}\n </div>\n )}\n {children != null && (\n <div className=\"trc-page-hero__actions trc-enter\" style={delay(450)}>\n {children}\n </div>\n )}\n </div>\n </div>\n </section>\n );\n}\n\nexport type HeroClip = {\n /** Muted video, 1280 px, without an audio track. Provide WebM and/or MP4. */\n webm?: string;\n mp4?: string;\n /** Image shown before playback, and alone when the user prefers reduced motion. */\n poster?: string;\n};\n\nexport type HeroVideoProps = {\n /** Videos played one after another with a crossfade; the first one is picked at random. */\n clips: HeroClip[];\n /** Hero text (title, description, pills), pinned to the bottom left. */\n children: ReactNode;\n /** Optional block pinned to the bottom right on large screens. */\n aside?: ReactNode;\n /** Crossfade duration, in seconds. */\n fade?: number;\n /** Soft parallax: the video moves down slower than the page. */\n parallax?: boolean;\n className?: string;\n};\n\nconst prefersReducedMotion = () => window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n/**\n * Home page hero: rounded card inset from the edges, muted background videos that alternate with\n * a crossfade, dark veils for legibility. No video in the server render: the pick happens\n * after hydration, then the video fades in. Reduced motion: the still image only.\n */\nexport function HeroVideo({ clips, children, aside, fade = 1.2, parallax = true, className }: HeroVideoProps) {\n const videos = useRef<(HTMLVideoElement | null)[]>([]);\n const section = useRef<HTMLElement>(null);\n const media = useRef<HTMLDivElement>(null);\n // -1 until the pick is made: same render on the server and on the client.\n const [active, setActive] = useState(-1);\n\n useEffect(() => {\n if (clips.length === 0) return;\n const start = Math.floor(Math.random() * clips.length);\n // Element captured here: in strict mode, React detaches refs before the cleanup runs.\n const video = videos.current[start];\n if (!prefersReducedMotion()) void video?.play().catch(() => {});\n const frame = requestAnimationFrame(() => setActive(start));\n return () => {\n cancelAnimationFrame(frame);\n video?.pause();\n };\n }, [clips.length]);\n\n useEffect(() => {\n const el = section.current;\n const layer = media.current;\n if (!parallax || !el || !layer || prefersReducedMotion()) return;\n let frame = 0;\n const update = () => {\n frame = 0;\n const rect = el.getBoundingClientRect();\n const progress = Math.min(Math.max(-rect.top / rect.height, 0), 1);\n layer.style.transform = `translate3d(0, ${progress * 120}px, 0)`;\n };\n const onScroll = () => {\n if (!frame) frame = requestAnimationFrame(update);\n };\n update();\n window.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => {\n window.removeEventListener(\"scroll\", onScroll);\n cancelAnimationFrame(frame);\n };\n }, [parallax]);\n\n const playNext = (i: number) => {\n const next = videos.current[(i + 1) % clips.length];\n if (!next) return;\n next.currentTime = 0;\n void next.play().catch(() => {});\n setActive((i + 1) % clips.length);\n };\n\n return (\n <section ref={section} className={cx(\"trc-hero-inset\", className)}>\n <div className=\"trc-hero-video\">\n <div ref={media} aria-hidden className=\"trc-hero__media trc-hero-video__media\">\n {clips.map((clip, i) => (\n <video\n key={i}\n ref={(el) => {\n videos.current[i] = el;\n }}\n className={cx(\"trc-hero__image\", \"trc-hero-video__clip\", i === active && \"trc-hero-video__clip--active\")}\n style={{ transitionDuration: `${fade}s` }}\n muted\n playsInline\n preload=\"metadata\"\n poster={clip.poster}\n // Shortly before the active video ends, the next one restarts and comes to the front.\n onTimeUpdate={(e) => {\n const v = e.currentTarget;\n if (i === active && v.duration && v.duration - v.currentTime <= fade) playNext(i);\n }}\n // Safety net when `timeupdate` did not trigger the switch (background tab…).\n onEnded={() => i === active && playNext(i)}\n >\n {clip.webm && <source src={clip.webm} type=\"video/webm\" />}\n {clip.mp4 && <source src={clip.mp4} type=\"video/mp4\" />}\n </video>\n ))}\n </div>\n <div aria-hidden className=\"trc-hero-video__veil\" />\n <div className=\"trc-hero-video__content\">\n <div className=\"trc-hero-video__main\">{children}</div>\n {aside != null && <div className=\"trc-hero-video__aside\">{aside}</div>}\n </div>\n </div>\n </section>\n );\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { cx } from \"../utils/cx\";\nimport { ArrowUp } from \"../utils/icons\";\n\nexport type BackToTopProps = {\n label?: string;\n /** Scroll offset, in viewport heights, from which the button appears. */\n threshold?: number;\n className?: string;\n};\n\n/** Floating accent \"Back to top\" button: appears once the first screen is scrolled past. */\nexport function BackToTop({ label = \"Back to top\", threshold = 0.8, className }: BackToTopProps) {\n const [visible, setVisible] = useState(false);\n\n useEffect(() => {\n const update = () => setVisible(window.scrollY > window.innerHeight * threshold);\n update();\n window.addEventListener(\"scroll\", update, { passive: true });\n return () => window.removeEventListener(\"scroll\", update);\n }, [threshold]);\n\n return (\n <button\n type=\"button\"\n onClick={() =>\n window.scrollTo({\n top: 0,\n behavior: window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches ? \"auto\" : \"smooth\",\n })\n }\n aria-label={label}\n aria-hidden={!visible}\n tabIndex={visible ? 0 : -1}\n className={cx(\"trc-back-to-top\", visible && \"trc-back-to-top--visible\", className)}\n >\n <ArrowUp />\n </button>\n );\n}\n"],"mappings":"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","names":["jsx","Fragment","jsx","jsxs","PillButton","PillLink","jsx","jsxs","forwardRef","jsx","jsxs","forwardRef","Input","Textarea","Select","forwardRef","jsx","jsxs","forwardRef","Checkbox","Switch","useEffect","useId","useRef","jsx","jsxs","useEffect","useId","useRef","jsx","jsxs","useEffect","useRef","useState","jsx","jsxs","useRef","useState","useEffect","useEffect","useState","jsx","useState","useEffect"]}
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--trc-bg: #0b0c0f;--trc-surface: #151618;--trc-surface-raised: #1b1c1f;--trc-surface-alt: #232428;--trc-fg: #ffffff;--trc-fg-muted: rgba(255, 255, 255, .72);--trc-fg-subtle: rgba(255, 255, 255, .55);--trc-fg-faint: rgba(255, 255, 255, .4);--trc-border: rgba(255, 255, 255, .08);--trc-border-strong: rgba(255, 255, 255, .16);--trc-border-pill: rgba(255, 255, 255, .2);--trc-accent: #08c8d8;--trc-on-accent: #0b0c0f;--trc-danger: #ff6b6b;--trc-font: "Montserrat", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;--trc-font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;--trc-radius-sm: 10px;--trc-radius: 16px;--trc-radius-pill: 999px;--trc-ease: cubic-bezier(.77, 0, .175, 1);--trc-ease-out: cubic-bezier(.22, 1, .36, 1);--trc-duration: .5s}*,:before,:after{--trc-accent-soft: color-mix(in srgb, var(--trc-accent) 12%, transparent);--trc-ring: 0 0 0 2px var(--trc-bg), 0 0 0 4px var(--trc-accent)}.trc{background-color:var(--trc-bg);color:var(--trc-fg);font-family:var(--trc-font);letter-spacing:-.01em;color-scheme:dark;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.trc-display{font-family:var(--trc-font);font-weight:400;letter-spacing:-.025em;line-height:1.08}.trc-accent{color:var(--trc-accent)}.trc-visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.trc-spin{animation:trc-spin .8s linear infinite}@keyframes trc-spin{to{transform:rotate(360deg)}}.trc-enter{animation:trc-enter .9s var(--trc-ease-out) both;animation-delay:var(--trc-delay, 0ms)}@keyframes trc-enter{0%{opacity:0;transform:translateY(16px)}}@media(prefers-reduced-motion:reduce){.trc-enter{animation:none}}.trc-heading--display{font-size:clamp(3rem,2.2rem + 3.6vw,4.5rem)}.trc-heading--xl{font-size:clamp(2.25rem,1.9rem + 1.6vw,3rem)}.trc-heading--lg{font-size:clamp(1.75rem,1.55rem + .9vw,2.25rem);line-height:1.15}.trc-heading--md{font-size:1.5rem;line-height:1.2}.trc-heading--sm{font-size:1.25rem;line-height:1.3}.trc-display{margin:0;color:var(--trc-fg)}.trc-text{margin:0;line-height:1.65}.trc-text--lg{font-size:1.125rem}.trc-text--md{font-size:1rem}.trc-text--sm{font-size:.875rem}.trc-text--default{color:var(--trc-fg)}.trc-text--muted{color:var(--trc-fg-muted)}.trc-text--subtle{color:var(--trc-fg-subtle)}.trc-step-number{display:block;flex-shrink:0;font-family:var(--trc-font);font-size:3rem;font-weight:300;font-variant-numeric:tabular-nums;letter-spacing:-.025em;line-height:1;color:var(--trc-accent)}.trc-step-number--sm{font-size:1.5rem}.trc-pill{--pill-inset: 6px;--pill-dot: 44px;position:relative;isolation:isolate;box-sizing:border-box;display:inline-flex;flex-shrink:0;align-items:center;gap:14px;height:56px;max-width:100%;padding:var(--pill-inset) 24px var(--pill-inset) var(--pill-inset);overflow:hidden;border:1px solid var(--trc-border-pill);border-radius:var(--trc-radius-pill);background:transparent;color:var(--trc-fg);font:500 15px/1 var(--trc-font);letter-spacing:-.01em;text-decoration:none;cursor:pointer;outline:none;-webkit-tap-highlight-color:transparent}.trc-pill--sm{--pill-inset: 4px;--pill-dot: 32px;gap:10px;height:40px;padding-right:16px;font-size:14px}.trc-pill--solid{border-color:#fff;background:#fff;color:var(--trc-bg)}.trc-pill:focus-visible{box-shadow:var(--trc-ring)}.trc-pill:disabled{cursor:not-allowed;opacity:.6}.trc-pill__fill{position:absolute;z-index:-1;top:var(--pill-inset);bottom:var(--pill-inset);left:var(--pill-inset);width:var(--pill-dot);border-radius:var(--trc-radius-pill);background:var(--trc-accent);transition:width var(--trc-duration) var(--trc-ease)}.trc-pill__icon{display:flex;flex-shrink:0;align-items:center;justify-content:center;width:var(--pill-dot);height:var(--pill-dot);color:var(--trc-on-accent)}.trc-pill__icon svg{width:18px;height:18px}.trc-pill--sm .trc-pill__icon svg{width:16px;height:16px}.trc-pill__label{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;transition:color .3s ease}@media(hover:hover){.trc-pill:not(:disabled):hover .trc-pill__fill{width:calc(100% - 2 * var(--pill-inset))}.trc-pill:not(:disabled):hover .trc-pill__label{color:var(--trc-on-accent);transition-delay:.15s}}.trc-pill:focus-visible .trc-pill__fill{width:calc(100% - 2 * var(--pill-inset))}.trc-pill:focus-visible .trc-pill__label{color:var(--trc-on-accent)}@media(prefers-reduced-motion:reduce){.trc-pill__fill{transition-duration:1ms}}.trc-container{box-sizing:border-box;width:100%;max-width:1280px;margin-inline:auto;padding-inline:16px}.trc-container--narrow{max-width:768px}.trc-container--wide{max-width:1600px}@media(min-width:640px){.trc-container{padding-inline:24px}}@media(min-width:1024px){.trc-container{padding-inline:40px}}.trc-section--sm{padding-block:48px}.trc-section--md{padding-block:72px}.trc-section--lg{padding-block:96px}@media(min-width:768px){.trc-section--md{padding-block:96px}.trc-section--lg{padding-block:128px}}.trc-section-inset{box-sizing:border-box;padding-inline:8px}.trc-section-inset__card{position:relative;isolation:isolate;box-sizing:border-box;max-width:1600px;margin-inline:auto;overflow:hidden;border-radius:var(--trc-radius);background:var(--trc-surface)}@media(min-width:640px){.trc-section-inset{padding-inline:16px}}.trc-card{position:relative;box-sizing:border-box;border:1px solid var(--trc-border);border-radius:var(--trc-radius);background:var(--trc-surface);color:var(--trc-fg)}.trc-card--alt{background:var(--trc-surface-alt)}.trc-card--pad-sm{padding:20px}.trc-card--pad-md{padding:28px}.trc-card--pad-lg{padding:32px}@media(min-width:640px){.trc-card--pad-lg{padding:40px}}.trc-card--interactive{display:block;text-decoration:none;transition:background-color .3s ease,border-color .3s ease}a.trc-card--interactive,button.trc-card--interactive{cursor:pointer;font:inherit;text-align:inherit}.trc-card--interactive:hover{background:var(--trc-surface-raised);border-color:var(--trc-border-strong)}.trc-card--alt.trc-card--interactive:hover{background:color-mix(in srgb,var(--trc-surface-alt) 92%,white)}.trc-card--interactive:focus-visible{outline:none;box-shadow:var(--trc-ring)}.trc-card--watermark{isolation:isolate;overflow:hidden}.trc-card__watermark{position:absolute;z-index:-1;top:-28px;right:-28px;display:flex;width:160px;height:160px;color:var(--trc-fg);opacity:.05;pointer-events:none;transition:opacity .6s var(--trc-ease-out),color .6s var(--trc-ease-out),transform .6s var(--trc-ease-out)}.trc-card__watermark svg{width:100%;height:100%;stroke-width:1.25px}.trc-card__watermark svg *{vector-effect:non-scaling-stroke}.trc-card--watermark:hover .trc-card__watermark{color:var(--trc-accent);opacity:.18;transform:rotate(-6deg) scale(1.04)}@media(prefers-reduced-motion:reduce){.trc-card__watermark{transition-duration:1ms}}.trc-field{display:grid;align-content:start;gap:8px;min-width:0}.trc-field__label{font-size:14px;font-weight:500;line-height:1.4;color:var(--trc-fg)}.trc-field__required{color:var(--trc-accent)}.trc-field__message{margin:0;font-size:13px;line-height:1.5;color:var(--trc-fg-subtle)}.trc-field__message--error{color:var(--trc-danger)}.trc-control{box-sizing:border-box;width:100%;height:48px;margin:0;padding:0 16px;border:1px solid var(--trc-border-strong);border-radius:12px;background:#ffffff08;color:var(--trc-fg);font:400 15px/1.4 var(--trc-font);letter-spacing:-.01em;outline:none;transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease}.trc-control::placeholder{color:var(--trc-fg-faint)}.trc-control:hover:not(:disabled){border-color:#ffffff47}.trc-control:focus-visible{border-color:var(--trc-accent);box-shadow:0 0 0 3px var(--trc-accent-soft)}.trc-control[aria-invalid=true]{border-color:var(--trc-danger)}.trc-control[aria-invalid=true]:focus-visible{box-shadow:0 0 0 3px color-mix(in srgb,var(--trc-danger) 18%,transparent)}.trc-control:disabled{cursor:not-allowed;opacity:.5}.trc-control--textarea{height:auto;min-height:96px;padding:12px 16px;line-height:1.55;resize:vertical}.trc-select{position:relative;display:block}.trc-control--select{padding-right:44px;appearance:none;cursor:pointer}.trc-control--select:has(option[value=""]:checked){color:var(--trc-fg-faint)}.trc-control--select option{background:var(--trc-surface);color:var(--trc-fg)}.trc-select__chevron{position:absolute;top:50%;right:16px;width:18px;height:18px;color:var(--trc-fg-subtle);pointer-events:none;transform:translateY(-50%)}.trc-toggle{display:flex;align-items:flex-start;gap:12px;cursor:pointer;-webkit-tap-highlight-color:transparent}.trc-toggle:has(input:disabled){cursor:not-allowed;opacity:.5}.trc-toggle__text{display:grid;gap:2px;min-width:0}.trc-toggle__label{font-size:15px;line-height:1.45;color:var(--trc-fg)}.trc-toggle__description{font-size:13px;line-height:1.5;color:var(--trc-fg-subtle)}.trc-checkbox{position:relative;display:flex;flex-shrink:0;margin-top:1px}.trc-checkbox__input{width:20px;height:20px;margin:0;border:1px solid var(--trc-border-pill);border-radius:6px;background:#ffffff08;appearance:none;cursor:inherit;outline:none;transition:background-color .2s ease,border-color .2s ease}.trc-toggle:hover .trc-checkbox__input:not(:disabled,:checked){border-color:#fff6}.trc-checkbox__input:checked{border-color:var(--trc-accent);background:var(--trc-accent)}.trc-checkbox__input:focus-visible{box-shadow:var(--trc-ring)}.trc-checkbox__check{position:absolute;inset:3px;width:14px;height:14px;color:var(--trc-on-accent);stroke-width:3;opacity:0;pointer-events:none;transform:scale(.6);transition:opacity .2s ease,transform .3s var(--trc-ease-out)}.trc-checkbox__input:checked+.trc-checkbox__check{opacity:1;transform:scale(1)}.trc-switch{position:relative;display:flex;flex-shrink:0}.trc-switch__input{width:40px;height:24px;margin:0;border:1px solid var(--trc-border-strong);border-radius:var(--trc-radius-pill);background:#ffffff14;appearance:none;cursor:inherit;outline:none;transition:background-color .3s ease,border-color .3s ease}.trc-switch__input:checked{border-color:var(--trc-accent);background:var(--trc-accent)}.trc-switch__input:focus-visible{box-shadow:var(--trc-ring)}.trc-switch__thumb{position:absolute;top:4px;left:4px;width:16px;height:16px;border-radius:50%;background:var(--trc-fg);pointer-events:none;transition:transform .3s var(--trc-ease),background-color .3s ease}.trc-switch__input:checked+.trc-switch__thumb{background:var(--trc-on-accent);transform:translate(16px)}@media(prefers-reduced-motion:reduce){.trc-checkbox__check,.trc-switch__thumb{transition-duration:1ms}}.trc-header{position:fixed;inset:0 0 auto;z-index:40;box-sizing:border-box;padding:8px;font-family:var(--trc-font);pointer-events:none}.trc-header__bar{box-sizing:border-box;display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);align-items:center;gap:16px;max-width:1600px;height:64px;margin-inline:auto;padding-inline:16px;border:1px solid transparent;border-radius:var(--trc-radius);pointer-events:auto;transition:background-color .3s ease,border-color .3s ease,backdrop-filter .3s ease}.trc-header__bar--scrolled{border-color:#ffffff1a;background:color-mix(in srgb,var(--trc-surface) 80%,transparent);-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px)}@media(min-width:640px){.trc-header{padding:16px}.trc-header__bar{height:80px;padding-inline:32px}}.trc-header__logo{grid-column:1;justify-self:start;display:inline-flex;flex-shrink:0;align-items:center;color:var(--trc-fg);text-decoration:none}.trc-header__nav{grid-column:2;display:none;align-items:center;gap:28px}.trc-header__link{position:relative;display:inline-flex;align-items:center;gap:6px;padding:4px 0;border:0;background:none;color:#fffc;font:inherit;font-size:15px;text-decoration:none;cursor:pointer;transition:color .2s ease}.trc-header__link:hover,.trc-header__link--active{color:var(--trc-fg)}.trc-header__link--active:after{content:"";position:absolute;bottom:-4px;left:50%;width:4px;height:4px;border-radius:50%;background:var(--trc-accent);transform:translate(-50%)}.trc-header__end{grid-column:3;justify-self:end;display:flex;align-items:center;gap:8px}.trc-header__actions,.trc-header__cta{display:none}.trc-header__actions{align-items:center;gap:8px}@media(min-width:640px){.trc-header__actions{display:flex}.trc-header__cta{display:inline-flex}}.trc-header__burger{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--trc-fg);cursor:pointer;transition:background-color .2s ease}.trc-header__burger:hover{background:#ffffff1a}.trc-header__burger svg{width:20px;height:20px}@media(min-width:1024px){.trc-header__nav{display:flex}.trc-header__burger{display:none}}.trc-dropdown{position:relative}.trc-dropdown__trigger--open{color:var(--trc-fg)}.trc-dropdown__chevron{width:16px;height:16px;transition:transform .3s ease}.trc-dropdown__trigger--open .trc-dropdown__chevron{transform:rotate(180deg)}.trc-dropdown__panel{position:absolute;top:100%;left:50%;width:320px;padding-top:16px;visibility:hidden;opacity:0;transform:translate(-50%,-4px);transition:opacity .3s var(--trc-ease-out),transform .3s var(--trc-ease-out),visibility 0s .3s}.trc-dropdown__panel--open{visibility:visible;opacity:1;transform:translate(-50%);transition-delay:0s}.trc-dropdown__list{margin:0;padding:8px;list-style:none;border:1px solid rgba(255,255,255,.1);border-radius:var(--trc-radius);background:color-mix(in srgb,var(--trc-surface) 95%,transparent);box-shadow:0 24px 60px -20px #000000b3;-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px)}.trc-dropdown__item{display:block;padding:14px 16px;border-radius:12px;color:inherit;text-decoration:none;transition:background-color .2s ease}.trc-dropdown__item:hover,.trc-dropdown__item:focus-visible{background:#ffffff0d}.trc-dropdown__label{display:block;font-size:15px;color:var(--trc-fg)}.trc-dropdown__description{display:block;margin-top:2px;font-size:13px;line-height:1.4;color:var(--trc-fg-subtle)}.trc-drawer{position:fixed;inset:0;z-index:50;font-family:var(--trc-font);letter-spacing:-.01em;color:var(--trc-fg);visibility:hidden;transition:visibility 0s .4s}.trc-drawer--open{visibility:visible;transition-delay:0s}.trc-drawer__overlay{position:absolute;inset:0;background:#0009;opacity:0;transition:opacity .4s ease}.trc-drawer--open .trc-drawer__overlay{opacity:1}.trc-drawer__panel{position:absolute;top:0;right:0;bottom:0;box-sizing:border-box;display:flex;flex-direction:column;width:min(380px,88vw);padding:24px;overflow-y:auto;border-left:1px solid rgba(255,255,255,.1);background:var(--trc-bg);outline:none;transform:translate(100%);transition:transform .4s var(--trc-ease-out)}.trc-drawer--open .trc-drawer__panel{transform:translate(0)}.trc-drawer__head{display:flex;align-items:center;justify-content:space-between}.trc-drawer__title{margin:0;font-size:12px;font-weight:500;letter-spacing:.18em;text-transform:uppercase;color:#ffffff80}.trc-drawer__close{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;margin-right:-8px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--trc-fg);cursor:pointer}.trc-drawer__close:hover{background:#ffffff1a}.trc-drawer__close svg{width:20px;height:20px}.trc-drawer__cta{align-self:flex-start;margin-top:24px}.trc-drawer__footer{margin-top:24px}.trc-mobile-nav{display:flex;flex-direction:column;margin-top:16px}.trc-mobile-nav__link,.trc-mobile-nav__group{padding-block:16px;border-bottom:1px solid rgba(255,255,255,.1)}.trc-mobile-nav__link,.trc-mobile-nav__heading{margin:0;font-size:18px;color:var(--trc-fg);text-decoration:none}.trc-mobile-nav__link{transition:color .2s ease}.trc-mobile-nav__link:hover,.trc-mobile-nav__link--active{color:var(--trc-accent)}.trc-mobile-nav__sub{margin:12px 0 0;padding:0 0 0 16px;list-style:none;border-left:1px solid rgba(255,255,255,.1)}.trc-mobile-nav__sublink{display:block;padding-block:6px;color:#ffffffb3;text-decoration:none;transition:color .2s ease}.trc-mobile-nav__sublink:hover,.trc-mobile-nav__sublink[aria-current=page]{color:var(--trc-accent)}@media(prefers-reduced-motion:reduce){.trc-drawer,.trc-drawer__overlay,.trc-drawer__panel,.trc-dropdown__panel{transition-duration:1ms}}.trc-footer{box-sizing:border-box;padding:0 8px 8px;font-family:var(--trc-font)}.trc-footer__card{box-sizing:border-box;max-width:1600px;margin-inline:auto;padding-inline:24px;border:1px solid rgba(255,255,255,.06);border-radius:var(--trc-radius);background:var(--trc-surface);color:var(--trc-fg)}.trc-footer__main{display:grid;gap:48px;padding-block:64px}.trc-footer__brand{max-width:384px}.trc-footer__logo{display:inline-flex;color:var(--trc-fg);text-decoration:none}.trc-footer__tagline{margin:24px 0 0;line-height:1.65;color:#ffffffb3}.trc-footer__extra{display:grid;justify-items:start;gap:24px;margin-top:32px}.trc-footer__columns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:40px 32px}.trc-footer__heading{margin:0;font-size:12px;font-weight:500;letter-spacing:.18em;text-transform:uppercase;color:#ffffff73}.trc-footer__list{display:grid;gap:14px;margin:20px 0 0;padding:0;list-style:none;font-size:15px}.trc-footer__link{color:#ffffffd9;text-decoration:none;transition:color .2s ease}.trc-footer__link:hover{color:var(--trc-accent)}.trc-footer__bottom{display:flex;flex-direction:column;gap:20px;padding-block:24px;border-top:1px solid rgba(255,255,255,.1);font-size:14px;color:#ffffff8c}.trc-footer__copyright{margin:0}.trc-footer__legal{display:flex;flex-wrap:wrap;gap:8px 24px}.trc-footer__legal-link{color:inherit;text-decoration:none;transition:color .2s ease}.trc-footer__legal-link:hover{color:var(--trc-fg)}@media(min-width:640px){.trc-footer{padding:0 16px 16px}.trc-footer__card{padding-inline:40px}.trc-footer__columns{grid-auto-columns:minmax(0,1fr);grid-auto-flow:column;grid-template-columns:none}}@media(min-width:768px){.trc-footer__bottom{flex-direction:row;align-items:center;justify-content:space-between}}@media(min-width:1024px){.trc-footer__main{grid-template-columns:1.2fr 2fr}}.trc-header__logo:focus-visible,.trc-header__link:focus-visible,.trc-header__burger:focus-visible,.trc-dropdown__item:focus-visible,.trc-drawer__close:focus-visible,.trc-mobile-nav a:focus-visible,.trc-footer a:focus-visible{outline:2px solid var(--trc-accent);outline-offset:4px;border-radius:4px}.trc-dropdown__item:focus-visible{outline-offset:-2px;border-radius:12px}.trc-hero-inset{box-sizing:border-box;padding:8px}@media(min-width:640px){.trc-hero-inset{padding:16px}}.trc-hero__media{position:absolute;inset:0;z-index:-2}.trc-hero__media>img,.trc-hero__media>picture,.trc-hero__image{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}.trc-page-hero{position:relative;isolation:isolate;max-width:1600px;margin-inline:auto;overflow:hidden;border-radius:var(--trc-radius);background:var(--trc-surface);color:var(--trc-fg)}.trc-page-hero__glow{position:absolute;inset:0;background:radial-gradient(ellipse at 85% 0%,color-mix(in srgb,var(--trc-accent) 16%,transparent),transparent 60%)}.trc-page-hero__veil{position:absolute;inset:0;z-index:-1;background:linear-gradient(100deg,#0b0c0ff7,#0b0c0fd9,#0b0c0f8c)}.trc-page-hero:not(:has(img,picture,video)) .trc-page-hero__veil{display:none}.trc-page-hero__content{box-sizing:border-box;max-width:1280px;margin-inline:auto;padding:144px 24px 64px}.trc-page-hero__title{max-width:56rem;font-size:clamp(2.25rem,1.6rem + 3vw,3.75rem)}.trc-page-hero__description{max-width:42rem;margin:24px 0 0;font-size:1.125rem;line-height:1.65;color:var(--trc-fg-muted)}.trc-page-hero__meta{margin-top:24px;font-size:14px;color:var(--trc-fg-subtle)}.trc-page-hero__actions{display:flex;flex-wrap:wrap;gap:12px;margin-top:32px}@media(min-width:640px){.trc-page-hero__content{padding-inline:40px}}@media(min-width:768px){.trc-page-hero__content{padding-block:176px 80px}}.trc-hero-video{position:relative;isolation:isolate;display:flex;flex-direction:column;max-width:1600px;min-height:calc(100svh - 16px);margin-inline:auto;overflow:hidden;border-radius:var(--trc-radius);background:var(--trc-surface);color:var(--trc-fg);clip-path:inset(0 round var(--trc-radius))}@media(min-width:640px){.trc-hero-video{min-height:calc(100svh - 32px)}}.trc-hero-video__media{inset:-16px 0 -128px;will-change:transform}.trc-hero-video__clip{opacity:0;transition-property:opacity;transition-timing-function:ease-in-out}.trc-hero-video__clip--active{opacity:1}.trc-hero-video__veil{position:absolute;inset:0;z-index:-1;background:linear-gradient(to top,#0b0c0ff2,#0b0c0f8c 40%,#0b0c0f1a 75%),linear-gradient(to right,rgba(11,12,15,.6),transparent 60%),#00000073}.trc-hero-video__content{box-sizing:border-box;display:grid;align-items:end;gap:40px;margin-top:auto;padding:144px 24px 40px}.trc-hero-video__main{max-width:48rem}@media(min-width:640px){.trc-hero-video__content{padding:160px 40px 56px}}@media(min-width:1024px){.trc-hero-video__content{grid-template-columns:1fr auto}}.trc-back-to-top{position:fixed;right:16px;bottom:16px;z-index:40;display:flex;align-items:center;justify-content:center;width:48px;height:48px;padding:0;border:0;border-radius:50%;background:var(--trc-accent);color:var(--trc-on-accent);box-shadow:0 10px 30px -10px color-mix(in srgb,var(--trc-accent) 60%,transparent);cursor:pointer;opacity:0;pointer-events:none;transform:translateY(16px);transition:opacity .3s ease,transform .3s ease}.trc-back-to-top--visible{opacity:1;pointer-events:auto;transform:translateY(0)}.trc-back-to-top--visible:hover{transform:translateY(-2px)}.trc-back-to-top:focus-visible{outline:none;box-shadow:var(--trc-ring)}.trc-back-to-top svg{width:20px;height:20px}@media(min-width:640px){.trc-back-to-top{right:32px;bottom:32px}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,80 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trc-ui",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React components with a deep black design: near-black backgrounds, graphite cards, thin headings and pill buttons.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Aurel Agbado",
|
|
8
|
+
"email": "agbadoaurel@gmail.com",
|
|
9
|
+
"url": "https://www.theringconcept.com/"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/aa404/trc-ui#readme",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/aa404/trc-ui.git",
|
|
15
|
+
"directory": "packages/trc-ui"
|
|
16
|
+
},
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/aa404/trc-ui/issues"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"react",
|
|
22
|
+
"react-components",
|
|
23
|
+
"ui",
|
|
24
|
+
"ui-kit",
|
|
25
|
+
"component-library",
|
|
26
|
+
"design-system",
|
|
27
|
+
"dark-theme",
|
|
28
|
+
"nextjs",
|
|
29
|
+
"landing-page",
|
|
30
|
+
"typescript"
|
|
31
|
+
],
|
|
32
|
+
"type": "module",
|
|
33
|
+
"sideEffects": [
|
|
34
|
+
"*.css"
|
|
35
|
+
],
|
|
36
|
+
"main": "./dist/index.cjs",
|
|
37
|
+
"module": "./dist/index.js",
|
|
38
|
+
"types": "./dist/index.d.ts",
|
|
39
|
+
"exports": {
|
|
40
|
+
".": {
|
|
41
|
+
"import": {
|
|
42
|
+
"types": "./dist/index.d.ts",
|
|
43
|
+
"default": "./dist/index.js"
|
|
44
|
+
},
|
|
45
|
+
"require": {
|
|
46
|
+
"types": "./dist/index.d.cts",
|
|
47
|
+
"default": "./dist/index.cjs"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"./styles.css": "./dist/styles.css",
|
|
51
|
+
"./package.json": "./package.json"
|
|
52
|
+
},
|
|
53
|
+
"files": [
|
|
54
|
+
"dist",
|
|
55
|
+
"README.md",
|
|
56
|
+
"LICENSE",
|
|
57
|
+
"CHANGELOG.md"
|
|
58
|
+
],
|
|
59
|
+
"publishConfig": {
|
|
60
|
+
"access": "public"
|
|
61
|
+
},
|
|
62
|
+
"scripts": {
|
|
63
|
+
"build": "tsup",
|
|
64
|
+
"build:watch": "tsup --watch",
|
|
65
|
+
"typecheck": "tsc --noEmit",
|
|
66
|
+
"prepublishOnly": "npm run typecheck && npm run build"
|
|
67
|
+
},
|
|
68
|
+
"peerDependencies": {
|
|
69
|
+
"react": ">=18",
|
|
70
|
+
"react-dom": ">=18"
|
|
71
|
+
},
|
|
72
|
+
"devDependencies": {
|
|
73
|
+
"tsup": "^9.0.0",
|
|
74
|
+
"typescript": "^5.9.3",
|
|
75
|
+
"react": "^19.3.1",
|
|
76
|
+
"react-dom": "^19.3.1",
|
|
77
|
+
"@types/react": "^19.3.0",
|
|
78
|
+
"@types/react-dom": "^19.3.0"
|
|
79
|
+
}
|
|
80
|
+
}
|