@stasho/ds 0.15.5 → 0.16.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stasho/ds",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "stasho design system",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"./drawer": "./src/components/drawer/drawer.tsx",
|
|
52
52
|
"./empty-state": "./src/components/empty-state/empty-state.tsx",
|
|
53
53
|
"./logo": "./src/components/logo/logo.tsx",
|
|
54
|
+
"./logo-mark": "./src/components/logo/logo-mark.tsx",
|
|
54
55
|
"./progress-bar": "./src/components/progress-bar/progress-bar.tsx",
|
|
55
56
|
"./stepper": "./src/components/stepper/stepper.tsx",
|
|
56
57
|
"./loader": "./src/components/loader/loader.tsx",
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, forwardRef } from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@ac/lib/cn";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Palettes for {@link LogoMark}. These are fixed brand hexes, deliberately NOT
|
|
7
|
+
* theme tokens: the mark is exported to PNG, uploaded to third-party surfaces
|
|
8
|
+
* (GitHub App avatar, favicons, social cards) and must render identically
|
|
9
|
+
* everywhere, including where our CSS never loads. `void` matches the cyan and
|
|
10
|
+
* ground already shipped in the app's own `logo.png`.
|
|
11
|
+
*/
|
|
12
|
+
const MARK_PALETTES = {
|
|
13
|
+
void: { bg: "#07080a", fg: "#22d3ee" },
|
|
14
|
+
cyan: { bg: "#22d3ee", fg: "#07080a" },
|
|
15
|
+
deep: { bg: "#00004e", fg: "#22d3ee" },
|
|
16
|
+
mono: { bg: "#07080a", fg: "#ffffff" },
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
type MarkPalette = keyof typeof MARK_PALETTES;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The lowercase "s" of the stasho wordmark, as real outlines.
|
|
23
|
+
*
|
|
24
|
+
* Provenance: Anybody, weight 900, `wdth` axis instantiated to 100, glyph "s"
|
|
25
|
+
* converted to a path with fontTools, then sheared by 0.25 — the exact
|
|
26
|
+
* synthetic-oblique transform Chromium applies, since Google Fonts serves
|
|
27
|
+
* Anybody with `font-style: normal` only and no italic face exists. Verified
|
|
28
|
+
* at 0.000% pixel difference against the browser's own rendering.
|
|
29
|
+
*
|
|
30
|
+
* Outlines, not `<text>`, on purpose: LogoWordmark/LogoLetter render live text
|
|
31
|
+
* and so depend on the consuming app having loaded Anybody, which is what made
|
|
32
|
+
* their viewBoxes wrong for months. This mark has no font dependency at all.
|
|
33
|
+
*
|
|
34
|
+
* Scaled so the glyph's farthest point sits 14% of the frame inside the edge —
|
|
35
|
+
* measured against the inscribed CIRCLE, not the square, so the mark keeps a
|
|
36
|
+
* real ring of air when a platform crops it to a badge.
|
|
37
|
+
*/
|
|
38
|
+
const MARK_PATH =
|
|
39
|
+
"M230.88 392.47Q297.95 392.47 340.42 372.64Q382.88 352.81 395.74 301.37Q406.11 259.89 377.92 243.01Q349.74 226.13 301.92 221.6Q267.59 217.52 245.75 215.59Q223.91 213.66 226.85 201.88Q228.95 193.49 239.09 189.19Q249.23 184.88 268.72 184.88Q290.25 184.88 304.95 194.06Q319.65 203.24 322.66 215.7L420.16 182.84Q416.48 147.72 380.7 133.55Q344.92 119.39 286.45 119.39Q225.27 119.39 181.22 138.77Q137.17 158.14 126.18 202.11Q115.47 244.94 140.14 264.99Q164.82 285.05 213.65 290.03Q249.74 294.34 272.77 296.04Q295.8 297.74 292.97 309.07Q290.7 318.13 278.52 322.44Q266.34 326.75 248.89 326.75Q223.51 326.75 208.16 317.91Q192.8 309.07 190.08 295.47L92.47 328.79Q97.68 363.23 135.61 377.85Q173.54 392.47 230.88 392.47Z";
|
|
40
|
+
|
|
41
|
+
interface LogoMarkProps
|
|
42
|
+
extends Omit<ComponentPropsWithoutRef<"svg">, "viewBox" | "xmlns"> {
|
|
43
|
+
/** Brand palette. Defaults to `void` (cyan on near-black). */
|
|
44
|
+
palette?: MarkPalette;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* stasho badge mark — the wordmark's "s" inside a filled square, with a ring of
|
|
49
|
+
* air sized for circular cropping. Use where a platform wants a self-contained
|
|
50
|
+
* avatar (GitHub App, favicon, social profile) rather than the line-art
|
|
51
|
+
* {@link Logo}, which inherits `currentColor`.
|
|
52
|
+
*
|
|
53
|
+
* The mark carries its own background, so it does NOT follow the theme. For a
|
|
54
|
+
* circular badge, round it with a class: `className="rounded-full"`.
|
|
55
|
+
*/
|
|
56
|
+
const LogoMark = forwardRef<SVGSVGElement, LogoMarkProps>(
|
|
57
|
+
({ palette = "void", className, ...rest }, ref) => {
|
|
58
|
+
const { bg, fg } = MARK_PALETTES[palette];
|
|
59
|
+
return (
|
|
60
|
+
<svg
|
|
61
|
+
ref={ref}
|
|
62
|
+
viewBox="0 0 512 512"
|
|
63
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
64
|
+
className={cn("shrink-0", className)}
|
|
65
|
+
{...rest}
|
|
66
|
+
>
|
|
67
|
+
<rect width="512" height="512" fill={bg} />
|
|
68
|
+
<path d={MARK_PATH} fill={fg} />
|
|
69
|
+
</svg>
|
|
70
|
+
);
|
|
71
|
+
},
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
LogoMark.displayName = "LogoMark";
|
|
75
|
+
|
|
76
|
+
export { LogoMark, MARK_PALETTES, MARK_PATH };
|
|
77
|
+
export type { LogoMarkProps, MarkPalette };
|
|
@@ -2,92 +2,89 @@ import { type ComponentPropsWithoutRef, forwardRef } from "react";
|
|
|
2
2
|
|
|
3
3
|
import { cn } from "@ac/lib/cn";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import { MARK_PATH } from "./logo-mark";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* stasho
|
|
9
|
-
*
|
|
8
|
+
* The stasho logotype, as real outlines.
|
|
9
|
+
*
|
|
10
|
+
* Every mark here is the Anybody 900 glyph set converted to paths with
|
|
11
|
+
* fontTools and sheared by 0.25 — the exact synthetic-oblique transform
|
|
12
|
+
* Chromium applies, since Google Fonts serves Anybody with `font-style:
|
|
13
|
+
* normal` only and no italic face exists. Per-glyph pen positions were read
|
|
14
|
+
* back from the browser (`getStartPositionOfChar`) so kerning matches what
|
|
15
|
+
* live text produced.
|
|
16
|
+
*
|
|
17
|
+
* These replaced live `<text>` elements, which made every mark depend on the
|
|
18
|
+
* CONSUMING app having loaded Anybody. That dependency is why the viewBoxes
|
|
19
|
+
* were once fitted to the fallback font and clipped the trailing glyph for
|
|
20
|
+
* months (Decision #105). Outlines cannot drift that way.
|
|
21
|
+
*
|
|
22
|
+
* viewBoxes and glyph positions are byte-identical to the `<text>` versions
|
|
23
|
+
* they replace, so nothing moved: verified at 4x against the old rendering
|
|
24
|
+
* with zero pixels flipping between ink and ground (max channel delta 79/255,
|
|
25
|
+
* confined to antialiased edges).
|
|
26
|
+
*
|
|
27
|
+
* The icon paths before this were inherited from the @aleph-front/ds fork —
|
|
28
|
+
* Aleph Cloud's mark, not ours, despite a doc comment that claimed otherwise.
|
|
29
|
+
*
|
|
30
|
+
* There is deliberately no combined "icon + wordmark" lockup. With the icon
|
|
31
|
+
* being the letter "s", any lockup repeats the word's own first letter, and a
|
|
32
|
+
* badge-plus-wordmark version was tried and rejected. The full logo IS the
|
|
33
|
+
* wordmark; use {@link Logo} or {@link LogoMark} where a standalone mark is
|
|
34
|
+
* wanted.
|
|
10
35
|
*/
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
<svg
|
|
14
|
-
ref={ref}
|
|
15
|
-
viewBox="0 0 209 209"
|
|
16
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
-
fill="currentColor"
|
|
18
|
-
className={cn("shrink-0", className)}
|
|
19
|
-
{...rest}
|
|
20
|
-
>
|
|
21
|
-
<path d="M170.448 76.895c21.371 0 38.552-17.181 38.552-38.447C209 17.18 191.714 0 170.448 0c-21.372 0-38.552 17.181-38.552 38.448 0 21.266 17.18 38.447 38.552 38.447Z" />
|
|
22
|
-
<path d="M38.553 208.057c21.371 0 38.552-17.181 38.552-38.448 0-21.267-17.286-38.448-38.552-38.448C17.181 131.161 0 148.342 0 169.609c-.104 21.267 17.182 38.448 38.553 38.448Z" />
|
|
23
|
-
<path d="M143.106 11.314C106.544-3.772 62.858 3.457 33.106 33 3.353 62.647-3.875 106.019 11.21 142.476L143.106 11.314Z" />
|
|
24
|
-
<path d="M65.792 196.847c36.562 15.086 80.247 7.857 110-21.686 29.752-29.647 36.98-73.018 21.895-109.475L65.792 196.847Z" />
|
|
25
|
-
</svg>
|
|
26
|
-
),
|
|
27
|
-
);
|
|
36
|
+
const WORDMARK_PATH =
|
|
37
|
+
"M74.38 180.9Q103.98 180.9 122.71 172.15Q141.45 163.4 147.12 140.7Q151.7 122.4 139.26 114.95Q126.83 107.5 105.73 105.5Q90.58 103.7 80.94 102.85Q71.3 102 72.6 96.8Q73.53 93.1 78 91.2Q82.48 89.3 91.08 89.3Q100.58 89.3 107.06 93.35Q113.55 97.4 114.88 102.9L157.9 88.4Q156.28 72.9 140.49 66.65Q124.7 60.4 98.9 60.4Q71.9 60.4 52.46 68.95Q33.02 77.5 28.18 96.9Q23.45 115.8 34.34 124.65Q45.23 133.5 66.78 135.7Q82.7 137.6 92.86 138.35Q103.03 139.1 101.78 144.1Q100.78 148.1 95.4 150Q90.03 151.9 82.33 151.9Q71.13 151.9 64.35 148Q57.58 144.1 56.38 138.1L13.3 152.8Q15.6 168 32.34 174.45Q49.08 180.9 74.38 180.9ZM212.97 181.7Q228.77 181.7 243.95 178.6L251.35 149Q243.47 151.7 235.97 151.7Q229.37 151.7 226.25 149.2Q223.12 146.7 225.25 138.2L236.75 92.2H270.95L278.65 61.4H244.45L251.27 34.1H206.07L199.25 61.4H172.85L165.15 92.2H191.55L177.65 147.8Q172.92 166.7 183.9 174.2Q194.87 181.7 212.97 181.7ZM309.35 181.4Q316.25 181.4 322.92 180.3Q329.6 179.2 335.42 177.3Q341.25 175.4 345.76 172.95Q350.27 170.5 352.87 167.7L353.8 180H391.3L409.47 107.3Q413.8 90 408.97 79.7Q404.15 69.4 390.8 64.8Q377.45 60.2 355.95 60.2Q344.85 60.2 333.95 61.8Q323.05 63.4 313.37 66.9Q303.7 70.4 295.97 76.3Q288.25 82.2 283.6 90.8L324.57 103.3Q327.47 98.1 331.43 95.25Q335.4 92.4 339.87 91.3Q344.35 90.2 348.65 90.2Q354.85 90.2 358.92 91.5Q363 92.8 364.56 95.95Q366.12 99.1 364.7 104.8L364.02 107.5H327.72Q315.02 107.5 305.12 109.5Q295.22 111.5 288 115.8Q280.77 120.1 276.05 127Q271.32 133.9 268.85 143.8Q266.2 154.4 267.58 161.65Q268.97 168.9 274.28 173.25Q279.6 177.6 288.37 179.5Q297.15 181.4 309.35 181.4ZM326.8 152.8Q323.4 152.8 320.82 152.3Q318.25 151.8 316.63 150.65Q315.02 149.5 314.58 147.45Q314.15 145.4 314.97 142.1Q315.82 138.7 317.25 136.6Q318.67 134.5 320.73 133.45Q322.8 132.4 325.75 132Q328.7 131.6 332.5 131.6H357.3L354.1 144.4Q351.4 146.8 346.86 148.75Q342.32 150.7 337.06 151.75Q331.8 152.8 326.8 152.8ZM474.88 180.9Q504.48 180.9 523.21 172.15Q541.95 163.4 547.62 140.7Q552.2 122.4 539.76 114.95Q527.33 107.5 506.23 105.5Q491.07 103.7 481.44 102.85Q471.8 102 473.1 96.8Q474.02 93.1 478.5 91.2Q482.98 89.3 491.57 89.3Q501.07 89.3 507.56 93.35Q514.05 97.4 515.38 102.9L558.4 88.4Q556.77 72.9 540.99 66.65Q525.2 60.4 499.4 60.4Q472.4 60.4 452.96 68.95Q433.52 77.5 428.68 96.9Q423.95 115.8 434.84 124.65Q445.73 133.5 467.27 135.7Q483.2 137.6 493.36 138.35Q503.52 139.1 502.27 144.1Q501.27 148.1 495.9 150Q490.52 151.9 482.82 151.9Q471.62 151.9 464.85 148Q458.07 144.1 456.88 138.1L413.8 152.8Q416.1 168 432.84 174.45Q449.57 180.9 474.88 180.9ZM551.59 180H596.79L636.04 23H590.84ZM632.19 180H677.29L692.51 119.1Q699.06 92.9 694.06 76.7Q689.06 60.5 664.26 60.5Q637.16 60.5 616.2 77.75Q595.24 95 591.06 111.7L610.91 120.3Q614.24 107 622.4 99.15Q630.56 91.3 639.26 91.3Q647.06 91.3 649.33 96.85Q651.59 102.4 646.84 121.4ZM759.57 180.9Q797.37 180.9 816.19 164.4Q835.02 147.9 841.97 120.1Q848.94 92.2 838.27 76.1Q827.59 60 789.79 60Q752.09 60 733.32 76.1Q714.54 92.2 707.57 120.1Q700.62 147.9 711.24 164.4Q721.87 180.9 759.57 180.9ZM767.14 150.6Q757.44 150.6 752.58 145.25Q747.72 139.9 752.62 120.3Q757.52 100.7 765.02 95.5Q772.52 90.3 782.22 90.3Q792.02 90.3 796.87 95.5Q801.72 100.7 796.82 120.3Q791.92 139.9 784.43 145.25Q776.94 150.6 767.14 150.6Z";
|
|
28
38
|
|
|
29
|
-
|
|
39
|
+
const LETTER_PATH =
|
|
40
|
+
"M74.38 180.9Q103.98 180.9 122.71 172.15Q141.45 163.4 147.12 140.7Q151.7 122.4 139.26 114.95Q126.83 107.5 105.73 105.5Q90.58 103.7 80.94 102.85Q71.3 102 72.6 96.8Q73.53 93.1 78 91.2Q82.48 89.3 91.08 89.3Q100.58 89.3 107.06 93.35Q113.55 97.4 114.88 102.9L157.9 88.4Q156.28 72.9 140.49 66.65Q124.7 60.4 98.9 60.4Q71.9 60.4 52.46 68.95Q33.02 77.5 28.18 96.9Q23.45 115.8 34.34 124.65Q45.23 133.5 66.78 135.7Q82.7 137.6 92.86 138.35Q103.03 139.1 101.78 144.1Q100.78 148.1 95.4 150Q90.03 151.9 82.33 151.9Q71.13 151.9 64.35 148Q57.58 144.1 56.38 138.1L13.3 152.8Q15.6 168 32.34 174.45Q49.08 180.9 74.38 180.9Z";
|
|
41
|
+
|
|
42
|
+
type LogoProps = Omit<
|
|
43
|
+
ComponentPropsWithoutRef<"svg">,
|
|
44
|
+
"viewBox" | "xmlns" | "title"
|
|
45
|
+
> & {
|
|
46
|
+
/**
|
|
47
|
+
* Accessible name, rendered as `<title>`. Defaults to "stasho". Pass `null`
|
|
48
|
+
* for a purely decorative mark, or set `aria-hidden` on the element.
|
|
49
|
+
*/
|
|
50
|
+
title?: string | null;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const DEFAULT_TITLE = "stasho";
|
|
54
|
+
|
|
55
|
+
function Title({ title }: { title: string | null | undefined }) {
|
|
56
|
+
const value = title === undefined ? DEFAULT_TITLE : title;
|
|
57
|
+
return value === null ? null : <title>{value}</title>;
|
|
58
|
+
}
|
|
30
59
|
|
|
31
60
|
/**
|
|
32
|
-
* stasho
|
|
33
|
-
*
|
|
61
|
+
* stasho icon mark — the wordmark's "s" on a square canvas, sharing its
|
|
62
|
+
* geometry with {@link LogoMark} (14% of the frame clear of the edge, measured
|
|
63
|
+
* against the inscribed circle) but transparent and inheriting
|
|
64
|
+
* `currentColor`. Use for square placements; use `LogoMark` where the mark
|
|
65
|
+
* needs to carry its own background.
|
|
34
66
|
*/
|
|
35
|
-
const
|
|
36
|
-
({ className, ...rest }, ref) => (
|
|
67
|
+
const Logo = forwardRef<SVGSVGElement, LogoProps>(
|
|
68
|
+
({ className, title, ...rest }, ref) => (
|
|
37
69
|
<svg
|
|
38
70
|
ref={ref}
|
|
39
|
-
viewBox="0 0
|
|
71
|
+
viewBox="0 0 512 512"
|
|
40
72
|
xmlns="http://www.w3.org/2000/svg"
|
|
41
73
|
fill="currentColor"
|
|
42
74
|
className={cn("shrink-0", className)}
|
|
43
75
|
{...rest}
|
|
44
76
|
>
|
|
45
|
-
{
|
|
46
|
-
<
|
|
47
|
-
x="261"
|
|
48
|
-
y="180"
|
|
49
|
-
fill="currentColor"
|
|
50
|
-
fontFamily="inherit"
|
|
51
|
-
fontSize="200"
|
|
52
|
-
fontWeight="600"
|
|
53
|
-
>
|
|
54
|
-
stasho
|
|
55
|
-
</text>
|
|
56
|
-
{/* Icon mark */}
|
|
57
|
-
<path d="M170.448 76.895c21.371 0 38.552-17.181 38.552-38.447C209 17.18 191.714 0 170.448 0c-21.372 0-38.552 17.181-38.552 38.448 0 21.266 17.18 38.447 38.552 38.447Z" />
|
|
58
|
-
<path d="M38.553 208.056c21.371 0 38.552-17.18 38.552-38.447 0-21.267-17.286-38.448-38.552-38.448C17.181 131.161 0 148.342 0 169.609c-.104 21.267 17.182 38.447 38.553 38.447Z" />
|
|
59
|
-
<path d="M143.106 11.314C106.544-3.772 62.858 3.457 33.106 33 3.353 62.647-3.875 106.019 11.21 142.476L143.106 11.314Z" />
|
|
60
|
-
<path d="M65.792 196.847c36.562 15.086 80.247 7.857 110-21.686 29.752-29.647 36.98-73.018 21.895-109.475L65.792 196.847Z" />
|
|
77
|
+
<Title title={title} />
|
|
78
|
+
<path d={MARK_PATH} />
|
|
61
79
|
</svg>
|
|
62
80
|
),
|
|
63
81
|
);
|
|
64
82
|
|
|
65
|
-
|
|
83
|
+
Logo.displayName = "Logo";
|
|
66
84
|
|
|
67
|
-
/**
|
|
68
|
-
* stasho wordmark only, no icon (placeholder logotype, rebrand still deferred).
|
|
69
|
-
* Set in Anybody 800 italic to match the brand headings; the consuming app must
|
|
70
|
-
* load Anybody or it falls back to sans-serif. Inherits color from parent via
|
|
71
|
-
* `currentColor`.
|
|
72
|
-
*
|
|
73
|
-
* The wordmark is live `<text>`, so its width is decided by whichever faces the
|
|
74
|
-
* consuming app actually loaded — not by anything this component controls. The
|
|
75
|
-
* viewBox must therefore clear the WIDEST realistic rendering: overflow clips a
|
|
76
|
-
* glyph, while underflow only leaves benign trailing space. Measured at
|
|
77
|
-
* font-size 200, `font-stretch: normal` (Chromium, 2026-08-21): Anybody 800/900
|
|
78
|
-
* italic 848.9, Anybody 800 upright 833.1, Anybody 700 italic 777.6, generic
|
|
79
|
-
* sans-serif fallback ~650. 880 clears the widest with headroom.
|
|
80
|
-
*
|
|
81
|
-
* Two known ways past 880, both requiring a consumer to opt in: Anybody ships a
|
|
82
|
-
* `wdth` 75..125 axis, and `font-stretch` inherits into SVG `<text>` — at
|
|
83
|
-
* `wdth` 125 this measures 1046. Nothing sets it today; the numbers above
|
|
84
|
-
* assume `wdth` 100.
|
|
85
|
-
*
|
|
86
|
-
* The previous 654 was fitted to the generic sans-serif FALLBACK, not to
|
|
87
|
-
* Anybody, and clipped the trailing "o" by ~30% wherever Anybody loaded.
|
|
88
|
-
*/
|
|
85
|
+
/** "stasho" wordmark, no icon. Set the height and use `w-auto`. */
|
|
89
86
|
const LogoWordmark = forwardRef<SVGSVGElement, LogoProps>(
|
|
90
|
-
({ className, ...rest }, ref) => (
|
|
87
|
+
({ className, title, ...rest }, ref) => (
|
|
91
88
|
<svg
|
|
92
89
|
ref={ref}
|
|
93
90
|
viewBox="0 0 880 229"
|
|
@@ -96,17 +93,8 @@ const LogoWordmark = forwardRef<SVGSVGElement, LogoProps>(
|
|
|
96
93
|
className={cn("shrink-0", className)}
|
|
97
94
|
{...rest}
|
|
98
95
|
>
|
|
99
|
-
<
|
|
100
|
-
|
|
101
|
-
y="180"
|
|
102
|
-
fill="currentColor"
|
|
103
|
-
fontFamily="Anybody, sans-serif"
|
|
104
|
-
fontSize="200"
|
|
105
|
-
fontWeight="800"
|
|
106
|
-
fontStyle="italic"
|
|
107
|
-
>
|
|
108
|
-
stasho
|
|
109
|
-
</text>
|
|
96
|
+
<Title title={title} />
|
|
97
|
+
<path d={WORDMARK_PATH} />
|
|
110
98
|
</svg>
|
|
111
99
|
),
|
|
112
100
|
);
|
|
@@ -114,18 +102,13 @@ const LogoWordmark = forwardRef<SVGSVGElement, LogoProps>(
|
|
|
114
102
|
LogoWordmark.displayName = "LogoWordmark";
|
|
115
103
|
|
|
116
104
|
/**
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* Same live-`<text>` sizing rule as LogoWordmark above — the viewBox clears the
|
|
123
|
-
* widest realistic rendering. Measured at font-size 200 (Chromium, 2026-08-21):
|
|
124
|
-
* Anybody 800/900 italic "s" 157.9. 164 clears it with ~3.9% headroom. The
|
|
125
|
-
* previous 119 clipped the single glyph by ~33%.
|
|
105
|
+
* Single "s" for collapsed placements. Shares {@link Logo}'s glyph but keeps
|
|
106
|
+
* the wordmark's 229-tall box and baseline, so it lines up with
|
|
107
|
+
* {@link LogoWordmark} when the two are swapped in place — which is exactly
|
|
108
|
+
* what the Sidebar does when it collapses.
|
|
126
109
|
*/
|
|
127
110
|
const LogoLetter = forwardRef<SVGSVGElement, LogoProps>(
|
|
128
|
-
({ className, ...rest }, ref) => (
|
|
111
|
+
({ className, title, ...rest }, ref) => (
|
|
129
112
|
<svg
|
|
130
113
|
ref={ref}
|
|
131
114
|
viewBox="0 0 164 229"
|
|
@@ -134,22 +117,13 @@ const LogoLetter = forwardRef<SVGSVGElement, LogoProps>(
|
|
|
134
117
|
className={cn("shrink-0", className)}
|
|
135
118
|
{...rest}
|
|
136
119
|
>
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
y="180"
|
|
140
|
-
fill="currentColor"
|
|
141
|
-
fontFamily="Anybody, sans-serif"
|
|
142
|
-
fontSize="200"
|
|
143
|
-
fontWeight="800"
|
|
144
|
-
fontStyle="italic"
|
|
145
|
-
>
|
|
146
|
-
s
|
|
147
|
-
</text>
|
|
120
|
+
<Title title={title} />
|
|
121
|
+
<path d={LETTER_PATH} />
|
|
148
122
|
</svg>
|
|
149
123
|
),
|
|
150
124
|
);
|
|
151
125
|
|
|
152
126
|
LogoLetter.displayName = "LogoLetter";
|
|
153
127
|
|
|
154
|
-
export { Logo,
|
|
128
|
+
export { Logo, LogoWordmark, LogoLetter };
|
|
155
129
|
export type { LogoProps };
|