diff --git a/.vscode/settings.json b/.vscode/settings.json index d62318597..88a37c0b7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,6 +6,7 @@ "eslint.validate": ["javascript", "javascriptreact", "astro", "typescript", "typescriptreact"], "stylelint.validate": ["html", "astro"], "cSpell.words": [ + "'s", "AACN", "Abbrs", "Acronis", @@ -55,6 +56,7 @@ "cpus", "criticals", "crossenv", + "ctlog", "CUDA", "cust", "cyclonedx", @@ -81,9 +83,11 @@ "encryptor", "enddt", "epoll", + "ESO", "etcdctl", "exfiltrated", "exfiltrates", + "exfiltrating", "EXIF", "fastly", "Favicons", @@ -139,6 +143,7 @@ "ILIKE", "IMDS", "incentivized", + "INCRBY", "inotify", "instrumenta", "interrobang", @@ -248,9 +253,11 @@ "oklch", "oncall", "Onest", + "OPA", "openslo", "optin", "OSSL", + "outofsync", "PABC", "pacticipant", "PERC", @@ -297,6 +304,7 @@ "registrator", "Rego", "Rekor", + "replcia", "repost", "reposts", "RGAA", diff --git a/_CHAT_BOT.md b/CHAT_BOT.md similarity index 100% rename from _CHAT_BOT.md rename to CHAT_BOT.md diff --git a/_CRM.md b/HUBSPOT.md similarity index 100% rename from _CRM.md rename to HUBSPOT.md diff --git a/MERMAID.md b/MERMAID.md index cad5c5b53..c4ca8d0cd 100644 --- a/MERMAID.md +++ b/MERMAID.md @@ -1,30 +1,60 @@ # Mermaid usage -## src/content/articles/opentelemetry-span-design-granularity-overhead/pdf.mdx +- `flowchart LR`, `flowchart TD` - shows a sequence of actions. +- `gantt` +- `graph TD` - legacy implementation, use `flowchart` instead. +- `sequenceDiagram` +- `stateDiagram-v2` - is meant for Finite State Machines (FSM), shows the status of a system at any given time. -```mermaid -gantt - title Trace Waterfall (readable) - dateFormat X - axisFormat %L ms +**Quick Comparison Table** - section Request - HTTP GET /orders/123 :a1, 0, 150 +| Type | Purpose | Key Feature | Syntax Note | +| :-------------------- | :------------------------------------ | :----------------------------------------------------------- | :----------------------------------------------------------- | +| **`flowchart`** | Visualizing processes or logic flows. | **Newest engine**: Supports subgraphs, better styling, and more shapes. | Use `flowchart TD` or `flowchart LR`. | +| **`graph`** | Legacy version of the flowchart. | Older engine with fewer features and more rigid layouts. | Often used interchangeably but lacks `flowchart`'s flexibility. | +| **`stateDiagram-v2`** | Modeling system behavior/states. | **UML-compliant**: Focuses on "States" and "Transitions." | Uses `[*] ->` for start/end points. | - section Cache - cache.get :a2, 5, 15 +## flowchart LR - section Database - db.query orders :a3, 20, 80 +```text +flowchart LR + subgraph correct[Correct: 1-100 spans] + B1[batch.process] --> E1[item.failed event] + B1 --> E2[item.failed event] + B1 --> A1[batch.successful: 9998] + end - section Enrichment - enrichOrder :a4, 85, 140 - http.get /customers/456 :a5, 90, 120 - http.get /products/789 :a6, 90, 110 + subgraph wrong[Wrong: 10,000 spans] + I1[process.item] --> I2[process.item] + I2 --> I3[process.item] + I3 --> I4[...9,997 more...] + end + + style correct fill:#9f9,color:#000 + style wrong fill:#f96,color:#000 ``` -Figure: Readable trace waterfall with clear hierarchy. ```mermaid +flowchart LR + subgraph correct[Correct: 1-100 spans] + B1[batch.process] --> E1[item.failed event] + B1 --> E2[item.failed event] + B1 --> A1[batch.successful: 9998] + end + + subgraph wrong[Wrong: 10,000 spans] + I1[process.item] --> I2[process.item] + I2 --> I3[process.item] + I3 --> I4[...9,997 more...] + end + + style correct fill:#9f9,color:#000 + style wrong fill:#f96,color:#000 +``` + +## flowchart TD + +```text flowchart TD A[Incoming Request] --> B{Head Sampling?} @@ -46,42 +76,87 @@ flowchart TD style H fill:#f96,color:#000 style G fill:#9f9,color:#000 ``` -Figure: Head sampling reduces overhead; tail sampling preserves interesting traces. ```mermaid -gantt - title Trace Waterfall (over-instrumented) - dateFormat X - axisFormat %L ms +flowchart TD + A[Incoming Request] --> B{Head Sampling?} - section Request - HTTP GET /orders/123 :a1, 0, 150 + B -->|Yes| C[Create Spans] + B -->|No| D[No Spans Created] - section Validation - validate.request :a2, 2, 5 - parse.json :a3, 5, 8 - validate.orderId :a4, 8, 10 + C --> E[Export to Collector] + E --> F{Tail Sampling?} - section Cache - cache.get :a5, 10, 12 - serialize.key :a6, 10, 11 - redis.get :a7, 11, 12 - deserialize.result :a8, 12, 13 + F -->|Error?| G[Keep] + F -->|Slow?| G + F -->|High-value?| G + F -->|Random 5%| G + F -->|Otherwise| H[Drop] - section Database - db.getConnection :a9, 15, 18 - db.query orders :a10, 18, 75 - db.releaseConnection :a11, 75, 77 - map.toEntity :a12, 77, 79 + G --> I[Storage Backend] - section Response - serialize.json :a13, 140, 145 - set.headers :a14, 145, 147 - send.response :a15, 147, 150 + style D fill:#f96,color:#000 + style H fill:#f96,color:#000 + style G fill:#9f9,color:#000 +``` + +## graph TD + +```text +graph TD + subgraph CP[Control Plane] + A[API Server] --> B[State Store] + A --> C[Controllers] + end + + D[Isolation Boundary] + + subgraph DP[Data Plane] + F[Worker Node 1] + G[Worker Node 2] + H[Worker Node 3] + end + + C -->|"Desired State"| D + D --> F + D --> G + D --> H + + F -->|"Actual State"| D + G -->|"Actual State"| D + H -->|"Actual State"| D + D --> C ``` -Figure: Over-instrumented trace—wall of spans obscures the critical path. ```mermaid +graph TD + subgraph CP[Control Plane] + A[API Server] --> B[State Store] + A --> C[Controllers] + end + + D[Isolation Boundary] + + subgraph DP[Data Plane] + F[Worker Node 1] + G[Worker Node 2] + H[Worker Node 3] + end + + C -->|"Desired State"| D + D --> F + D --> G + D --> H + + F -->|"Actual State"| D + G -->|"Actual State"| D + H -->|"Actual State"| D + D --> C +``` + +## sequenceDiagram + +```text sequenceDiagram participant Client participant API as API Service @@ -108,51 +183,154 @@ sequenceDiagram API-->>Client: Enriched order Note over API: Root span ends ``` -Figure: Request instrumentation sequence. ```mermaid -flowchart LR - subgraph correct[Correct: 1-100 spans] - B1[batch.process] --> E1[item.failed event] - B1 --> E2[item.failed event] - B1 --> A1[batch.successful: 9998] - end +sequenceDiagram + participant Client + participant API as API Service + participant Cache + participant DB as Database + participant Customers as Customers Service - subgraph wrong[Wrong: 10,000 spans] - I1[process.item] --> I2[process.item] - I2 --> I3[process.item] - I3 --> I4[...9,997 more...] - end + Client->>API: GET /orders/123 + Note over API: Root span: HTTP GET /orders/{id} - style correct fill:#9f9,color:#000 - style wrong fill:#f96,color:#000 + API->>Cache: Get order:123 + Note over API: Child span: cache.get + Cache-->>API: Miss + + API->>DB: SELECT * FROM orders + Note over API: Child span: db.query orders + DB-->>API: Order data + + API->>Customers: GET /customers/456 + Note over API: Child span: HTTP GET customers-service + Note over Customers: Continues trace + Customers-->>API: Customer data + + API-->>Client: Enriched order + Note over API: Root span ends ``` -Figure: Batch instrumentation approaches—events vs spans. -## src/content/articles/platform-architecture-control-plane-data-plane-separation/index.mdx +## stateDiagram-v2 + +```text +stateDiagram-v2 + [*] --> Closed + Closed --> Open: Failures exceed threshold + Open --> HalfOpen: Timeout expires + HalfOpen --> Closed: Probe succeeds + HalfOpen --> Open: Probe fails + + note right of Closed + Normal operation + Requests flow through + Track failure rate + end note + + note right of Open + Fail fast + Don't call downstream + Return cached/fallback + end note + + note right of HalfOpen + Test recovery + Allow limited probes + Monitor success + end note +``` ```mermaid -graph TB - subgraph CP[Control Plane] - A[API Server] --> B[State Store] - A --> C[Controllers] - end +stateDiagram-v2 + [*] --> Closed + Closed --> Open: Failures exceed threshold + Open --> HalfOpen: Timeout expires + HalfOpen --> Closed: Probe succeeds + HalfOpen --> Open: Probe fails + + note right of Closed + Normal operation + Requests flow through + Track failure rate + end note + + note right of Open + Fail fast + Don't call downstream + Return cached/fallback + end note + + note right of HalfOpen + Test recovery + Allow limited probes + Monitor success + end note +``` - D[Isolation Boundary] +## gantt - subgraph DP[Data Plane] - F[Worker Node 1] - G[Worker Node 2] - H[Worker Node 3] - end +```text +gantt + title Trace Waterfall (over-instrumented) + dateFormat X + axisFormat %L ms - C -->|"Desired State"| D - D --> F - D --> G - D --> H + section Request + HTTP GET /orders/123 :a1, 0, 150 - F -->|"Actual State"| D - G -->|"Actual State"| D - H -->|"Actual State"| D - D --> C + section Validation + validate.request :a2, 2, 5 + parse.json :a3, 5, 8 + validate.orderId :a4, 8, 10 + + section Cache + cache.get :a5, 10, 12 + serialize.key :a6, 10, 11 + redis.get :a7, 11, 12 + deserialize.result :a8, 12, 13 + + section Database + db.getConnection :a9, 15, 18 + db.query orders :a10, 18, 75 + db.releaseConnection :a11, 75, 77 + map.toEntity :a12, 77, 79 + + section Response + serialize.json :a13, 140, 145 + set.headers :a14, 145, 147 + send.response :a15, 147, 150 ``` + +```mermaid +gantt + title Trace Waterfall (over-instrumented) + dateFormat X + axisFormat %L ms + + section Request + HTTP GET /orders/123 :a1, 0, 150 + + section Validation + validate.request :a2, 2, 5 + parse.json :a3, 5, 8 + validate.orderId :a4, 8, 10 + + section Cache + cache.get :a5, 10, 12 + serialize.key :a6, 10, 11 + redis.get :a7, 11, 12 + deserialize.result :a8, 12, 13 + + section Database + db.getConnection :a9, 15, 18 + db.query orders :a10, 18, 75 + db.releaseConnection :a11, 75, 77 + map.toEntity :a12, 77, 79 + + section Response + serialize.json :a13, 140, 145 + set.headers :a14, 145, 147 + send.response :a15, 147, 150 +``` +Figure: Over-instrumented trace—wall of spans obscures the critical path. diff --git a/_LIT_AND_CAROUSEL_REFACTOR.md b/_LIT_AND_CAROUSEL_REFACTOR.md deleted file mode 100644 index df923a9eb..000000000 --- a/_LIT_AND_CAROUSEL_REFACTOR.md +++ /dev/null @@ -1,76 +0,0 @@ -1. Issues with refactoring Carousel and Testimonials to LitElement -No real blockers. The migration is straightforward because: - -Light DOM is already solved. ThemePicker demonstrates the pattern: createRenderRoot() { return this }. Since all three components render their HTML via Astro templates (not Lit's render()), this is the correct approach and already in use. -LitElement is already bundled. ThemePicker pulls it in, so there's no added dependency cost. -Lifecycle maps cleanly. The manual connectedCallback → initialize() pattern in Carousel/Testimonials translates directly. The main changes are calling super.connectedCallback() / super.disconnectedCallback() and optionally using firstUpdated() instead of the manual DOMContentLoaded check. -Nanostore integration improves. Carousel and Testimonials currently call createAnimationController manually. With LitElement they could use StoreController for reactive bindings (like ThemePicker does with createThemeController), though it's not required since the animation lifecycle uses callbacks rather than direct store subscriptions. -The only thing to watch: the transition:persist directive must remain on the HTML custom element tag itself, not on an Astro component wrapper. That's already a project rule and isn't affected by LitElement vs HTMLElement. - -2. Revised recommendation - -With all three components sharing LitElement as a base, an abstract base class becomes the cleanest option. - -Proposed structure: - -```bash -src/components/scripts/embla/ - EmblaCarouselBase.ts – abstract LitElement base class - types.ts – shared types (TimerHandle, EmblaRootElement, etc.) - logging.ts – createE2ELogger(prefix) -``` - -## What goes in EmblaCarouselBase extends LitElement - -All the code that's currently duplicated (~400 lines between Carousel and Testimonials): - -Responsibility Implementation -Light DOM createRenderRoot() { return this } -Embla init/destroy initEmbla() / teardownEmbla() with options from abstract getter -Autoplay plugin Setup, pending-state queue, scheduleAutoplayReady(), flushPendingAutoplayState() -pause() / resume() public API Identical in both today -Viewport observer setupViewportObserver() / teardownViewportObserver() / syncAutoplayWithViewport() -Animation lifecycle registerAnimationLifecycle() wrapping createAnimationController -Focus-visible pause handleFocusIn() / scheduleFocusVisiblePauseSync() / syncFocusVisiblePauseState() -Prev/next buttons setupNavigationButtons() with enable/disable state updates -Dots navigation setupDotsNavigation() with an overridable method for dot active styling -E2E logging logForE2E() using a configurable prefix -data-carousel-ready / data-carousel-autoplay attributes Set/remove in base -connectedCallback / disconnectedCallback / teardown Full lifecycle orchestration - -### What subclasses configure - -Via abstract getters or overridable methods — keeping each subclass to ~50–100 lines of glue: - -| Configuration point | Carousel | Testimonials | Skills (new) | -| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | -| `abstract get emblaOptions()` | [{ loop: true, align: 'start' }](vscode-file://vscode-app/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) | [{ loop: true, align: 'center' }](vscode-file://vscode-app/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) | [{ loop: true, align: 'start', dragFree: true }](vscode-file://vscode-app/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) | -| `abstract get autoplayOptions()` | [{ delay: 4000, ... }](vscode-file://vscode-app/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) | [{ delay: 6000, ... }](vscode-file://vscode-app/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) | `null` (no autoplay initially) | -| [abstract get animationId()](vscode-file://vscode-app/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) | `'carousel'` | ['testimonials-carousel'](vscode-file://vscode-app/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) | `'skills-carousel'` | -| [abstract get scriptName()](vscode-file://vscode-app/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) | ['CarouselElement'](vscode-file://vscode-app/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) | ['TestimonialsCarouselElement'](vscode-file://vscode-app/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) | `'SkillsCarouselElement'` | -| `abstract get logPrefix()` | `'carousel'` | ['testimonials'](vscode-file://vscode-app/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) | `'skills'` | -| `abstract get focusVisibleSelector()` | `'[data-carousel-slide] :focus-visible'` | `'[data-testimonials-slide] :focus-visible'` | component-specific | -| `abstract queryElements()` | Uses Carousel selectors | Uses Testimonials selectors | Uses Skills selectors | - -Then each subclass adds only its unique features: - -| Feature | Where it lives | -| ------------------------------------------------------------ | ------------------------------------------------------------ | -| Keyboard nav (ArrowLeft/Right) | Carousel subclass only | -| Status region ("Slide X of Y") | Carousel subclass only | -| Autoplay toggle button + icon swap | Testimonials subclass only | -| Viewport ID / `aria-controls` on buttons | Testimonials subclass only | -| Dot active styling ([is-active](vscode-file://vscode-app/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) vs `w-6`) | Override `applyDotActiveStyle()` / `applyDotInactiveStyle()` | - -Two reasonable paths: - -A: ThemePicker stays independent but extracts just the nav-button wiring into a small utility function in src/components/scripts/embla/navigation.ts (~30 lines). This avoids forcing ThemePicker into a base class that's 90% irrelevant to it. -B: ThemePicker extends EmblaCarouselBase with autoplay disabled and most features no-op'd. This feels forced and adds cognitive overhead for no real benefit. -I'd recommend A. The base class serves the autoplay-carousel family (Carousel, Testimonials, Skills, and any future autoplay carousel). ThemePicker shares one small utility. - -Estimated result -EmblaCarouselBase.ts: ~350–400 lines (extracted from current duplication) -Each subclass (Carousel, Testimonials, Skills): ~50–150 lines of component-specific code -navigation.ts utility for ThemePicker: ~30 lines -Net reduction: ~400+ lines eliminated across Carousel and Testimonials -Skills starts with a thin subclass instead of copy-pasting a fourth time \ No newline at end of file diff --git a/_TODO.md b/_TODO.md index f50743dbf..be7419cce 100644 --- a/_TODO.md +++ b/_TODO.md @@ -238,6 +238,10 @@ https://mermaid.js.org/config/directives.html - Service worker isn't caching favicon +- Image component with zoom + and -, and magnify glass. Modal to expand full size. + +- Don't lazy load hero image + ## List Component - Task list checked variant Markdown in dark theme is awkward, it has a dark shadow @@ -250,29 +254,6 @@ https://mermaid.js.org/config/directives.html - Need to improve the "squish" animation where the header reduces in size on scroll down, and returns to full size on scroll up. Maybe reduce and expand the text and search / themepicker / hamburger menu sizes in place, and then slide them horizontally. -## Image component - -Only needed if images used in content: Use an in-project Image component to wrap Astro's Image and Picture. Show a magnifying glass with a "+" for the cursor on hover, and a modal to show a magnified view of images on click. - -- `accTitle`: Alert severity decision tree -- `accDescr`: Flowchart showing how to classify an alert as a Page or Notification. When an alert fires, check if there is user-facing impact. If no, it is a Notification. If yes, check if there is immediate revenue or safety impact. If yes, it is a Page. If no, check if the SLO burn rate is critical. If yes, it is a Page. If no, it is a Notification. - -
- - [accTitle] - see details below for full text description - -
- - Figure 1: Process Workflow - - -
- View detailed text description -

[Insert your full accDescr content here]

-
-
-
- ## Content Issues - "### Geographic/Currency Mismatches" in deep-dive/cdn-edge-caching-cache-keys-vary-headers has a table -> callout -> table back to back @@ -289,56 +270,19 @@ Only needed if images used in content: Use an in-project Image component to wrap - We need to check for short form and deep article articles where the deep-dive index.pdf has a non-featured tag like "argo-cd" only in the pdf.mdx. In those cases, we should make sure the callout for the deep dive includes the name of that non-featured (technology) tag -## Table Refactor Instructions - -Our current articles have markdown tables. I want to refactor these into using our Table component. I'd like you to take it and use it for the content prop in a Table component instance you add so that the table renders using the same layout as the markdown table. Use the string variant in the tbody -> tr -> th element. Use "vertical-column-delineation-table" for the "variant" prop of the Table component. - -Each table will have the "figure" prop as a line below the table, prefixed with "Table: ". We should remove the "Table: " prefix from the figure string as this is used by our Markdown setup to identify figure captions. Do not leave multiple trailing empty lines after the table. - -The first file to update is: - -## List Refactor Instructions - -numbered-with-background-list, check-icons-list - -We have lists in our current articles that are of two variants: those that are plain text lists (either ordered or unordered), and those that are lists with both leads and plain texts. Our List component layouts handle both lists with leads and those without. We can identify leads because that text is emphasized with markdown in some fashion: "_", "__", "*", or "**". We need to refactor the markdown lists in a file into either an ordered (numbered-with-background-list) or unordered (check-icons-list) list, and extract lead text if present into the optional lead prop if any lead text is present. The "lead" prop should come first and before the "text" prop in the object. The "lead" prop is the emphasized text that comes first in the list items we are converting to the List component +- deep-dive/kubernetes-pod-resource-requests-limits-qos-classes is showing the Download hero image -An example is as follows: +- Add a "Preview Special" item to our Download CTA that lets the user know the Deep Dive content can be previewed in HTML format, and offer a switch to it. -- _Alerts per on-call shift_: Total alert volume during a rotation. Anything above 20 per 24-hour shift is a red flag. +- How can we handle footnotes in List components? src/content/articles/kubernetes-multi-cluster-fleet-management-configuration/pdf.mdx line 80 - - -The first file to update is: - -### Timelines - -- Good generation: - -api-gateway-metrics-traces-logs-debugging/trace-context-propagation-creating-connected-spans-across-gateway-boundary.jpg - -- Needs done: - -backpressure-load-shedding-admission-control-overload/backpressure-propagates-from-the-constrained-resource-back-to-the-client.png - -argocd-sync-failures-gitops-debugging-troubleshooting/hook-execution-sequence-during-argoc-sync-lifecycle.png - -- Not close enough in details: - -argocd-sync-failures-gitops-debugging-troubleshooting/resource-dependency-graph-showing-potential-failure-points.png +### This file was badly mangled during refactoring, need to compare against original: -### Figure captions are broken: +src/content/articles/internal-developer-portal-platform-self-service-actions/pdf.mdx -src/content/articles/structured-logging-correlation-ids-log-schema-design/pdf.mdx +## Prompt for Mermaid Images -### This file was badly mangled during refactoring, need to compare against original: +├── +└── -src/content/articles/internal-developer-portal-platform-self-service-actions/pdf.mdx +jpg diff --git a/package-lock.json b/package-lock.json index 213d9be27..a71b44c6c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -176,7 +176,7 @@ "unist-util-is": "^6.0.1", "unist-util-visit": "^5.1.0", "uuid": "^13.0.0", - "vercel": "^50.27.1", + "vercel": "^50.28.0", "vite": "^7.3.1", "vitest": "4.0.18", "vitest-axe": "0.1.0", @@ -9434,12 +9434,12 @@ } }, "node_modules/@vercel/backends": { - "version": "0.0.40", - "resolved": "https://registry.npmjs.org/@vercel/backends/-/backends-0.0.40.tgz", - "integrity": "sha512-cYyfPeGrpqyxBgcgKoaZJ+9M7NRKf1eevzKkrX9QRmiBBlGduR34hV859uK4ouBJByHE7n9Tkga2dRLOH8pMcQ==", + "version": "0.0.41", + "resolved": "https://registry.npmjs.org/@vercel/backends/-/backends-0.0.41.tgz", + "integrity": "sha512-XjikuYlrvVQEjfcdPIAQNrT4GqHJid1k1aueRIxtX33kvsCaMqd1xz2PwrNcyEHmwR7JRgGI1A8Twx9QDMq9eg==", "license": "Apache-2.0", "dependencies": { - "@vercel/build-utils": "13.6.2", + "@vercel/build-utils": "13.6.3", "@vercel/nft": "1.3.0", "execa": "3.2.0", "fs-extra": "11.1.0", @@ -9658,21 +9658,21 @@ } }, "node_modules/@vercel/build-utils": { - "version": "13.6.2", - "resolved": "https://registry.npmjs.org/@vercel/build-utils/-/build-utils-13.6.2.tgz", - "integrity": "sha512-KiwRUd2x1ZHm73p+/hfdVWZHWXT8r+oN/5ZN1lJyb41AGK4Zhrug6X60jNyVhnw6GjpwBuPTBcys29cCsPjkWQ==", + "version": "13.6.3", + "resolved": "https://registry.npmjs.org/@vercel/build-utils/-/build-utils-13.6.3.tgz", + "integrity": "sha512-KOxkJ38uzZoxvto1fL6H2Vxm69vbbKgpY7vq07M1mVdRM9q2jXFN5Lo6bebtuH/kuv0cLZNXCE1r8aFmaTwpTg==", "license": "Apache-2.0", "dependencies": { - "@vercel/python-analysis": "0.8.1" + "@vercel/python-analysis": "0.8.2" } }, "node_modules/@vercel/cervel": { - "version": "0.0.27", - "resolved": "https://registry.npmjs.org/@vercel/cervel/-/cervel-0.0.27.tgz", - "integrity": "sha512-w6FPgnnZD2nr43pkhXSY0tGMwCJT6kh8f8VoEL97ISSkxywZYX+Bw5FxrNavAEMC0wYm7esEosOdAEAh8Twbag==", + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/@vercel/cervel/-/cervel-0.0.28.tgz", + "integrity": "sha512-JanW95I8imjFzve1NCHv2JK5Bd/vd6DKULPaELAkC5pFV1lnqDHKmJEf21Trbg2qi9Rg5x0z08DbF44pcd6X+g==", "license": "Apache-2.0", "dependencies": { - "@vercel/backends": "0.0.40" + "@vercel/backends": "0.0.41" }, "bin": { "cervel": "bin/cervel.mjs" @@ -9691,12 +9691,12 @@ } }, "node_modules/@vercel/elysia": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/@vercel/elysia/-/elysia-0.1.43.tgz", - "integrity": "sha512-Q5XCGVMuO0XF2n/XEEP43d+AIk8Yl09NwJmJ0m9w5Mx0Pyacb1Yo6dcbn6vnsj4j50dpYGeejdaqu77xOKi8mQ==", + "version": "0.1.44", + "resolved": "https://registry.npmjs.org/@vercel/elysia/-/elysia-0.1.44.tgz", + "integrity": "sha512-GYpOziLqPHoNopgpeogo20teEkcs2/2sbfitPd94UR+zpILHgaYXLAvk0im1OkOlRmptJACCGdD/O3Pc9flpnA==", "license": "Apache-2.0", "dependencies": { - "@vercel/node": "5.6.10", + "@vercel/node": "5.6.11", "@vercel/static-config": "3.1.2" } }, @@ -9707,14 +9707,14 @@ "license": "Apache-2.0" }, "node_modules/@vercel/express": { - "version": "0.1.52", - "resolved": "https://registry.npmjs.org/@vercel/express/-/express-0.1.52.tgz", - "integrity": "sha512-lvZyw/7IOVMx6YqniijlMrU0ys+bcbqkY+5slGQMoXrtW7Mo2RhF9f27y+1Bl1ELv8JzyrXhOLHu2f5gn4CsgQ==", + "version": "0.1.53", + "resolved": "https://registry.npmjs.org/@vercel/express/-/express-0.1.53.tgz", + "integrity": "sha512-rgKtIsqv0g+q+78CIEt2sl4l7lFBa/VX1Curivj9E088BkC7GFEjHUHvmCp0pZ9zX7irpt5zRtSErQM63+U3Qg==", "license": "Apache-2.0", "dependencies": { - "@vercel/cervel": "0.0.27", + "@vercel/cervel": "0.0.28", "@vercel/nft": "1.1.1", - "@vercel/node": "5.6.10", + "@vercel/node": "5.6.11", "@vercel/static-config": "3.1.2", "fs-extra": "11.1.0", "path-to-regexp": "8.3.0", @@ -9900,12 +9900,12 @@ } }, "node_modules/@vercel/fastify": { - "version": "0.1.46", - "resolved": "https://registry.npmjs.org/@vercel/fastify/-/fastify-0.1.46.tgz", - "integrity": "sha512-R8uSV3SSbFJ39o3VAfsKwlWOPGDfQyNXxJ2dT8Z05GQ4O3qgGTcRd/oEothQZgnJR9fjGzDQ3q7SwWBd12150A==", + "version": "0.1.47", + "resolved": "https://registry.npmjs.org/@vercel/fastify/-/fastify-0.1.47.tgz", + "integrity": "sha512-lg0X5RuIGXP9Dkg7Kzs3f1XVjD7wHvpuUlVZyhmvmOsMn5nYDB4vo8QrLaDaWJo10PVDppm9BVBfdKp2HWvFQw==", "license": "Apache-2.0", "dependencies": { - "@vercel/node": "5.6.10", + "@vercel/node": "5.6.11", "@vercel/static-config": "3.1.2" } }, @@ -10065,13 +10065,13 @@ } }, "node_modules/@vercel/gatsby-plugin-vercel-builder": { - "version": "2.0.142", - "resolved": "https://registry.npmjs.org/@vercel/gatsby-plugin-vercel-builder/-/gatsby-plugin-vercel-builder-2.0.142.tgz", - "integrity": "sha512-F6Mo5fROP57wX/vAngXHA+xBZVwi98vU5YT1J+n/PYxIwbOVCa6SyPOI98o6a+uLQnchqbWbcXcV2CaYmU85VA==", + "version": "2.0.143", + "resolved": "https://registry.npmjs.org/@vercel/gatsby-plugin-vercel-builder/-/gatsby-plugin-vercel-builder-2.0.143.tgz", + "integrity": "sha512-UO0BLWfxi8SFQwSpMNNNRHvai5+cElRUzqasxFgC1zGyo7Bbw0FZA6JTkIIJ1Rdk/rHr9xhn7/8R8fGIvmGaKA==", "license": "Apache-2.0", "dependencies": { "@sinclair/typebox": "0.25.24", - "@vercel/build-utils": "13.6.2", + "@vercel/build-utils": "13.6.3", "esbuild": "0.27.0", "etag": "1.8.1", "fs-extra": "11.1.0" @@ -10555,23 +10555,23 @@ "license": "Apache-2.0" }, "node_modules/@vercel/h3": { - "version": "0.1.52", - "resolved": "https://registry.npmjs.org/@vercel/h3/-/h3-0.1.52.tgz", - "integrity": "sha512-bk8id7w9evxD+JeOUJt6qfDohGwJFBVh7N1qh1OG/nngzzb/Ojg+poH5EGpYwYiKymPK7NMgQl0fb0ZjhIU4bg==", + "version": "0.1.53", + "resolved": "https://registry.npmjs.org/@vercel/h3/-/h3-0.1.53.tgz", + "integrity": "sha512-98KBB5XFdvezLRzlFNUJKQEgoDRrwsJaied3fUCcMzWYy5FXqvO+XqmWUGk4bApOM86MFkCsp6h9KqIZkn53uA==", "license": "Apache-2.0", "dependencies": { - "@vercel/node": "5.6.10", + "@vercel/node": "5.6.11", "@vercel/static-config": "3.1.2" } }, "node_modules/@vercel/hono": { - "version": "0.2.46", - "resolved": "https://registry.npmjs.org/@vercel/hono/-/hono-0.2.46.tgz", - "integrity": "sha512-rg+6PnvIV20lUM3r2fcjJ/1g1z3ND6h3EqlOQytwCuwpP/jB88TUy+guutB4rDpylPvHzleZqjgi2rE9yH4URg==", + "version": "0.2.47", + "resolved": "https://registry.npmjs.org/@vercel/hono/-/hono-0.2.47.tgz", + "integrity": "sha512-JgS1j45JugQ4QXjkUZ7DFABZQ0AVIPbxF+IAlpfcKPUHViE1HKwsw7TnfY2zKktaMIY5EutkimDvQV1KtFmYjg==", "license": "Apache-2.0", "dependencies": { "@vercel/nft": "1.1.1", - "@vercel/node": "5.6.10", + "@vercel/node": "5.6.11", "@vercel/static-config": "3.1.2", "fs-extra": "11.1.0", "path-to-regexp": "8.3.0", @@ -10767,22 +10767,22 @@ } }, "node_modules/@vercel/koa": { - "version": "0.1.26", - "resolved": "https://registry.npmjs.org/@vercel/koa/-/koa-0.1.26.tgz", - "integrity": "sha512-TzH4xovhGbr2kmZyvMraaJ3A28qRdo8SxkBO+LIb3ahM739VyTAkH3EYR5CPaemkRv00+nTyBxJJxfnhP1n2MA==", + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/@vercel/koa/-/koa-0.1.27.tgz", + "integrity": "sha512-3fPAVVSMYRFhuz8BKh0yvDTmwp2q6KPodqYcNt10TvsMvU5RiQUVPxjgEUAS7a5dtI4J5lCGQ+7aG1Qeso8S+w==", "license": "Apache-2.0", "dependencies": { - "@vercel/node": "5.6.10", + "@vercel/node": "5.6.11", "@vercel/static-config": "3.1.2" } }, "node_modules/@vercel/nestjs": { - "version": "0.2.47", - "resolved": "https://registry.npmjs.org/@vercel/nestjs/-/nestjs-0.2.47.tgz", - "integrity": "sha512-/yIbLc5rv8GQ+lsJ45JkObcNiMe5yUgXx2d8wryW1SajPV1/iP+wFRK28/Q+6zdvapcgqhFRwInZh+61um/ZWg==", + "version": "0.2.48", + "resolved": "https://registry.npmjs.org/@vercel/nestjs/-/nestjs-0.2.48.tgz", + "integrity": "sha512-bYdyQt0ew1nY5SGdkByXpwoDwBwtCwkyKBuxypc+bFeTksNkp09YnoUYo8ppqhGoXFre9ZEubvVLwIOGS1/aLw==", "license": "Apache-2.0", "dependencies": { - "@vercel/node": "5.6.10", + "@vercel/node": "5.6.11", "@vercel/static-config": "3.1.2" } }, @@ -11006,16 +11006,16 @@ } }, "node_modules/@vercel/node": { - "version": "5.6.10", - "resolved": "https://registry.npmjs.org/@vercel/node/-/node-5.6.10.tgz", - "integrity": "sha512-HEydd6y0KPjCyI9sM3n2/XCjS/fZV/7sO7jFjia9I5XbEJ6LCwkI6rR+GQB751NL0He0vFusy+mm394hJC/Rqg==", + "version": "5.6.11", + "resolved": "https://registry.npmjs.org/@vercel/node/-/node-5.6.11.tgz", + "integrity": "sha512-nzoS+ufkxpT4JxEzrjSA9vCEr4XzjCsHvGzi37+O+wajMldxsfcrvk9xHHuz1ZRzclwuPhcvLOMrs+ViJu63oA==", "license": "Apache-2.0", "dependencies": { "@edge-runtime/node-utils": "2.3.0", "@edge-runtime/primitives": "4.1.0", "@edge-runtime/vm": "3.2.0", "@types/node": "20.11.0", - "@vercel/build-utils": "13.6.2", + "@vercel/build-utils": "13.6.3", "@vercel/error-utils": "2.0.3", "@vercel/nft": "1.1.1", "@vercel/static-config": "3.1.2", @@ -11718,18 +11718,18 @@ } }, "node_modules/@vercel/python": { - "version": "6.20.1", - "resolved": "https://registry.npmjs.org/@vercel/python/-/python-6.20.1.tgz", - "integrity": "sha512-a/VgUJ/N7SfKgE2fen6iaNow/nWEGEQj57SNyPwo4emvPfO1dPxUlZWyAEdctfXYKjnJR2WAU2kYcCDw+zenZg==", + "version": "6.20.2", + "resolved": "https://registry.npmjs.org/@vercel/python/-/python-6.20.2.tgz", + "integrity": "sha512-8RY+LlSDxOaCToLp77uPXn4cC1leoUIRdfLsq87wiIR8trnhUHIjHpBC39dm4B5MoyFPZPRLirIsBond4kB3RQ==", "license": "Apache-2.0", "dependencies": { - "@vercel/python-analysis": "0.8.1" + "@vercel/python-analysis": "0.8.2" } }, "node_modules/@vercel/python-analysis": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@vercel/python-analysis/-/python-analysis-0.8.1.tgz", - "integrity": "sha512-gW1pZDqJaTcjZYPvNhXXLOPgLu6vJW9PKweJoX2f8EKAoW+JIiYncl8AddcSlngNhQRG7SqUl2u3qosZM4kUBA==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@vercel/python-analysis/-/python-analysis-0.8.2.tgz", + "integrity": "sha512-tLYH5LydD3deJio2/T7FxMRuW0Vvqhlo0Fy24fgZBQipqpOE7aMODoKTulHx5Z1b/tFLCPOV8NkbpwOY0EVa5g==", "license": "Apache-2.0", "dependencies": { "@bytecodealliance/preview2-shim": "0.17.6", @@ -12213,13 +12213,13 @@ "license": "ISC" }, "node_modules/@vercel/static-build": { - "version": "2.8.44", - "resolved": "https://registry.npmjs.org/@vercel/static-build/-/static-build-2.8.44.tgz", - "integrity": "sha512-xzRBFm+tgVoyE/qSF+BeKXKckLVYXR2dGHsp+fNRttLXi7fq2AUCTM7DNNT4TkkTxcPX5FaJ1tRHxlqLizv91A==", + "version": "2.8.45", + "resolved": "https://registry.npmjs.org/@vercel/static-build/-/static-build-2.8.45.tgz", + "integrity": "sha512-eIQBLGzCTgCMGYS4wu4OSUMENFOR7yl8dzd7xURh/AnZ42ypAa5sKc7u85Z5MSY9G3o+1It/8cxlD1RDgQa/XA==", "license": "Apache-2.0", "dependencies": { "@vercel/gatsby-plugin-vercel-analytics": "1.0.11", - "@vercel/gatsby-plugin-vercel-builder": "2.0.142", + "@vercel/gatsby-plugin-vercel-builder": "2.0.143", "@vercel/static-config": "3.1.2", "ts-morph": "12.0.0" } @@ -39586,33 +39586,33 @@ } }, "node_modules/vercel": { - "version": "50.27.1", - "resolved": "https://registry.npmjs.org/vercel/-/vercel-50.27.1.tgz", - "integrity": "sha512-tFBs/wc6gLG0KWgUz/B/dkTKEarNLWXk2BErrbCdXnrJxhb9DL1ebEC8SYfqJZUcPOCGnELdOp0NZS26AJ0yuw==", + "version": "50.28.0", + "resolved": "https://registry.npmjs.org/vercel/-/vercel-50.28.0.tgz", + "integrity": "sha512-h4J4Xv04oxNIdS6Bp72GbXRC1N1cJN6q5uTe7CBMjPxZ/Usg4twn+l716X4ZxHro1AydjJa2iuAsIxjudjeYsg==", "license": "Apache-2.0", "dependencies": { - "@vercel/backends": "0.0.40", + "@vercel/backends": "0.0.41", "@vercel/blob": "2.3.0", - "@vercel/build-utils": "13.6.2", + "@vercel/build-utils": "13.6.3", "@vercel/detect-agent": "1.1.0", - "@vercel/elysia": "0.1.43", - "@vercel/express": "0.1.52", - "@vercel/fastify": "0.1.46", + "@vercel/elysia": "0.1.44", + "@vercel/express": "0.1.53", + "@vercel/fastify": "0.1.47", "@vercel/fun": "1.3.0", "@vercel/go": "3.4.3", - "@vercel/h3": "0.1.52", - "@vercel/hono": "0.2.46", + "@vercel/h3": "0.1.53", + "@vercel/hono": "0.2.47", "@vercel/hydrogen": "1.3.5", - "@vercel/koa": "0.1.26", - "@vercel/nestjs": "0.2.47", + "@vercel/koa": "0.1.27", + "@vercel/nestjs": "0.2.48", "@vercel/next": "4.15.41", - "@vercel/node": "5.6.10", - "@vercel/python": "6.20.1", + "@vercel/node": "5.6.11", + "@vercel/python": "6.20.2", "@vercel/redwood": "2.4.9", "@vercel/remix-builder": "5.6.0", "@vercel/ruby": "2.3.2", "@vercel/rust": "1.0.5", - "@vercel/static-build": "2.8.44", + "@vercel/static-build": "2.8.45", "chokidar": "4.0.0", "esbuild": "0.27.0", "form-data": "^4.0.0", diff --git a/package.json b/package.json index 9eb0debb7..b65d388f3 100644 --- a/package.json +++ b/package.json @@ -230,7 +230,7 @@ "unist-util-is": "^6.0.1", "unist-util-visit": "^5.1.0", "uuid": "^13.0.0", - "vercel": "^50.27.1", + "vercel": "^50.28.0", "vite": "^7.3.1", "vitest": "4.0.18", "vitest-axe": "0.1.0", diff --git a/src/components/Diagram/index.astro b/src/components/Diagram/index.astro new file mode 100644 index 000000000..677e913c9 --- /dev/null +++ b/src/components/Diagram/index.astro @@ -0,0 +1,55 @@ +--- +import type { ImageMetadata } from 'astro' +import { Picture } from 'astro:assets' + +export interface Props { + /** The image source for the diagram */ + src?: ImageMetadata + /** The title of the diagram */ + title: string + /** A detailed description of the diagram for vision-impaired users */ + description: string +} + +const { src, title, description } = Astro.props +const hasDefaultSlot = Astro.slots.has('default') +--- + +
+ {src && ( + + )} + + {hasDefaultSlot && ( +
+ +
+ )} + +
+
+ +
+ {title} + + description + +
+
+

+ {description} +

+
+
+
diff --git a/src/components/Icon/icons/api.astro b/src/components/Icon/icons/api.astro new file mode 100644 index 000000000..3e64fc96b --- /dev/null +++ b/src/components/Icon/icons/api.astro @@ -0,0 +1,32 @@ +--- +export type Props = { + color: string + classes?: string + size: number + accessible: boolean + focusable: boolean + isListMarker?: boolean + id?: string +} + +const { color, classes, size, accessible, focusable, isListMarker, id } = Astro.props +--- + + + {accessible && API Icon} + + diff --git a/src/components/Icon/icons/apple.astro b/src/components/Icon/icons/apple.astro index 758b6369d..f9e657f35 100644 --- a/src/components/Icon/icons/apple.astro +++ b/src/components/Icon/icons/apple.astro @@ -24,5 +24,7 @@ const { color, classes, size, accessible, focusable, isListMarker, id } = Astro. role="img" > {accessible && apple icon} - + diff --git a/src/components/Icon/icons/chart-line.astro b/src/components/Icon/icons/chart-line.astro new file mode 100644 index 000000000..14af22a44 --- /dev/null +++ b/src/components/Icon/icons/chart-line.astro @@ -0,0 +1,32 @@ +--- +export type Props = { + color: string + classes?: string + size: number + accessible: boolean + focusable: boolean + isListMarker?: boolean + id?: string +} + +const { color, classes, size, accessible, focusable, isListMarker, id } = Astro.props +--- + + + {accessible && Chart with Line Moving Up Icon} + + diff --git a/src/components/Icon/icons/dns.astro b/src/components/Icon/icons/dns.astro new file mode 100644 index 000000000..3fea8efc6 --- /dev/null +++ b/src/components/Icon/icons/dns.astro @@ -0,0 +1,33 @@ +--- +export type Props = { + color: string + classes?: string + size: number + accessible: boolean + focusable: boolean + isListMarker?: boolean + id?: string +} + +const { color, classes, size, accessible, focusable, isListMarker, id } = Astro.props +--- + + + {accessible && Domain Name Server Icon} + + diff --git a/src/components/Icon/icons/load-balancer.astro b/src/components/Icon/icons/load-balancer.astro new file mode 100644 index 000000000..14ef5ceba --- /dev/null +++ b/src/components/Icon/icons/load-balancer.astro @@ -0,0 +1,79 @@ +--- +export type Props = { + color: string + classes?: string + size: number + accessible: boolean + focusable: boolean + isListMarker?: boolean + id?: string +} + +const { color, classes, size, accessible, focusable, isListMarker, id } = Astro.props +--- + + + {accessible && User Avatar Icon} + + + + + + + + + diff --git a/src/components/Icon/icons/moon-svgrepo-com.svg b/src/components/Icon/icons/moon-svgrepo-com.svg deleted file mode 100644 index c99ee0059..000000000 --- a/src/components/Icon/icons/moon-svgrepo-com.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - diff --git a/src/components/Icon/icons/network.astro b/src/components/Icon/icons/network.astro new file mode 100644 index 000000000..a24e712b7 --- /dev/null +++ b/src/components/Icon/icons/network.astro @@ -0,0 +1,32 @@ +--- +export type Props = { + color: string + classes?: string + size: number + accessible: boolean + focusable: boolean + isListMarker?: boolean + id?: string +} + +const { color, classes, size, accessible, focusable, isListMarker, id } = Astro.props +--- + + + {accessible && User Avatar Icon} + + diff --git a/src/components/Icon/icons/on-call.astro b/src/components/Icon/icons/on-call.astro new file mode 100644 index 000000000..df7863a40 --- /dev/null +++ b/src/components/Icon/icons/on-call.astro @@ -0,0 +1,42 @@ +--- +export type Props = { + color: string + classes?: string + size: number + accessible: boolean + focusable: boolean + isListMarker?: boolean + id?: string +} + +const { color, classes, size, accessible, focusable, isListMarker, id } = Astro.props +--- + + + {accessible && On Call Phone Icon} + + + + + diff --git a/src/components/Icon/icons/routing.astro b/src/components/Icon/icons/routing.astro new file mode 100644 index 000000000..3808d690a --- /dev/null +++ b/src/components/Icon/icons/routing.astro @@ -0,0 +1,29 @@ +--- +export type Props = { + color: string + classes?: string + size: number + accessible: boolean + focusable: boolean + isListMarker?: boolean + id?: string +} + +const { color, classes, size, accessible, focusable, isListMarker, id } = Astro.props +--- + + + {accessible && User Avatar Icon} + + diff --git a/src/components/Image/index.astro b/src/components/Image/index.astro new file mode 100644 index 000000000..e69de29bb diff --git a/src/components/Inset/index.astro b/src/components/Inset/index.astro new file mode 100644 index 000000000..f25e68060 --- /dev/null +++ b/src/components/Inset/index.astro @@ -0,0 +1,28 @@ +--- +import DefaultInset from './layouts/DefaultInset.astro' + +export type Props = { + classes?: { + layout?: string + wrapper?: string + } + color?: string | undefined + size?: number + variant: string +} + +const { variant = 'default', classes, color } = Astro.props +--- + +
+ {variant === 'default' && + (classes?.layout !== undefined ? ( + + + + ) : ( + + + + ))} +
diff --git a/src/components/Inset/layouts/DefaultInset.astro b/src/components/Inset/layouts/DefaultInset.astro new file mode 100644 index 000000000..d1d74472e --- /dev/null +++ b/src/components/Inset/layouts/DefaultInset.astro @@ -0,0 +1,17 @@ +--- +export type Props = { + classes?: { + layout?: string + } + color?: string | undefined +} + +const { classes, color }: Props = Astro.props + +const backgroundClass = color ? `bg-${color}` : 'bg-content-inverse-active' +const layoutClass = `font-mono ${backgroundClass} border-2 border-trim rounded-md px-6 pt-6` +--- + +
+ +
diff --git a/src/components/List/index.astro b/src/components/List/index.astro index 3c144c0c6..c9c1c5860 100644 --- a/src/components/List/index.astro +++ b/src/components/List/index.astro @@ -29,6 +29,7 @@ export type Props = { ol?: string ul?: string li?: string + titleClass?: string icon?: string header?: string content?: string @@ -38,11 +39,13 @@ export type Props = { } size?: number variant: string + style?: Record } -const { items, size, variant = 'default', classes } = Astro.props +const { items, size, variant = 'default', classes, style } = Astro.props const classesProps = classes ? { classes } : {} const sizeProps = size !== undefined ? { size } : {} +const styleProps = style ? { style } : {} const itemsWithColor = items as Array<{ title?: string lead?: string @@ -64,19 +67,19 @@ const plainIconItems = items.filter((item): item is Props['items'][number] & { i }) --- -
- {variant === 'accent-border-left-list' && } - {variant === 'badge-list' && } - {variant === 'card-grid-list' && } - {variant === 'check-icons-list' && } - {variant === 'chevron-list' && } - {variant === 'colored-marker-list' && } - {variant === 'numbered-with-background-list' && } - {variant === 'plain-icon-list' && } - {variant === 'side-by-side-list' && } - {variant === 'timeline-list' && } - {variant === 'two-column-check-icons-list' && } - {variant === 'two-column-icon-list' && } - {variant === 'three-column-icon-list' && } - {variant === 'zebra-list' && } +
+ {variant === 'accent-border-left-list' && } + {variant === 'badge-list' && } + {variant === 'card-grid-list' && } + {variant === 'check-icons-list' && } + {variant === 'chevron-list' && } + {variant === 'colored-marker-list' && } + {variant === 'numbered-with-background-list' && } + {variant === 'plain-icon-list' && } + {variant === 'side-by-side-list' && } + {variant === 'timeline-list' && } + {variant === 'two-column-check-icons-list' && } + {variant === 'two-column-icon-list' && } + {variant === 'three-column-icon-list' && } + {variant === 'zebra-list' && }
diff --git a/src/components/List/layouts/AccentBorderLeftList.astro b/src/components/List/layouts/AccentBorderLeftList.astro index 422b9f1bd..57a706377 100644 --- a/src/components/List/layouts/AccentBorderLeftList.astro +++ b/src/components/List/layouts/AccentBorderLeftList.astro @@ -16,7 +16,7 @@ const { items, classes }: Props = Astro.props const ulClass = "space-y-4 list-none pl-0" const liClass = "border-l-4 pl-4" -const headerClass = "text-content-active font-semibold mb-2" +const headerClass = "text-page-inverse font-semibold mb-2" const textClass = "text-content-offset text-sm" --- @@ -24,7 +24,7 @@ const textClass = "text-content-offset text-sm" { items.map((item) => (
  • -

    {item.lead}

    + {item.lead &&

    } {Array.isArray(item.text) ? (
    {item.text.map((paragraph) => ( diff --git a/src/components/List/layouts/BadgeList.astro b/src/components/List/layouts/BadgeList.astro index 4ae796f98..b3cc2dfe2 100644 --- a/src/components/List/layouts/BadgeList.astro +++ b/src/components/List/layouts/BadgeList.astro @@ -9,15 +9,22 @@ export type Props = { classes?: { ul?: string li?: string + titleClass?: string + content?: string em?: string } } const { items, classes }: Props = Astro.props -const ulClass = ["space-y-4", classes?.ul] -const liClass = ["flex flex-col sm:flex-row sm:items-baseline gap-2 sm:gap-4", classes?.li] -const titleClass = "shrink-0 px-2 py-1 rounded bg-content text-page-base font-mono text-xs font-bold" +const ulClass = ["space-y-4 sm:space-y-0 sm:table sm:border-separate sm:border-spacing-x-4 sm:border-spacing-y-4", classes?.ul] +const liClass = ["flex flex-col gap-2 sm:table-row", classes?.li] +const titleCellClass = "sm:table-cell sm:align-baseline" +const titleClass = [ + "inline-block px-2 py-1 rounded bg-content text-page-base font-mono text-xs font-bold", + classes?.titleClass, +] +const bodyClass = ["sm:table-cell sm:align-baseline", classes?.content] const emClass = ["text-content font-bold not-italic mr-2", classes?.em] --- @@ -25,10 +32,14 @@ const emClass = ["text-content font-bold not-italic mr-2", classes?.em] { items.map((item) => (
  • - {item.title} - - {item.lead} - {item.text} + {item.title && ( + + + + )} + + {item.lead && } +
  • )) diff --git a/src/components/List/layouts/CardGridList.astro b/src/components/List/layouts/CardGridList.astro index 33297d484..ce3b9cce9 100644 --- a/src/components/List/layouts/CardGridList.astro +++ b/src/components/List/layouts/CardGridList.astro @@ -1,6 +1,9 @@ --- +import Icon from '@components/Icon/index.astro' + export type Props = { items: { + icon?: string lead?: string text: string }[] @@ -15,15 +18,20 @@ const { items, classes }: Props = Astro.props const ulClass = ["grid grid-cols-1 md:grid-cols-2 gap-4", classes?.ul] const liClass = ["bg-page-offset border border-trim rounded-lg p-5 hover:border-primary transition-colors", classes?.li] -const emClass = ["block text-content font-semibold not-italic mb-2", classes?.em] +const emClass = ["block text-page-inverse font-semibold not-italic mb-2", classes?.em] ---
      { items.map((item) => (
    • - {item.lead} - {item.text} +
      + {item.icon && ( + + )} + {item.lead && } +
      +
    • )) } diff --git a/src/components/List/layouts/CheckIconsList.astro b/src/components/List/layouts/CheckIconsList.astro index 17355cf38..2181d5f66 100644 --- a/src/components/List/layouts/CheckIconsList.astro +++ b/src/components/List/layouts/CheckIconsList.astro @@ -34,11 +34,11 @@ const emClass = ["text-content font-semibold not-italic", classes?.em] {item.lead && ( <> - {item.lead} - + + )} - {item.text} + )) diff --git a/src/components/List/layouts/ChevronList.astro b/src/components/List/layouts/ChevronList.astro index 79edce25a..0c62918ea 100644 --- a/src/components/List/layouts/ChevronList.astro +++ b/src/components/List/layouts/ChevronList.astro @@ -19,7 +19,7 @@ const { items, classes }: Props = Astro.props const ulClass = ["space-y-3", classes?.ul] const liClass = ["group", classes?.li] const emClass = ["text-content font-semibold not-italic", classes?.em] -const textClass = "block text-content-offset text-sm mt-0.5" +const textClass = "block text-content-offset mt-0.5" ---
        @@ -36,8 +36,8 @@ const textClass = "block text-content-offset text-sm mt-0.5" />
        - {item.lead} - {item.text} + {item.lead && } +
    diff --git a/src/components/List/layouts/ColoredMarkerList.astro b/src/components/List/layouts/ColoredMarkerList.astro index f218f35e8..f9f68c283 100644 --- a/src/components/List/layouts/ColoredMarkerList.astro +++ b/src/components/List/layouts/ColoredMarkerList.astro @@ -32,8 +32,8 @@ const textClass = classes?.text ? [classes.text] : []
  • - {item.lead && {item.lead}} - {item.text} + {item.lead && } +
  • )) diff --git a/src/components/List/layouts/NumberedWithBackgroundList.astro b/src/components/List/layouts/NumberedWithBackgroundList.astro index f45108e47..ee0f7e610 100644 --- a/src/components/List/layouts/NumberedWithBackgroundList.astro +++ b/src/components/List/layouts/NumberedWithBackgroundList.astro @@ -24,8 +24,8 @@ const emClass = ["text-primary-offset font-semibold not-italic", classes?.em]
  • {index + 1}
    - {item.lead} -
    {item.text}
    + {item.lead && } +
  • )) diff --git a/src/components/List/layouts/PlainIconList.astro b/src/components/List/layouts/PlainIconList.astro index 370dac415..c63456dcb 100644 --- a/src/components/List/layouts/PlainIconList.astro +++ b/src/components/List/layouts/PlainIconList.astro @@ -31,7 +31,7 @@ const markerClasses = props.classes?.svg return (
  • - {text} +
  • ) }) diff --git a/src/components/List/layouts/SideBySideList.astro b/src/components/List/layouts/SideBySideList.astro index 4ad86c072..2205827e9 100644 --- a/src/components/List/layouts/SideBySideList.astro +++ b/src/components/List/layouts/SideBySideList.astro @@ -15,14 +15,14 @@ const { items, classes }: Props = Astro.props const dlClass = ["grid sm:grid-cols-[1fr_2fr] gap-x-8 gap-y-6", classes?.ul] const dtClass = ["font-bold text-right pt-0.5 border-r border-trim pr-8", classes?.em] -const ddClass = ["text-content-offset", classes?.li] +const ddClass = ["text-trim", classes?.li] ---
    { items.map((item) => ( -
    {item.lead}
    -
    {item.text}
    +
    +
    )) }
    diff --git a/src/components/List/layouts/ThreeColumnIconList.astro b/src/components/List/layouts/ThreeColumnIconList.astro index cd15c5169..fd8e5e793 100644 --- a/src/components/List/layouts/ThreeColumnIconList.astro +++ b/src/components/List/layouts/ThreeColumnIconList.astro @@ -25,8 +25,8 @@ export type Props = { const { items, classes, size }: Props = Astro.props const ulClass = ["grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6", classes?.ul].filter(Boolean).join(" ") -const liClass = ["flex items-start gap-2 bg-white dark:bg-gray-800 rounded-xl p-6 shadow-md", classes?.li].filter(Boolean).join(" ") -const iconWrapper = ["shrink-0 rounded-lg flex items-center justify-center mt-1", classes?.icon].filter(Boolean).join(" ") +const liClass = ["flex items-start gap-2 bg-white rounded-xl p-6 shadow-md", classes?.li].filter(Boolean).join(" ") +const iconWrapper = ["shrink-0 rounded-lg flex items-center justify-center mt-1 p-2", classes?.icon].filter(Boolean).join(" ") const contentWrapper = ["text-page-inverse mb-1 ml-2", classes?.content].filter(Boolean).join(" ") const headerClass = ["font-sans text-lg font-semibold text-gray-900 mt-0 mb-2", classes?.header].filter(Boolean).join(" ") const textClass = ["text-sm text-note-offset", classes?.text].filter(Boolean).join(" ") @@ -47,8 +47,8 @@ const textClass = ["text-sm text-note-offset", classes?.text].filter(Boolean).jo />
    -

    {item.title}

    -

    {item.text}

    + {item.title &&

    } +

    ) diff --git a/src/components/List/layouts/TimelineList.astro b/src/components/List/layouts/TimelineList.astro index a14d957d9..ca71eb2d3 100644 --- a/src/components/List/layouts/TimelineList.astro +++ b/src/components/List/layouts/TimelineList.astro @@ -37,8 +37,8 @@ const connectorClass = ["absolute left-1/2 top-[1.375rem] -bottom-1 -translate-x
    - {item.lead} - {item.text} + {item.lead && } +
    )) diff --git a/src/components/List/layouts/TwoColumnCheckIconsList.astro b/src/components/List/layouts/TwoColumnCheckIconsList.astro index c26e5b905..6984856a4 100644 --- a/src/components/List/layouts/TwoColumnCheckIconsList.astro +++ b/src/components/List/layouts/TwoColumnCheckIconsList.astro @@ -30,7 +30,7 @@ const liClass = ["flex items-center gap-2", classes?.li] size={size ?? 5} /> - {item.text} + )) diff --git a/src/components/List/layouts/TwoColumnIconList.astro b/src/components/List/layouts/TwoColumnIconList.astro index fc1971d15..34ee6812c 100644 --- a/src/components/List/layouts/TwoColumnIconList.astro +++ b/src/components/List/layouts/TwoColumnIconList.astro @@ -46,8 +46,8 @@ const textClass = ["text-sm text-note-offset", classes?.text].filter(Boolean).jo />
    -

    {item.title}

    -

    {item.text}

    + {item.title &&

    } +

    ) diff --git a/src/components/List/layouts/ZebraList.astro b/src/components/List/layouts/ZebraList.astro index bfc08551a..b4f91c289 100644 --- a/src/components/List/layouts/ZebraList.astro +++ b/src/components/List/layouts/ZebraList.astro @@ -12,30 +12,37 @@ export type Props = { li?: string em?: string } + style?: { + hideIcon?: boolean + } } -const { items, classes }: Props = Astro.props +const { items, classes, style }: Props = Astro.props const ulClass = ["border border-trim rounded-lg overflow-hidden divide-y divide-trim", classes?.ul] const liClass = ["p-4 bg-page-base flex items-center justify-between group hover:bg-page-offset transition-colors", classes?.li] -const emClass = ["text-content font-bold not-italic block mb-0.5", classes?.em] -const textClass = ["text-sm text-content-offset"] +const emClass = ["text-page-inverse font-bold not-italic block mb-0.5", classes?.em] +const textClass = ["text-content"] ---
      { items.map((item) => (
    • -
      - {item.lead} - {item.text} +
      + {item.lead && } +
      - + {!style?.hideIcon && ( +
      + +
      + )}
    • )) } diff --git a/src/components/Table/index.astro b/src/components/Table/index.astro index 50f0c15e9..7d2dd0b3a 100644 --- a/src/components/Table/index.astro +++ b/src/components/Table/index.astro @@ -1,15 +1,15 @@ --- -import CriteriaHighlightTable from '@components/Table/layouts/criteria-highlight.astro' -import GridAndAccentHeaderTable from '@components/Table/layouts/grid-and-accent-header.astro' -import MinimalBordersTable from '@components/Table/layouts/minimal-borders.astro' -import NumberedReviewTable from '@components/Table/layouts/numbered-review.astro' -import ReportTable from '@components/Table/layouts/report-table.astro' -import SemanticColoringTable from '@components/Table/layouts/semantic-coloring.astro' -import SoftHeaderCardTable from '@components/Table/layouts/soft-header-card.astro' -import StickyHeaderTable from '@components/Table/layouts/sticky-header.astro' -import StripedRowsTable from '@components/Table/layouts/striped-rows.astro' -import TimelineLabelsTable from '@components/Table/layouts/timeline-labels.astro' -import VerticalColumnDelineationTable from '@components/Table/layouts/vertical-column-delineation.astro' +import CriteriaHighlightTable, { type Props as CriteriaHighlightTableProps } from '@components/Table/layouts/criteria-highlight.astro' +import GridAndAccentHeaderTable, { type Props as GridAndAccentHeaderTableProps } from '@components/Table/layouts/grid-and-accent-header.astro' +import MinimalBordersTable, { type Props as MinimalBordersTableProps } from '@components/Table/layouts/minimal-borders.astro' +import NumberedReviewTable, { type Props as NumberedReviewTableProps } from '@components/Table/layouts/numbered-review.astro' +import ReportTable, { type Props as ReportTableProps } from '@components/Table/layouts/report-table.astro' +import SemanticColoringTable, { type Props as SemanticColoringTableProps } from '@components/Table/layouts/semantic-coloring.astro' +import SoftHeaderCardTable, { type Props as SoftHeaderCardTableProps } from '@components/Table/layouts/soft-header-card.astro' +import StickyHeaderTable, { type Props as StickyHeaderTableProps } from '@components/Table/layouts/sticky-header.astro' +import StripedRowsTable, { type Props as StripedRowsTableProps } from '@components/Table/layouts/striped-rows.astro' +import TimelineLabelsTable, { type Props as TimelineLabelsTableProps } from '@components/Table/layouts/timeline-labels.astro' +import VerticalColumnDelineationTable, { type Props as VerticalColumnDelineationTableProps } from '@components/Table/layouts/vertical-column-delineation.astro' export type Props = { content: { @@ -22,13 +22,13 @@ export type Props = { tbody: { tr: { th?: string | { label: string; color?: string } - td: string[] + td: Array }[] } tfoot?: { tr: { th?: string - td: string[] + td: Array }[] } } @@ -38,30 +38,37 @@ export type Props = { figure?: string thead?: string tbody?: string + tbodyRowHeader?: string + tbodyLastColumn?: string tfoot?: string } + fullWidth?: boolean variant: string } -const { content, variant = 'default', classes } = Astro.props +const { content, variant = 'default', classes, fullWidth = true } = Astro.props const classesProps = classes ? { classes } : {} -const wrapperClass = 'overflow-x-auto rounded-lg border border-trim bg-content-inverse' +const layoutProps = { ...classesProps, fullWidth } +const wrapperClass = [ + 'overflow-x-auto rounded-md border border-trim bg-content-inverse', + fullWidth ? 'w-full' : 'mx-auto w-fit max-w-full', +].join(' ') ---
      - {variant === 'criteria-highlight-table' && } - {variant === 'grid-and-accent-header-table' && } - {variant === 'minimal-borders-table' && } - {variant === 'numbered-review-table' && } - {variant === 'report-table' && } - {variant === 'semantic-coloring-table' && } - {variant === 'soft-header-card-table' && } - {variant === 'sticky-header-table' && } - {variant === 'striped-rows-table' && } - {variant === 'timeline-labels-table' && } - {variant === 'vertical-column-delineation-table' && } + {variant === 'criteria-highlight-table' && } + {variant === 'grid-and-accent-header-table' && } + {variant === 'minimal-borders-table' && } + {variant === 'numbered-review-table' && } + {variant === 'report-table' && } + {variant === 'semantic-coloring-table' && } + {variant === 'soft-header-card-table' && } + {variant === 'sticky-header-table' && } + {variant === 'striped-rows-table' && } + {variant === 'timeline-labels-table' && } + {variant === 'vertical-column-delineation-table' && }
      {content.figure && (
      diff --git a/src/components/Table/layouts/criteria-highlight.astro b/src/components/Table/layouts/criteria-highlight.astro index 2f0a302f6..3bfdc5eaa 100644 --- a/src/components/Table/layouts/criteria-highlight.astro +++ b/src/components/Table/layouts/criteria-highlight.astro @@ -26,15 +26,17 @@ export type Props = { tbody?: string tfoot?: string } + fullWidth?: boolean } -const { content, classes }: Props = Astro.props +const { content, classes, fullWidth = true }: Props = Astro.props -const tableClass = 'w-full text-left' +const tableClass = `text-left${fullWidth ? ' w-full' : ''}` const captionClass = 'text-left px-4 py-3 text-content-offset' const headerClass = 'px-4 py-2.5 font-semibold text-content-active' const theadClass = 'bg-page-offset border-b border-trim' const rowClass = 'transition-colors duration-150 hover:bg-page-offset border-b border-trim-offset last:border-b-0' +const getOverallColumnIndex = (hasRowHeader: boolean, cellIndex: number) => (hasRowHeader ? cellIndex + 1 : cellIndex) --- @@ -63,15 +65,15 @@ const rowClass = 'transition-colors duration-150 hover:bg-page-offset border-b b )} {row.td.map((td, index) => ( - index === 1 ? ( + getOverallColumnIndex(Boolean(row.th), index) === 1 ? ( - + ) : ( )} {row.td.map((td, index) => ( - index === 1 ? ( + getOverallColumnIndex(Boolean(row.th), index) === 1 ? ( - + ) : ( + )} {row.td.map((td, index) => ( }[] } tfoot?: { tr: { th?: string - td: string[] + td: Array }[] } } @@ -26,11 +26,12 @@ export type Props = { tbody?: string tfoot?: string } + fullWidth?: boolean } -const { content, classes }: Props = Astro.props +const { content, classes, fullWidth = true }: Props = Astro.props -const tableClass = 'w-full text-left border-collapse' +const tableClass = `text-left border-collapse${fullWidth ? ' w-full' : ''}` const captionClass = 'text-left px-5 py-3 text-content-offset' const headerClass = 'px-5 py-3 font-semibold text-content' const theadClass = 'bg-note-inverse/50 border-b border-trim' @@ -38,6 +39,11 @@ const tbodyClass = '' const tfootClass = '' const stateClasses = { + note: { + rowBgClass: 'bg-note-inverse', + barClass: 'bg-note', + textClass: 'text-note-offset', + }, success: { rowBgClass: 'bg-success-inverse', barClass: 'bg-success', @@ -63,9 +69,17 @@ const stateClasses = { type SemanticStateName = keyof typeof stateClasses const isSemanticStateName = (value: string): value is SemanticStateName => { - return value === 'success' || value === 'warning' || value === 'danger' || value === 'info' + return value === 'note' || value === 'success' || value === 'warning' || value === 'danger' || value === 'info' } +const firstBodyRow = content.tbody.tr[0] +const hasRowHeaders = content.tbody.tr.some(row => row.th !== undefined) +const bodyColumnCount = hasRowHeaders + ? (firstBodyRow?.td.length ?? 0) + 1 + : (firstBodyRow?.td.length ?? 0) +const shouldPrependStateHeader = hasRowHeaders && content.thead?.th.length === bodyColumnCount - 1 +const headerCells = shouldPrependStateHeader ? ['State', ...(content.thead?.th ?? [])] : (content.thead?.th ?? []) + const getStateClass = (row: Props['content']['tbody']['tr'][number], rowIndex: number) => { if (typeof row.th === 'object' && row.th?.color && isSemanticStateName(row.th.color)) { return stateClasses[row.th.color] @@ -88,7 +102,21 @@ const getStateLabel = (row: Props['content']['tbody']['tr'][number]): string => return row.th.label } - return row.th ?? row.td[0] ?? '' + const firstCell = row.td[0] + + return row.th ?? (firstCell ? getCellLabel(firstCell) : '') +} + +const getCellLabel = (cell: string | { label: string; color?: string }) => { + return typeof cell === 'string' ? cell : cell.label +} + +const getCellStateClass = (cell: string | { label: string; color?: string }) => { + if (typeof cell === 'object' && cell.color && isSemanticStateName(cell.color)) { + return stateClasses[cell.color] + } + + return undefined } --- @@ -103,8 +131,7 @@ const getStateLabel = (row: Props['content']['tbody']['tr'][number]): string => {content.thead && ( - State - {content.thead.th.map((th) => ( + {headerCells.map((th) => ( ))} @@ -133,24 +160,56 @@ const getStateLabel = (row: Props['content']['tbody']['tr'][number]): string => index === 0 ? 'font-medium text-content' : 'text-content', classes?.tbody, ]} - set:html={td} - > + > + {(() => { + const cellStateClass = getCellStateClass(td) + + if (!cellStateClass) { + return + } + + return ( + + ) + })()} + )) ) : ( - row.td.map((td, index) => { - if (index === 0) return null + row.td.map((td, index) => ( + + {(() => { + const cellStateClass = getCellStateClass(td) - return ( - - ) - }) + if (!cellStateClass) { + return + } + + return ( + + ) + })()} + + )) )} ) @@ -179,7 +238,7 @@ const getStateLabel = (row: Props['content']['tbody']['tr'][number]): string =>
      - {row.th ?? row.td[0]} + {row.th ?? (row.td[0] ? getCellLabel(row.td[0]) : '')} {row.th ? ( @@ -190,24 +249,56 @@ const getStateLabel = (row: Props['content']['tbody']['tr'][number]): string => index === 0 ? 'font-medium text-content' : 'text-content', classes?.tfoot, ]} - set:html={td} - > + > + {(() => { + const cellStateClass = getCellStateClass(td) + + if (!cellStateClass) { + return + } + + return ( + + ) + })()} + )) ) : ( - row.td.map((td, index) => { - if (index === 0) return null - - return ( - - ) - }) + row.td.map((td, index) => ( + + {(() => { + const cellStateClass = getCellStateClass(td) + + if (!cellStateClass) { + return + } + + return ( + + ) + })()} + + )) )} ) diff --git a/src/components/Table/layouts/soft-header-card.astro b/src/components/Table/layouts/soft-header-card.astro index 23bfb13ac..9ed749940 100644 --- a/src/components/Table/layouts/soft-header-card.astro +++ b/src/components/Table/layouts/soft-header-card.astro @@ -26,12 +26,13 @@ export type Props = { tbody?: string tfoot?: string } + fullWidth?: boolean } -const { content, classes }: Props = Astro.props +const { content, classes, fullWidth = true }: Props = Astro.props const introClass = 'px-5 py-4 bg-primary text-primary-inverse' -const tableClass = 'w-full text-left' +const tableClass = `text-left${fullWidth ? ' w-full' : ''}` const headerClass = 'px-5 py-3 font-semibold text-content-active' const theadClass = 'bg-page-offset border-b border-trim' const tbodyClass = '' diff --git a/src/components/Table/layouts/sticky-header.astro b/src/components/Table/layouts/sticky-header.astro index 740a4738a..08e84dc0f 100644 --- a/src/components/Table/layouts/sticky-header.astro +++ b/src/components/Table/layouts/sticky-header.astro @@ -26,11 +26,12 @@ export type Props = { tbody?: string tfoot?: string } + fullWidth?: boolean } -const { content, classes }: Props = Astro.props +const { content, classes, fullWidth = true }: Props = Astro.props -const tableClass = 'w-full text-left' +const tableClass = `text-left${fullWidth ? ' w-full' : ''}` const captionClass = 'text-left px-5 py-3 text-content-offset' const headerClass = 'px-5 py-3 font-semibold text-content-active border-b border-primary' const theadClass = 'sticky top-0 bg-page-offset' diff --git a/src/components/Table/layouts/striped-rows.astro b/src/components/Table/layouts/striped-rows.astro index 144fcd4b8..cb1ac36fe 100644 --- a/src/components/Table/layouts/striped-rows.astro +++ b/src/components/Table/layouts/striped-rows.astro @@ -26,11 +26,12 @@ export type Props = { tbody?: string tfoot?: string } + fullWidth?: boolean } -const { content, classes }: Props = Astro.props +const { content, classes, fullWidth = true }: Props = Astro.props -const tableClass = 'w-full text-left' +const tableClass = `text-left${fullWidth ? ' w-full' : ''}` const captionClass = 'text-left px-5 py-3 text-content-offset' const headerClass = 'px-5 py-3 font-semibold' const theadClass = 'bg-primary text-primary-inverse' diff --git a/src/components/Table/layouts/timeline-labels.astro b/src/components/Table/layouts/timeline-labels.astro index 34e3734e0..ab875b0ad 100644 --- a/src/components/Table/layouts/timeline-labels.astro +++ b/src/components/Table/layouts/timeline-labels.astro @@ -26,17 +26,32 @@ export type Props = { tbody?: string tfoot?: string } + fullWidth?: boolean } -const { content, classes }: Props = Astro.props +const { content, classes, fullWidth = true }: Props = Astro.props -const tableClass = 'w-full text-left' +const tableClass = `text-left${fullWidth ? ' w-full' : ''}` const captionClass = 'text-left px-4 py-3 text-content-offset' const headerClass = 'px-4 py-2.5 font-semibold text-content-active' const theadClass = 'bg-page-offset border-b border-trim' const tbodyClass = '' const tfootClass = '' const rowClass = 'transition-colors duration-150 hover:bg-page-offset border-b border-trim-offset last:border-b-0' + +const getMarkerColorClass = (rowHeader: string | { label: string; color?: string }) => { + if (typeof rowHeader === 'string') { + return 'bg-secondary' + } + + const color = rowHeader.color?.trim() + + if (!color) { + return 'bg-secondary' + } + + return color.startsWith('bg-') ? color : `bg-${color}` +} --- @@ -62,12 +77,12 @@ const rowClass = 'transition-colors duration-150 hover:bg-page-offset border-b b {row.th && (
      - +