diff --git a/assets/css/app.css b/assets/css/app.css
index 98fdfe7..53d9dae 100644
--- a/assets/css/app.css
+++ b/assets/css/app.css
@@ -3,10 +3,24 @@
@source "../js/**/*.js";
@source "../../lib/elixir_ai_web.ex";
@source "../../lib/elixir_ai_web/**/*.*ex";
+@source inline("{bg-seafoam-950/30,bg-red-950/30,bg-green-950/30,bg-blue-950/30,bg-yellow-950/30,bg-purple-950/30,bg-pink-950/30}");
@plugin "@tailwindcss/forms";
@plugin "../heroicons_plugin.js";
@theme {
+ --color-brand: #fd4f00;
+
+ --color-seafoam-50: #ecfeff;
+ --color-seafoam-100: #cffafe;
+ --color-seafoam-200: #a5f3fc;
+ --color-seafoam-300: #67e8f9;
+ --color-seafoam-400: #22d3ee;
+ --color-seafoam-500: #06b6d4;
+ --color-seafoam-600: #0891b2;
+ --color-seafoam-700: #0e7490;
+ --color-seafoam-800: #155e75;
+ --color-seafoam-900: #164e63;
+ --color-seafoam-950: #083344;
}
@variant phx-click-loading (&.phx-click-loading, .phx-click-loading &);
@@ -17,7 +31,7 @@
/* Form Elements */
label {
- @apply block text-sm font-medium text-cyan-300 mb-1;
+ @apply block text-sm font-medium text-seafoam-300 mb-1;
}
input[type="text"],
@@ -29,11 +43,11 @@ input[type="url"],
textarea,
select {
@apply w-full rounded-md px-3 py-2 text-sm
- bg-cyan-950 text-cyan-50 placeholder-cyan-600
- border border-cyan-800
+ bg-seafoam-950 text-seafoam-50 placeholder-seafoam-600
+ border border-seafoam-800
outline-none
transition-colors duration-150
- focus:border-cyan-500 focus:ring-1 focus:ring-cyan-500;
+ focus:border-seafoam-500 focus:ring-1 focus:ring-seafoam-500;
}
textarea {
@@ -43,19 +57,19 @@ textarea {
button[type="submit"],
input[type="submit"] {
@apply px-4 py-2 rounded-md text-sm font-medium
- bg-cyan-600 text-white
- border border-cyan-500
+ bg-seafoam-600 text-white
+ border border-seafoam-500
transition-colors duration-150
- hover:bg-cyan-500
+ hover:bg-seafoam-500
disabled:opacity-40 disabled:cursor-not-allowed;
}
fieldset {
- @apply border border-cyan-800 rounded-md px-4 py-3;
+ @apply border border-seafoam-800 rounded-md px-4 py-3;
}
legend {
- @apply text-sm font-semibold text-cyan-400 px-1;
+ @apply text-sm font-semibold text-seafoam-400 px-1;
}
button {
@@ -72,8 +86,3 @@ button {
.reasoning-content.collapsed {
@apply opacity-0 max-h-0 pt-0 pb-0 mb-0;
}
-
-
-
-
-
diff --git a/assets/css/markdown.css b/assets/css/markdown.css
index 024f539..9857315 100644
--- a/assets/css/markdown.css
+++ b/assets/css/markdown.css
@@ -1,7 +1,7 @@
/* Rendered Markdown */
.markdown {
- @apply text-cyan-50 leading-7 text-base;
+ @apply text-seafoam-50 leading-7 text-base;
}
/* Headings */
@@ -11,26 +11,26 @@
.markdown h4,
.markdown h5,
.markdown h6 {
- @apply font-semibold text-cyan-300 mt-6 mb-2 leading-tight;
+ @apply font-semibold text-seafoam-300 mt-6 mb-2 leading-tight;
}
.markdown h1 {
- @apply text-3xl border-b border-cyan-900 pb-1;
+ @apply text-3xl border-b border-seafoam-900 pb-1;
}
.markdown h2 {
- @apply text-2xl border-b border-cyan-900 pb-1;
+ @apply text-2xl border-b border-seafoam-900 pb-1;
}
.markdown h3 {
- @apply text-xl text-cyan-200;
+ @apply text-xl text-seafoam-200;
}
.markdown h4 {
- @apply text-lg text-cyan-200;
+ @apply text-lg text-seafoam-200;
}
.markdown h5 {
- @apply text-base text-cyan-100;
+ @apply text-base text-seafoam-100;
}
.markdown h6 {
- @apply text-sm text-cyan-100;
+ @apply text-sm text-seafoam-100;
}
.markdown p {
@@ -38,33 +38,33 @@
}
.markdown a {
- @apply text-cyan-400 underline underline-offset-2 transition-colors duration-150 hover:text-cyan-300;
+ @apply text-seafoam-400 underline underline-offset-2 transition-colors duration-150 hover:text-seafoam-300;
}
.markdown strong {
- @apply font-bold text-cyan-100;
+ @apply font-bold text-seafoam-100;
}
.markdown em {
- @apply italic text-cyan-200;
+ @apply italic text-seafoam-200;
}
.markdown code {
- @apply font-mono text-sm bg-cyan-950 text-cyan-300 px-1 py-0.5 rounded border border-cyan-900;
+ @apply font-mono text-sm bg-seafoam-950 text-seafoam-300 px-1 py-0.5 rounded border border-seafoam-900;
}
.markdown pre {
- @apply bg-cyan-950 border border-cyan-900 rounded-lg px-5 py-4 overflow-x-auto my-4;
+ @apply bg-seafoam-950 border border-seafoam-900 rounded-lg px-5 py-4 overflow-x-auto my-4;
}
.markdown pre code {
- @apply bg-transparent border-0 p-0 text-sm text-cyan-100;
+ @apply bg-transparent border-0 p-0 text-sm text-seafoam-100;
}
.markdown blockquote {
- @apply border-l-2 border-cyan-700 my-4 px-4 py-2 bg-cyan-950 text-cyan-200 rounded-r italic;
+ @apply border-l-2 border-seafoam-700 my-4 px-4 py-2 bg-seafoam-950 text-seafoam-200 rounded-r italic;
}
.markdown hr {
- @apply border-0 border-t border-cyan-900 my-6;
+ @apply border-0 border-t border-seafoam-900 my-6;
}
.markdown ul,
.markdown ol {
@@ -80,7 +80,7 @@
@apply my-1;
}
.markdown li::marker {
- @apply text-cyan-700;
+ @apply text-seafoam-700;
}
.markdown ul ul,
@@ -95,22 +95,22 @@
@apply block w-full border-collapse my-4 text-sm overflow-x-auto;
}
.markdown thead {
- @apply bg-cyan-950;
+ @apply bg-seafoam-950;
}
.markdown th {
- @apply text-left px-3 py-2 text-cyan-300 font-semibold border-b-2 border-cyan-700;
+ @apply text-left px-3 py-2 text-seafoam-300 font-semibold border-b-2 border-seafoam-700;
}
.markdown td {
- @apply px-3 py-2 border-b border-cyan-900 text-cyan-100;
+ @apply px-3 py-2 border-b border-seafoam-900 text-seafoam-100;
}
.markdown tbody tr:hover {
- @apply bg-cyan-950;
+ @apply bg-seafoam-950;
}
.markdown img {
- @apply max-w-full rounded-md border border-cyan-900 my-2;
+ @apply max-w-full rounded-md border border-seafoam-900 my-2;
}
.markdown input[type="checkbox"] {
- @apply accent-cyan-700 mr-1;
+ @apply accent-seafoam-700 mr-1;
}
diff --git a/assets/tailwind.config.js b/assets/tailwind.config.js
deleted file mode 100644
index ce8719a..0000000
--- a/assets/tailwind.config.js
+++ /dev/null
@@ -1,104 +0,0 @@
-// See the Tailwind configuration guide for advanced usage
-// https://tailwindcss.com/docs/configuration
-
-const plugin = require("tailwindcss/plugin");
-const fs = require("fs");
-const path = require("path");
-
-module.exports = {
- content: [
- "./js/**/*.js",
- "../lib/elixir_ai_web.ex",
- "../lib/elixir_ai_web/**/*.*ex",
- ],
- safelist: [
- "bg-cyan-950/30",
- "bg-red-950/30",
- "bg-green-950/30",
- "bg-blue-950/30",
- "bg-yellow-950/30",
- "bg-purple-950/30",
- "bg-pink-950/30",
- ],
- theme: {
- extend: {
- colors: {
- brand: "#FD4F00",
- },
- },
- },
- plugins: [
- require("@tailwindcss/forms"),
- // Allows prefixing tailwind classes with LiveView classes to add rules
- // only when LiveView classes are applied, for example:
- //
- //
- //
- plugin(({ addVariant }) =>
- addVariant("phx-click-loading", [
- ".phx-click-loading&",
- ".phx-click-loading &",
- ]),
- ),
- plugin(({ addVariant }) =>
- addVariant("phx-submit-loading", [
- ".phx-submit-loading&",
- ".phx-submit-loading &",
- ]),
- ),
- plugin(({ addVariant }) =>
- addVariant("phx-change-loading", [
- ".phx-change-loading&",
- ".phx-change-loading &",
- ]),
- ),
-
- // Embeds Heroicons (https://heroicons.com) into your app.css bundle
- // See your `CoreComponents.icon/1` for more information.
- //
- plugin(function ({ matchComponents, theme }) {
- let iconsDir = path.join(__dirname, "../deps/heroicons/optimized");
- let values = {};
- let icons = [
- ["", "/24/outline"],
- ["-solid", "/24/solid"],
- ["-mini", "/20/solid"],
- ["-micro", "/16/solid"],
- ];
- icons.forEach(([suffix, dir]) => {
- fs.readdirSync(path.join(iconsDir, dir)).forEach((file) => {
- let name = path.basename(file, ".svg") + suffix;
- values[name] = { name, fullPath: path.join(iconsDir, dir, file) };
- });
- });
- matchComponents(
- {
- hero: ({ name, fullPath }) => {
- let content = fs
- .readFileSync(fullPath)
- .toString()
- .replace(/\r?\n|\r/g, "");
- let size = theme("spacing.6");
- if (name.endsWith("-mini")) {
- size = theme("spacing.5");
- } else if (name.endsWith("-micro")) {
- size = theme("spacing.4");
- }
- return {
- [`--hero-${name}`]: `url('data:image/svg+xml;utf8,${content}')`,
- "-webkit-mask": `var(--hero-${name})`,
- mask: `var(--hero-${name})`,
- "mask-repeat": "no-repeat",
- "background-color": "currentColor",
- "vertical-align": "middle",
- display: "inline-block",
- width: size,
- height: size,
- };
- },
- },
- { values },
- );
- }),
- ],
-};
diff --git a/config/config.exs b/config/config.exs
index b145435..8729216 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -25,7 +25,7 @@ config :esbuild,
]
config :tailwind,
- version: "4.0.9",
+ version: "4.2.2",
elixir_ai: [
args: ~w(
--input=css/app.css
diff --git a/lib/elixir_ai/ai_tools.ex b/lib/elixir_ai/ai_tools.ex
index 4e0bbc5..e477aea 100644
--- a/lib/elixir_ai/ai_tools.ex
+++ b/lib/elixir_ai/ai_tools.ex
@@ -83,7 +83,7 @@ defmodule ElixirAi.AiTools do
"color" => %{
"type" => "string",
"enum" => [
- "bg-cyan-950/30",
+ "bg-seafoam-950/30",
"bg-red-950/30",
"bg-green-950/30",
"bg-blue-950/30",
diff --git a/lib/elixir_ai_web/admin/admin_live.ex b/lib/elixir_ai_web/admin/admin_live.ex
index 285d614..c8df99a 100644
--- a/lib/elixir_ai_web/admin/admin_live.ex
+++ b/lib/elixir_ai_web/admin/admin_live.ex
@@ -108,7 +108,7 @@ defmodule ElixirAiWeb.AdminLive do
def render(assigns) do
~H"""
-
Cluster Admin
+
Cluster Admin
<%= for {node, status} <- @cluster_info.nodes do %>
@@ -121,12 +121,12 @@ defmodule ElixirAiWeb.AdminLive do
|> Enum.filter(fn {_, n} -> n == node end)
|> Enum.group_by(fn {view, _} -> view end) %>
-
-
+
+
- {node}
+ {node}
<%= if node == Node.self() do %>
- self
+ self
<% end %>
<.status_badge status={status} />
@@ -135,12 +135,12 @@ defmodule ElixirAiWeb.AdminLive do
<%= if node_singletons != [] do %>
-
+
Singletons
<%= for {module, _} <- node_singletons do %>
-
+
{inspect(module)}
<% end %>
@@ -150,15 +150,15 @@ defmodule ElixirAiWeb.AdminLive do
<%= if node_runners != [] do %>
-
+
Chat Runners
-
+
{length(node_runners)}
<%= for {name, _, _} <- node_runners do %>
-
+
{name}
<% end %>
@@ -168,14 +168,14 @@ defmodule ElixirAiWeb.AdminLive do
<%= if node_liveviews != %{} do %>
-
+
LiveViews
<%= for {view, instances} <- node_liveviews do %>
-
-
{short_module(view)}
-
×{length(instances)}
+
+ {short_module(view)}
+ ×{length(instances)}
<% end %>
@@ -183,7 +183,7 @@ defmodule ElixirAiWeb.AdminLive do
<% end %>
<%= if node_singletons == [] and node_runners == [] and node_liveviews == %{} do %>
-
No active processes
+
No active processes
<% end %>
@@ -207,7 +207,7 @@ defmodule ElixirAiWeb.AdminLive do
<% end %>
-
Refreshes every 1s or on node events.
+
Refreshes every 1s or on node events.
"""
end
@@ -236,7 +236,7 @@ defmodule ElixirAiWeb.AdminLive do
unreachable
<% other -> %>
-
+
{inspect(other)}
<% end %>
diff --git a/lib/elixir_ai_web/chat/chat_live.ex b/lib/elixir_ai_web/chat/chat_live.ex
index b82d3bd..94ec723 100644
--- a/lib/elixir_ai_web/chat/chat_live.ex
+++ b/lib/elixir_ai_web/chat/chat_live.ex
@@ -24,7 +24,7 @@ defmodule ElixirAiWeb.ChatLive do
|> assign(user_input: "")
|> assign(messages: conversation.messages)
|> assign(streaming_response: conversation.streaming_response)
- |> assign(background_color: "bg-cyan-950/30")
+ |> assign(background_color: "bg-seafoam-950/30")
|> assign(provider: conversation.provider)
|> assign(providers: AiProvider.all())
|> assign(db_error: nil)
@@ -42,7 +42,7 @@ defmodule ElixirAiWeb.ChatLive do
|> assign(user_input: "")
|> assign(messages: [])
|> assign(streaming_response: nil)
- |> assign(background_color: "bg-cyan-950/30")
+ |> assign(background_color: "bg-seafoam-950/30")
|> assign(provider: nil)
|> assign(providers: AiProvider.all())
|> assign(db_error: Exception.format(:error, reason))
@@ -54,7 +54,7 @@ defmodule ElixirAiWeb.ChatLive do
~H"""
- <.link navigate={~p"/"} class="text-cyan-700 hover:text-cyan-400 transition-colors">
+ <.link navigate={~p"/"} class="text-seafoam-700 hover:text-seafoam-400 transition-colors">
←
{@conversation_name}
diff --git a/lib/elixir_ai_web/chat/chat_message.ex b/lib/elixir_ai_web/chat/chat_message.ex
index a8a6f39..33cf701 100644
--- a/lib/elixir_ai_web/chat/chat_message.ex
+++ b/lib/elixir_ai_web/chat/chat_message.ex
@@ -9,8 +9,8 @@ defmodule ElixirAiWeb.ChatMessage do
def tool_result_message(assigns) do
~H"""
-
-
+
+
- tool result
- {@tool_call_id}
+ tool result
+ {@tool_call_id}
-
{@content}
+
{@content}
"""
@@ -38,7 +38,7 @@ defmodule ElixirAiWeb.ChatMessage do
def user_message(assigns) do
~H"""
-
@@ -85,14 +85,14 @@ defmodule ElixirAiWeb.ChatMessage do
<%= if @reasoning_content && @reasoning_content != "" do %>
@@ -146,14 +146,14 @@ defmodule ElixirAiWeb.ChatMessage do
<%= if @reasoning_content && @reasoning_content != "" do %>