Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
488b9e1
spec repo gitignore;
livelifelively Jan 20, 2026
f66489a
00a-02
livelifelively Jan 20, 2026
b653512
00a-03
livelifelively Jan 20, 2026
19178ab
00a-04
livelifelively Jan 20, 2026
6bf1342
00a-05
livelifelively Jan 20, 2026
614253d
fix linting issues
livelifelively Jan 20, 2026
13b9fb4
fix linting issues
livelifelively Jan 20, 2026
c2b395f
fix storybook issue;
livelifelively Jan 20, 2026
8dae22d
feat(ui): implement design tokens
livelifelively Jan 20, 2026
53dff45
buttons;
livelifelively Jan 20, 2026
bd861a3
input;
livelifelively Jan 20, 2026
1b2dba6
feat(ui): implement badge primitive
livelifelively Jan 20, 2026
657ee8f
feat(ui): implement icon primitive
livelifelively Jan 20, 2026
c86bb62
fix tests issue
livelifelively Jan 20, 2026
62009f6
Merge branch 'tests-fe-ph-0' of github.com:context-engine/say2 into i…
livelifelively Jan 20, 2026
bf7a9ba
feat(ui): implement toggle primitive
livelifelively Jan 20, 2026
809beeb
feat(ui): implement status dot primitive
livelifelively Jan 20, 2026
229e811
feat(ui): implement select primitive
livelifelively Jan 20, 2026
5ec5c7d
feat(ui): refactor Toggle with Bits UI and add Checkbox, Tooltip, Toast
livelifelively Jan 20, 2026
978da27
refactor(ui): refactor Button to use bits-ui Button
livelifelively Jan 20, 2026
9c29726
fix(ui): use let instead of const for destructuring
livelifelively Jan 20, 2026
16f2279
feat(ui): implement Spinner and SkipLink primitives
livelifelively Jan 20, 2026
b899287
refactor(ui): fix Button component issues
livelifelively Jan 21, 2026
f4fb2b5
chore: update UI package dependencies and cleanup
livelifelively Jan 21, 2026
d665a29
refactor(ui): fix Checkbox component and update ComponentType usage
livelifelively Jan 21, 2026
bb29032
package ui readme
livelifelively Jan 21, 2026
7322fbc
checkbox component;
livelifelively Jan 21, 2026
c71a218
refactor(ui): standardize primitives with ce- prefix and module exports
livelifelively Jan 21, 2026
db17ec8
refactor(ui): complete primitives standardization
livelifelively Jan 21, 2026
713f701
refactor(ui): improve tokens and dark mode accessibility
livelifelively Jan 21, 2026
4cacfcc
feat(ui): implement FocusTrap, ThemeToggle refactor, and primitive fixes
livelifelively Jan 21, 2026
2638e4a
feat(ui): implement LiveRegion and fix Input binding
livelifelively Jan 21, 2026
90caaab
feat(ui): implement EmptyState composite
livelifelively Jan 21, 2026
550ff0f
feat(ui): implement ExpandCollapse and CopyButton composites
livelifelively Jan 21, 2026
c751331
feat(ui): implement ToolCard composite
livelifelively Jan 21, 2026
ab73b33
feat(ui): refine ToolCard and fix Badge variant type
livelifelively Jan 21, 2026
940c2c6
feat(ui): implement ContextMenu composite
livelifelively Jan 21, 2026
a5d8805
style(ui): define missing --color-bg-surface token and fix translucency
livelifelively Jan 21, 2026
a9c52d2
feat(ui): implement ConnectionStatus composite
livelifelively Jan 21, 2026
4126e69
feat(ui): implement Lane A Level 0 composites
livelifelively Jan 21, 2026
9c303f8
feat(ui): implement DetailPanel and JSONInspector composites
livelifelively Jan 21, 2026
00be128
feat(ui): implement StatsPanel composite
livelifelively Jan 21, 2026
73d88cc
feat(ui): implement remaining Analysis composites
livelifelively Jan 21, 2026
8c77bdc
chore(ui): resolve linting and type errors and convert tests to bun:test
livelifelively Jan 21, 2026
89205a1
merge lane B
livelifelively Jan 21, 2026
1377e0a
fix(ui): resolve linting and type errors in SessionList
livelifelively Jan 21, 2026
95ee22f
test(ui): add unit tests for SessionList
livelifelively Jan 21, 2026
dd2d563
feat(ui): implement VirtualList component with @tanstack/svelte-virtual
livelifelively Jan 21, 2026
7eb8e74
fix(ui): fix VirtualList to correctly integrate TanStack Virtual with…
livelifelively Jan 21, 2026
5a799e5
feat(ui): implement MessageRow component and utils
livelifelively Jan 21, 2026
9e6f464
fix(ui): improve MessageRow selected state visibility and fix story t…
livelifelively Jan 21, 2026
2bf2f7b
feat(ui): add interactive SelectionDemo story for MessageRow
livelifelively Jan 21, 2026
1c3823a
fix(ui): increase MessageRow selection contrast per user feedback
livelifelively Jan 21, 2026
a7cbcfb
fix(ui): use correct color-info token for MessageRow selection and fi…
livelifelively Jan 21, 2026
b464b32
feat(ui): implement TrafficList with virtualization and auto-scroll
livelifelively Jan 21, 2026
aa634f1
fix(ui): ensure MessageRow fills virtual slot height and remove gaps
livelifelively Jan 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
# Finder (MacOS) folder config
.DS_Store

v0-docs
crystal
4 changes: 2 additions & 2 deletions .ignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Override .gitignore exclusions for AI editors/indexers
# This makes v0-docs accessible to AI coding assistants
# This makes crystal accessible to AI coding assistants
# even though it's excluded from Git tracking

!v0-docs
!crystal
13 changes: 13 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"svelte.plugin.svelte.useNewTransformation": true,
"svelte.enable-ts-plugin": true,
"files.associations": {
"svelte.config.js": "javascript"
},
"files.exclude": {
"**/.svelte-kit": true
},
"[svelte]": {
"editor.defaultFormatter": "svelte.svelte-vscode"
}
}
700 changes: 697 additions & 3 deletions bun.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions bunfig.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ coverageIgnorePatterns = [
# Test timeout in milliseconds
timeout = 10000

# Preload test setup (if needed)
# preload = ["./test-setup.ts"]
# Preload test setup (UI package needs happy-dom for DOM environment)
preload = ["./packages/ui/tests/svelte-plugin.ts", "./packages/ui/tests/setup.ts"]
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@
"@types/bun": "^1.3.6",
"fast-check": "^4.5.3"
}
}
}
111 changes: 111 additions & 0 deletions packages/ui/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
description: Use Bun instead of Node.js, npm, pnpm, or vite.
globs: "*.ts, *.tsx, *.html, *.css, *.js, *.jsx, package.json"
alwaysApply: false
---

Default to using Bun instead of Node.js.

- Use `bun <file>` instead of `node <file>` or `ts-node <file>`
- Use `bun test` instead of `jest` or `vitest`
- Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
- Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
- Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
- Use `bunx <package> <command>` instead of `npx <package> <command>`
- Bun automatically loads .env, so don't use dotenv.

## APIs

- `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
- `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
- `Bun.redis` for Redis. Don't use `ioredis`.
- `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
- `WebSocket` is built-in. Don't use `ws`.
- Prefer `Bun.file` over `node:fs`'s readFile/writeFile
- Bun.$`ls` instead of execa.

## Testing

Use `bun test` to run tests.

```ts#index.test.ts
import { test, expect } from "bun:test";

test("hello world", () => {
expect(1).toBe(1);
});
```

## Frontend

Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.

Server:

```ts#index.ts
import index from "./index.html"

Bun.serve({
routes: {
"/": index,
"/api/users/:id": {
GET: (req) => {
return new Response(JSON.stringify({ id: req.params.id }));
},
},
},
// optional websocket support
websocket: {
open: (ws) => {
ws.send("Hello, world!");
},
message: (ws, message) => {
ws.send(message);
},
close: (ws) => {
// handle close
}
},
development: {
hmr: true,
console: true,
}
})
```

HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.

```html#index.html
<html>
<body>
<h1>Hello, world!</h1>
<script type="module" src="./frontend.tsx"></script>
</body>
</html>
```

With the following `frontend.tsx`:

```tsx#frontend.tsx
import React from "react";
import { createRoot } from "react-dom/client";

// import .css files directly and it works
import './index.css';

const root = createRoot(document.body);

export default function Frontend() {
return <h1>Hello, world!</h1>;
}

root.render(<Frontend />);
```

Then, run index.ts

```sh
bun --hot ./index.ts
```

For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`.
37 changes: 37 additions & 0 deletions packages/ui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# dependencies (bun install)
node_modules

# output
out
dist
*.tgz
storybook-static
debug-storybook.log

# code coverage
coverage
*.lcov

# logs
logs
_.log
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# caches
.eslintcache
.cache
*.tsbuildinfo

# IntelliJ based IDEs
.idea

# Finder (MacOS) folder config
.DS_Store
.svelte-kit
15 changes: 15 additions & 0 deletions packages/ui/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { StorybookConfig } from "@storybook/svelte-vite";

const config: StorybookConfig = {
stories: ["../src/**/*.stories.@(js|ts|svelte)"],
addons: ["@storybook/addon-essentials"],
framework: {
name: "@storybook/svelte-vite",
options: {},
},
docs: {
autodocs: "tag",
},
};

export default config;
8 changes: 8 additions & 0 deletions packages/ui/.storybook/preview-head.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script>
// Inline script to prevent theme flash in Storybook
document.documentElement.classList.add('no-transition');
const theme = localStorage.getItem('say2-theme');
if (theme && theme !== 'system') {
document.documentElement.setAttribute('data-theme', theme);
}
</script>
46 changes: 46 additions & 0 deletions packages/ui/.storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { Preview } from "@storybook/svelte";

// Import tokens (includes typography)
import '../src/lib/tokens/index.css';

const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
backgrounds: {
default: "light",
values: [
{ name: "light", value: "#ffffff" },
{ name: "dark", value: "#1a1a1a" },
],
},
},
decorators: [
// Ensure fonts are loaded
(Story, context) => {
// Add Google Fonts link if not present
if (typeof document !== 'undefined') {
const linkId = 'google-fonts';
if (!document.getElementById(linkId)) {
const link = document.createElement('link');
link.id = linkId;
link.rel = 'stylesheet';
link.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap';
document.head.appendChild(link);
}

// Sync data-theme with Storybook background
const bgName = context.globals?.backgrounds?.value;
const theme = bgName === '#1a1a1a' ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', theme);
}
return Story();
}
]
};

export default preview;
87 changes: 87 additions & 0 deletions packages/ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# @say2/ui

UI component library for Say2, built with Svelte 5 and TypeScript.

## Overview

This package provides a set of primitive and composite UI components using:
- **Svelte 5** (with runes)
- **bits-ui** for headless component primitives
- **TypeScript** for type safety
- **Storybook** for component development and documentation
- **Bun** for testing

## Installation

```bash
bun install
```

## Development

### Storybook

Run Storybook for interactive component development:

```bash
bun run dev
```

This will start Storybook at [http://localhost:6006](http://localhost:6006) where you can:
- Browse all components in isolation
- View component documentation
- Interact with component controls
- Test different component states and variants

### Build Storybook

To build a static version of Storybook:

```bash
bun run build:storybook
```

## Testing

Run all tests:

```bash
bun run test
```

Run tests in watch mode:

```bash
bun run test:watch
```

## Building

Build the component library for distribution:

```bash
bun run build
```

This generates the package output in the `dist/` directory.

## Type Checking

Run Svelte type checking:

```bash
bun run check
```

## Component Structure

Components are organized into:
- **Primitives** (`src/lib/primitives/`) - Basic UI building blocks
- Button, Badge, Input, Checkbox, Select, etc.
- **Composites** (`src/lib/composites/`) - Complex components built from primitives

Each component typically includes:
- `*.svelte` - Component implementation
- `*.stories.ts` - Storybook stories
- `*.test.ts` - Unit tests
- `index.ts` - Barrel export
2 changes: 2 additions & 0 deletions packages/ui/bunfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[test]
preload = ["./tests/svelte-plugin.ts", "./tests/setup.ts"]
1 change: 1 addition & 0 deletions packages/ui/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("Hello via Bun!");
Loading
Loading