@dillingerstaffing/strand-ui 0.4.0 → 0.5.1

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": "@dillingerstaffing/strand-ui",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "Strand UI - Preact/React component library built on the Strand Design Language",
5
5
  "author": "Dillinger Staffing <engineering@dillingerstaffing.com> (https://dillingerstaffing.com)",
6
6
  "license": "MIT",
@@ -60,7 +60,7 @@
60
60
  }
61
61
  },
62
62
  "dependencies": {
63
- "@dillingerstaffing/strand": "^0.4.0"
63
+ "@dillingerstaffing/strand": "^0.5.1"
64
64
  },
65
65
  "devDependencies": {
66
66
  "@testing-library/preact": "^3.2.0",
@@ -0,0 +1,44 @@
1
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2
+
3
+ /* ── Layout ── */
4
+ .strand-code-block {
5
+ position: relative;
6
+ }
7
+
8
+ /* ── Label (optional language indicator) ── */
9
+ .strand-code-block__label {
10
+ display: block;
11
+ font-family: var(--strand-font-mono);
12
+ font-size: var(--strand-text-xs);
13
+ font-weight: var(--strand-weight-medium);
14
+ letter-spacing: var(--strand-tracking-widest);
15
+ text-transform: uppercase;
16
+ color: var(--strand-gray-500);
17
+ margin-bottom: var(--strand-space-2);
18
+ }
19
+
20
+ /* ── Code area ── */
21
+ .strand-code-block__pre {
22
+ font-family: var(--strand-font-mono);
23
+ font-size: var(--strand-text-sm);
24
+ line-height: var(--strand-leading-relaxed);
25
+ color: var(--strand-blue-midnight);
26
+ background: var(--strand-surface-recessed);
27
+ box-shadow: inset 0 1px 3px rgba(15, 23, 42, 0.06);
28
+ border-radius: var(--strand-radius-lg);
29
+ padding: var(--strand-space-3) var(--strand-space-4);
30
+ overflow-x: auto;
31
+ white-space: pre;
32
+ tab-size: 2;
33
+ margin: 0;
34
+ }
35
+
36
+ /* ── Inline code ── */
37
+ .strand-code-inline {
38
+ font-family: var(--strand-font-mono);
39
+ font-size: 0.875em;
40
+ color: var(--strand-blue-deep);
41
+ background: var(--strand-surface-recessed);
42
+ padding: 0.125em 0.375em;
43
+ border-radius: var(--strand-radius-sm);
44
+ }
@@ -0,0 +1,90 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { render } from "@testing-library/preact";
3
+ import { CodeBlock } from "./CodeBlock.js";
4
+
5
+ describe("CodeBlock", () => {
6
+ // ── Rendering ──
7
+
8
+ it("renders code content", () => {
9
+ const { getByText } = render(
10
+ <CodeBlock code="console.log('hello')" />,
11
+ );
12
+ expect(getByText("console.log('hello')")).toBeTruthy();
13
+ });
14
+
15
+ it("renders as a div element", () => {
16
+ const { container } = render(
17
+ <CodeBlock code="test" />,
18
+ );
19
+ expect(container.firstElementChild?.tagName).toBe("DIV");
20
+ });
21
+
22
+ it("renders a pre element containing code", () => {
23
+ const { container } = render(
24
+ <CodeBlock code="test" />,
25
+ );
26
+ const pre = container.querySelector(".strand-code-block__pre");
27
+ expect(pre).toBeTruthy();
28
+ expect(pre?.tagName).toBe("PRE");
29
+ expect(pre?.querySelector("code")).toBeTruthy();
30
+ });
31
+
32
+ // ── Base class ──
33
+
34
+ it("applies strand-code-block base class", () => {
35
+ const { container } = render(
36
+ <CodeBlock code="test" />,
37
+ );
38
+ expect(container.firstElementChild?.className).toContain("strand-code-block");
39
+ });
40
+
41
+ // ── Language label ──
42
+
43
+ it("renders language label when provided", () => {
44
+ const { container } = render(
45
+ <CodeBlock code="npm install" language="bash" />,
46
+ );
47
+ const label = container.querySelector(".strand-code-block__label");
48
+ expect(label).toBeTruthy();
49
+ expect(label?.textContent).toBe("bash");
50
+ });
51
+
52
+ it("does not render label when language is omitted", () => {
53
+ const { container } = render(
54
+ <CodeBlock code="test" />,
55
+ );
56
+ const label = container.querySelector(".strand-code-block__label");
57
+ expect(label).toBeNull();
58
+ });
59
+
60
+ // ── Custom className ──
61
+
62
+ it("merges custom className with component classes", () => {
63
+ const { container } = render(
64
+ <CodeBlock code="test" className="custom" />,
65
+ );
66
+ const el = container.firstElementChild;
67
+ expect(el?.className).toContain("strand-code-block");
68
+ expect(el?.className).toContain("custom");
69
+ });
70
+
71
+ // ── Code whitespace ──
72
+
73
+ it("preserves whitespace in code content", () => {
74
+ const code = "function hello() {\n return 'world';\n}";
75
+ const { container } = render(
76
+ <CodeBlock code={code} />,
77
+ );
78
+ const codeEl = container.querySelector("code");
79
+ expect(codeEl?.textContent).toBe(code);
80
+ });
81
+
82
+ // ── Forwarded props ──
83
+
84
+ it("forwards additional props", () => {
85
+ const { container } = render(
86
+ <CodeBlock code="test" id="my-code" />,
87
+ );
88
+ expect(container.firstElementChild?.getAttribute("id")).toBe("my-code");
89
+ });
90
+ });
@@ -0,0 +1,33 @@
1
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2
+
3
+ import type { JSX } from "preact";
4
+ import { forwardRef } from "preact/compat";
5
+
6
+ export interface CodeBlockProps
7
+ extends Omit<JSX.HTMLAttributes<HTMLDivElement>, "label"> {
8
+ /** The code content to display */
9
+ code: string;
10
+ /** Optional language label (e.g. "html", "css", "bash") */
11
+ language?: string;
12
+ }
13
+
14
+ export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
15
+ ({ code, language, className = "", ...rest }, ref) => {
16
+ const classes = ["strand-code-block", className]
17
+ .filter(Boolean)
18
+ .join(" ");
19
+
20
+ return (
21
+ <div ref={ref} className={classes} {...rest}>
22
+ {language && (
23
+ <span className="strand-code-block__label">{language}</span>
24
+ )}
25
+ <pre className="strand-code-block__pre">
26
+ <code>{code}</code>
27
+ </pre>
28
+ </div>
29
+ );
30
+ },
31
+ );
32
+
33
+ CodeBlock.displayName = "CodeBlock";
@@ -0,0 +1,2 @@
1
+ export { CodeBlock } from "./CodeBlock.js";
2
+ export type { CodeBlockProps } from "./CodeBlock.js";
package/src/index.ts CHANGED
@@ -47,6 +47,9 @@ export type { TableProps, TableColumn } from "./components/Table/index.js";
47
47
  export { DataReadout } from "./components/DataReadout/index.js";
48
48
  export type { DataReadoutProps } from "./components/DataReadout/index.js";
49
49
 
50
+ export { CodeBlock } from "./components/CodeBlock/index.js";
51
+ export type { CodeBlockProps } from "./components/CodeBlock/index.js";
52
+
50
53
  // Layout components
51
54
  export { Stack } from "./components/Stack/index.js";
52
55
  export type { StackProps } from "./components/Stack/index.js";