Skip to content

Commit 7b4a0cb

Browse files
Merge pull request #377 from basecamp/dark-mode
2 parents b7028ab + 95a6a2d commit 7b4a0cb

File tree

10 files changed

+82
-18
lines changed

10 files changed

+82
-18
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,11 @@ For the CSS, you can include it with the standard Rails helper:
8787
<%= stylesheet_link_tag "lexxy" %>
8888
```
8989

90-
Of course, you can copy the CSS to your project and adapt it to your needs.
90+
You can copy the CSS to your project and adapt it to your needs.
91+
92+
#### Custom styles and dark mode
93+
94+
All of Lexxy's color styles are defiend as CSS variables in `app/stylesheets/lexxy-variables.css`. This enables a straightforward way to customize Lexxy to match your application's theme. You can see an example implementation of a custom dark mode style in the Sandbox's stylesheet at `test/dummy/app/assets/stylesheets/sandbox.css`.
9195

9296
#### Rendered Action Text content
9397

app/assets/javascript/lexxy.js.gz

893 Bytes
Binary file not shown.
649 Bytes
Binary file not shown.

app/assets/stylesheets/lexxy-content.css

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@
6464
display: none;
6565
}
6666

67+
a {
68+
color: var(--lexxy-color-link);
69+
}
70+
6771
img,
6872
video,
6973
embed,
@@ -208,7 +212,8 @@
208212
font-size: var(--lexxy-text-small);
209213

210214
input {
211-
color: inherit;
215+
background: var(--lexxy-color-canvas);
216+
color: var(--lexxy-color-text);
212217
border: none;
213218
inline-size: 100%;
214219
max-inline-size: 100%;

app/assets/stylesheets/lexxy-editor.css

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
border: 1px solid var(--lexxy-color-ink-lighter);
1313
border-radius: calc(var(--lexxy-radius) + var(--lexxy-toolbar-gap));
14+
background-color: var(--lexxy-color-canvas);
1415
display: block;
1516
overflow: visible;
1617
position: relative;
@@ -36,7 +37,7 @@
3637

3738
@media(any-hover: hover) {
3839
&:hover {
39-
filter: brightness(0.9);
40+
background: var(--lexxy-color-ink-lightest);
4041
}
4142
}
4243
}
@@ -102,12 +103,13 @@
102103
display: grid;
103104
place-items: center;
104105

105-
&:is(:active) {
106-
background-color: var(--lexxy-color-selected);
107-
}
108-
106+
&:is(:active),
109107
&[aria-pressed="true"] {
110108
background-color: var(--lexxy-color-selected);
109+
110+
&:hover {
111+
background-color: var(--lexxy-color-selected-hover);
112+
}
111113
}
112114

113115
svg {
@@ -133,7 +135,7 @@
133135
}
134136

135137
[open] & {
136-
filter: brightness(0.9);
138+
background-color: var(--lexxy-color-ink-lightest);
137139
}
138140
}
139141
}
@@ -180,13 +182,16 @@
180182
}
181183

182184
input[type="url"] {
185+
background-color: var(--lexxy-color-canvas);
183186
border: 1px solid var(--lexxy-color-ink-lighter);
184187
border-radius: var(--lexxy-radius);
188+
color: var(--lexxy-color-text);
185189
min-inline-size: 30ch;
186190
}
187191

188192
button {
189193
background-color: var(--lexxy-color-ink-lightest);
194+
color: var(--lexxy-color-text);
190195
inline-size: 100%;
191196
justify-content: center;
192197
}

app/assets/stylesheets/lexxy-variables.css

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
--lexxy-color-ink-inverted: white;
99

1010
--lexxy-color-accent-dark: oklch(57% 0.19 260);
11-
--lexxy-color-accent-medium: oklch(66% 0.196 258);
11+
--lexxy-color-accent-medium: oklch(75% 0.196 258);
12+
--lexxy-color-accent-light: oklch(88% 0.026 254);
1213
--lexxy-color-accent-lightest: oklch(92% 0.026 254);
1314

1415
--lexxy-color-red: oklch(60% 0.15 27);
@@ -30,7 +31,8 @@
3031
--lexxy-color-text-subtle: var(--lexxy-color-ink-medium);
3132
--lexxy-color-link: var(--lexxy-color-accent-dark);
3233
--lexxy-color-selected: var(--lexxy-color-accent-lightest);
33-
--lexxy-color-selected-dark: var(--lexxy-color-blue-medium);
34+
--lexxy-color-selected-hover: var(--lexxy-color-accent-light);
35+
--lexxy-color-selected-dark: var(--lexxy-color-blue);
3436
--lexxy-color-code-bg: var(--lexxy-color-ink-lightest);
3537

3638
/* Typography */
@@ -48,4 +50,4 @@
4850
--lexxy-radius: 0.5ch;
4951
--lexxy-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
5052
--lexxy-z-popup: 1000;
51-
}
53+
}

test/dummy/app/assets/stylesheets/sandbox.css

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,52 @@
1+
:root {
2+
--sandbox-background-color: oklch(98% 0 0);
3+
--sandbox-text-color: oklch(20% 0 0);
4+
--sandbox-code-color: #2d3748;
5+
6+
/* Dark mode colors */
7+
@media (prefers-color-scheme: dark) {
8+
--sandbox-background-color: oklch(15% 0 0);
9+
--sandbox-text-color: oklch(96% 0 0);
10+
--sandbox-code-color: #f7fafc;
11+
12+
/* Lexxy dark mode colors */
13+
--lexxy-color-ink: oklch(96% 0 0);
14+
--lexxy-color-ink-medium: oklch(75% 0 0);
15+
--lexxy-color-ink-light: oklch(55% 0 0);
16+
--lexxy-color-ink-lighter: oklch(40% 0 0);
17+
--lexxy-color-ink-lightest: oklch(25% 0 0);
18+
--lexxy-color-ink-inverted: oklch(15% 0 0);
19+
20+
--lexxy-color-accent-dark: oklch(70% 0.30 260);
21+
--lexxy-color-accent-medium: oklch(75% 0.196 258);
22+
--lexxy-color-accent-light: oklch(45% 0.04 254);
23+
--lexxy-color-accent-lightest: oklch(35% 0.04 254);
24+
25+
--lexxy-color-red: oklch(70% 0.15 27);
26+
--lexxy-color-green: oklch(70% 0.15 145);
27+
--lexxy-color-blue: oklch(75% 0.196 258);
28+
--lexxy-color-purple: oklch(70% 0.15 305);
29+
30+
--lexxy-color-code-token-att: #ff7b72;
31+
--lexxy-color-code-token-comment: #8b949e;
32+
--lexxy-color-code-token-function: #d2a8ff;
33+
--lexxy-color-code-token-operator: #ff7b72;
34+
--lexxy-color-code-token-property: #79c0ff;
35+
--lexxy-color-code-token-punctuation: #f0f6fc;
36+
--lexxy-color-code-token-selector: #7ee787;
37+
--lexxy-color-code-token-variable: #ffa657;
38+
39+
--lexxy-shadow: 0 0 0 1px rgba(100, 100, 100, 0.3);
40+
}
41+
}
42+
143
html {
244
font-size: 16px;
345
}
446

547
body {
48+
background-color: var(--sandbox-background-color);
49+
color: var(--sandbox-text-color);
650
margin: 0;
751
padding: 0;
852
}
@@ -23,12 +67,11 @@ section {
2367
padding: var(--sandbox-padding);
2468

2569
&:first-child {
26-
box-shadow: 1px 0 2px oklch(95% 0 0);
2770
position: relative;
2871
}
2972

3073
&:last-child {
31-
background: oklch(98% 0 0);
74+
background: rgba(100, 100, 100, 0.1);
3275
overflow: hidden;
3376
}
3477
}
@@ -55,7 +98,7 @@ h2 {
5598

5699
pre[class*="language-"],
57100
code[class*="language-"] {
58-
color: #2d3748;
101+
color: var(--sandbox-code-color);
59102
background: none;
60103
font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
61104
font-size: 0.9rem;

test/dummy/app/javascript/controllers/lexxy_output_controller.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import htmlParser from "prettier/parser-html"
66
export default class extends Controller {
77
static targets = [ "editor", "output" ]
88

9+
connect() {
10+
this.refresh()
11+
}
12+
913
async refresh(event) {
1014
const code = this.editorTarget.value.trim()
1115
let formattedCode = await prettier.format(code, {

test/dummy/app/views/layouts/application.html.erb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818
<link rel="apple-touch-icon" href="/icon.png">
1919

2020
<%# Includes all stylesheet files in app/assets/stylesheets %>
21-
<%= stylesheet_link_tag :app %>
22-
21+
2322
<%= stylesheet_link_tag "lexxy" %>
2423

24+
<%= stylesheet_link_tag :app %>
25+
2526
<%= javascript_importmap_tags %>
2627
</head>
2728

test/dummy/app/views/sandbox/show.html.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
<% content_for :title, "Sandbox" %>
1+
<% content_for :title, "Lexxy Sandbox" %>
22

33
<main data-controller="lexxy-output" data-action="lexxy:change->lexxy-output#refresh">
44
<section>
55
<h2>Editor</h2>
66
<div>
7-
<%= rich_text_area_tag :sandbox, nil, placeholder: "Write something...", data: { lexxy_output_target: "editor" } do %>
7+
<%= rich_text_area_tag :sandbox, nil, value: "<h3>Lexxy</h3><p>Introducing <a href=\"https://github.com/basecamp/lexxy\">Lexxy</a>, a modern rich text editor for Rails</p><pre data-language=\"html\" data-highlight-language=\"html\">&lt;lexxy-editor placeholder=\"It all starts here...\"&gt;\n&lt;/lexxy-editor&gt;</pre><h4>Features</h4><ul><li>Built on top of Lexical, the powerful text editor framework from Meta.</li><li>Good HTML semantics. Paragraphs are real <code>&lt;p&gt;</code> tags, as they should be.</li><li>Markdown support: shortcuts, auto-formatting on paste.</li><li>Real-time code syntax highlighting.</li><li>Create links by pasting URLs on selected text.</li><li>Configurable prompts. Support for mentions and other interactive prompts with multiple loading and filtering strategies.</li><li>Preview attachments like PDFs and Videos in the editor.</li><li>Works seamlessly with Action Text, generating the same canonical HTML format it expects for attachments.</li></ul>", placeholder: "Write something...", data: { lexxy_output_target: "editor" } do %>
88
<lexxy-prompt trigger="@" src="<%= people_path %>" name="mention"></lexxy-prompt>
99
<% end %>
1010
</div>

0 commit comments

Comments
 (0)