Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d549f09
Design system iteration
michael Sep 5, 2026
7fa38f9
Finalize buttons and add typography
michael Sep 5, 2026
b07af0f
Add pill style to design system
michael Sep 5, 2026
a0267d5
Add formatting styles to the design system
michael Sep 5, 2026
96fee89
Include context menu and navigation links in the design system
michael Sep 5, 2026
ef1ee8c
Smart adjustments to --button-border-radius setting
michael Sep 5, 2026
c1a7834
Include an example main navigation
michael Sep 5, 2026
a517f1f
Adaptive underline thickness
michael Sep 5, 2026
17149c5
Cap border radius for marks with background
michael Sep 5, 2026
ac61adc
Document page limiter
michael Sep 5, 2026
46a4d3f
Document vertical block spacing
michael Sep 5, 2026
a022b05
Use tab indentation consistently and reference design system in README
michael Sep 5, 2026
558241b
Consistent rules and spacing for vertical block spacing
michael Sep 5, 2026
e5514c5
Better page title
michael Sep 5, 2026
0c03695
Document foundations, such as colors
michael Sep 5, 2026
90a5083
Serve design system as a regular page with nav and footer
michael Sep 5, 2026
0ba9357
Apply design system to buttons
michael Sep 6, 2026
af44172
Support small button layouts too
michael Sep 6, 2026
0dad00c
Make nav and descriptive listing conform to the design system
michael Sep 6, 2026
11c3e1e
Make Toolbar styles conform to the design system
michael Sep 6, 2026
6999491
Editor styles and table of contents pill
michael Sep 6, 2026
b2b9901
Make Table Of Contents a popover
michael Sep 6, 2026
593cfb7
More descriptive zoom cursor for videos
michael Sep 7, 2026
e80bebb
Document "tracks" in the design system
michael Sep 7, 2026
3bf6099
Fix styling edge cases around buttons and nav
michael Sep 7, 2026
2965c7c
Adjust link style for descriptive/titled gallery items
michael Sep 7, 2026
1844d34
Give variant selector a minimum width on mobile
michael Sep 7, 2026
78395ae
Remove some mobile height adjustments
michael Sep 7, 2026
7b1905f
Fix Table Of Contents positioning
michael Sep 7, 2026
8706929
Apply design system to page browser
michael Sep 7, 2026
d28fa1c
Text input outlines in --editing color
michael Sep 7, 2026
45754de
Use consistent styles in design system
michael Sep 7, 2026
2ae3ca8
Improve spacing on the design system page
michael Sep 7, 2026
383e989
Use generous block spacing for first section in design sytem
michael Sep 7, 2026
ef72f70
Remove no longer needed --secondary-button-background contract
michael Sep 7, 2026
2f88d7b
Cleanup
michael Sep 7, 2026
227b7d5
Make sure _self targets don't break client side navigation
michael Sep 7, 2026
baa47d0
Box shadow is no longer a design token
michael Sep 7, 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
17 changes: 17 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,26 @@ Repository-specific guidance for coding agents working on Svedit.

## Code style

- Use tabs for indentation throughout the project, including code snippets in documentation and design system examples. Preserve spaces only where the file format requires them.
- Use `snake_case` for project-defined JavaScript and TypeScript identifiers. Keep web platform and Svelte APIs in their native `camelCase` form.
- Prefer Tailwind classes and minimize custom CSS. For CSS custom properties, use Tailwind's arbitrary-value utilities, such as `text-(--editing)` and `border-(--editing)`, where applicable.

- Prefix all project-defined CSS classes with `ew-`, including component, state, and custom utility classes. Standard Tailwind classes and classes required by third-party libraries retain their original names.

## UI verification

- The user manually verifies UI changes. Do not use a browser, screenshots, or computer-use tools to verify the UI unless the user explicitly asks.
- Use appropriate code checks, such as formatting, linting, and Svelte diagnostics, without starting a browser-based verification workflow.

## Design system

- Inline formatting styles (emphasis, strong, link, code, and highlight) are mutually exclusive. Never nest them or apply multiple styles to the same text.

- Consult the [design system source](src/routes/design-system/+page.svelte) before styling UI. With the development server running, the user can open [the design system in a browser](http://localhost:5173/design-system) to inspect typography, spacing, buttons, and editor pills, and inspect the source for their recipes. Shared tokens and typography utilities live in `src/app.css`. Follow the UI verification rules above for agent browser use.
- When customizing an Editable site, prefer updating the design system first, then adopting those changes in the actual site components. This gives agents and people working manually a concrete reference to implement consistently.
- Keep reference examples as explicit HTML, SVG, and Tailwind classes. Repetition is intentional; application components own behavior and may adapt the recipes when their interaction requires it.
- Document new visual patterns in the reference page so future changes have a concrete example to follow.

## Architecture

Svedit is a Svelte 5 rich content editor built around a graph-based document model.
Expand Down
181 changes: 181 additions & 0 deletions DESIGN_SYSTEM.md

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ From here on, `git push` saves your work to your own repo. To bring in Editable

### Styling

With the development server running, open the [design system](http://localhost:5173/design-system) in your browser to explore typography, spacing, buttons, and editor pills. Inspect its [source code](src/routes/design-system/+page.svelte) for the corresponding markup and styles.

When customizing your Editable site, ideally update the design system first, then apply those changes to the actual site components. This gives you a concrete visual reference to work from and helps keep the site consistent, whether you build it with an agent or edit the code manually.

Adjust the colors and fonts directly in `src/app.css`:

```css
Expand Down Expand Up @@ -635,7 +639,6 @@ Create `src/app/components/Hero.svelte`. It reads the node at `path`, renders ea
import { get_svedit_context } from '#app/svedit_context.js';
import MediaProperty from './MediaProperty.svelte';


const svedit = get_svedit_context();
let { path }: { path: DocumentPath } = $props();
let node: Nodes['hero'] = $derived(svedit.session.get(path));
Expand Down Expand Up @@ -664,12 +667,12 @@ Create `src/app/components/Hero.svelte`. It reads the node at `path`, renders ea
<Node class="ew-hero bg-(--background) text-(--foreground)" {path}>
<div class="mx-auto max-w-7xl">
{#if layout === 'side-by-side'}
<div class="px-5 sm:px-7 grid items-center gap-10 py-16 md:grid-cols-2">
<div class="grid items-center gap-10 px-5 py-16 sm:px-7 md:grid-cols-2">
<div>{@render text()}</div>
{@render media()}
</div>
{:else}
<div class="px-5 sm:px-7 flex flex-col gap-10 py-16 text-center">
<div class="flex flex-col gap-10 px-5 py-16 text-center sm:px-7">
<div class="mx-auto max-w-2xl">{@render text()}</div>
{@render media()}
</div>
Expand Down
61 changes: 35 additions & 26 deletions src/app.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
@import 'tailwindcss';
@plugin '@tailwindcss/forms';

/* Resolve relative radius units where assigned, so nested controls inherit the same length. */
@property --button-border-radius {
syntax: '<length>';
inherits: true;
initial-value: 0px;
}

@font-face {
font-family: 'Inter';
src: url('/fonts/InterVariable.woff2') format('woff2');
Expand Down Expand Up @@ -56,7 +63,7 @@
/* Foreground color for content displayed on the editing accent. */
--editing-foreground: var(--background);

/* Rounded corners for buttons and navigation items. */
/* Rounded corners for controls; reference pills and popovers derive their shape from this. */
--button-border-radius: 3rem;
/* Rounded corners for images. */
--image-border-radius: 2.2rem;
Expand All @@ -69,77 +76,79 @@
--font-mono:
'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
'Courier New', monospace;
--shadow-sm: 0 2px 4px -1px oklch(0 0 0 / 0.12), 0 1px 2px -1px oklch(0 0 0 / 0.12);
--shadow-xl: 0 20px 25px -5px oklch(0 0 0 / 0.12), 0 8px 10px -6px oklch(0 0 0 / 0.12);
}

/* Typography system */
/******************************************************************/

/* E.g. Heading1XL */
/* Large display headings use medium weight; smaller headings use semibold. */
/* Heading1XL */
@utility display-1 {
@apply font-sans text-6xl leading-tight tracking-tight text-balance lg:text-7xl;
@apply font-sans text-6xl leading-tight font-medium tracking-tight text-balance lg:text-7xl;
}

/* E.g. Heading1 */
/* Heading1 */
@utility display-2 {
@apply font-sans text-5xl leading-tight tracking-tight text-balance lg:text-6xl;
@apply font-sans text-5xl leading-tight font-medium tracking-tight text-balance lg:text-6xl;
}

/* E.g. Heading2 */
/* Heading2 */
@utility display-3 {
@apply font-sans text-4xl leading-tight tracking-tight text-balance lg:text-5xl;
@apply font-sans text-4xl leading-tight font-medium tracking-tight text-balance lg:text-5xl;
}

/* E.g. Heading3 */
/* Heading3 */
@utility display-4 {
@apply font-sans text-3xl leading-tight tracking-tight text-balance lg:text-4xl;
@apply font-sans text-3xl leading-tight font-semibold tracking-tight text-balance lg:text-4xl;
}

/* E.g. Heading4, TitleGallery.title, ... */
/* Heading4 and gallery titles */
@utility display-5 {
@apply font-sans text-2xl leading-tight tracking-tight text-balance lg:text-3xl;
@apply font-sans text-2xl leading-tight font-semibold tracking-tight text-balance lg:text-3xl;
}

/* ParagraphSM, ListingItem.description, ... */
/* Body text uses regular weight and a consistent 1.5 line height. */
/* Small paragraphs and listing descriptions */
@utility body-sm {
@apply font-sans text-sm;
@apply font-sans text-sm leading-normal font-normal;
}

/* Paragraph, ... */
/* Standard paragraphs */
@utility body-base {
@apply font-sans text-base;
@apply font-sans text-base leading-normal font-normal;
}

/* ParagraphLG, ... */
/* Large paragraphs */
@utility body-lg {
@apply font-sans text-lg;
@apply font-sans text-lg leading-normal font-normal;
}

/* ParagraphXL, ... */
/* Introductory paragraphs */
@utility body-xl {
@apply font-sans text-xl lg:text-2xl;
@apply font-sans text-xl leading-normal font-normal lg:text-2xl;
}

/* EW-specific utils */
/* Vertical block spacing */
/******************************************************************/

@utility pt-section-wide {
/* Defaults for each edge. Replace the utility with explicit classes for custom spacing. */
@utility pt-block-generous {
@apply pt-10 sm:pt-14 md:pt-16 lg:pt-28;
}

@utility pt-section-narrow {
@utility pt-block-compact {
@apply pt-4 lg:pt-7;
}

@utility pb-section-wide {
@utility pb-block-generous {
@apply pb-10 sm:pb-14 md:pb-16 lg:pb-28;
}

@utility pb-section-narrow {
@utility pb-block-compact {
@apply pb-4 lg:pb-7;
}

/* EW-specific utilities */
@utility ew-bg-checkerboard {
background:
linear-gradient(
Expand Down
4 changes: 3 additions & 1 deletion src/app/app_context.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { getContext } from 'svelte';
import { getContext, type Snippet } from 'svelte';

/**
* The app-level context provided by App.svelte: server-derived flags plus
* the auth dialog state and its handlers.
*/
export type AppContext = {
/** Optional body for read-only routes using the shared site layout. */
readonly page_content?: Snippet;
readonly has_backend: boolean;
readonly can_edit: boolean;
readonly is_admin: boolean;
Expand Down
40 changes: 20 additions & 20 deletions src/app/components/Accordion.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@
let { path, mark: section = null } = $props();
let node: Nodes['accordion'] = $derived(svedit.session.get(path));
let accordion_layout = $derived(node.layout || 'narrow-left');
let padding_top_wide = $derived(!section || section?.is_start);
let padding_bottom_wide = $derived(!section || section?.is_end);
let padding_top_generous = $derived(!section || section.is_start);
let padding_bottom_generous = $derived(!section || section.is_end);
</script>

{#snippet narrow_left()}
<Node class="ew-accordion" {path}>
<div class="mx-auto max-w-7xl w-full">
<div class="mx-auto w-full max-w-7xl">
<div
class={[
padding_top_wide ? 'pt-section-wide' : 'pt-section-narrow',
padding_bottom_wide ? 'pb-section-wide' : 'pb-section-narrow'
padding_top_generous ? 'pt-block-generous' : 'pt-block-compact',
padding_bottom_generous ? 'pb-block-generous' : 'pb-block-compact'
]}
>
<div class="max-w-4xl px-5 sm:px-7 bg-(--background) text-(--foreground)">
<div class="max-w-4xl bg-(--background) px-5 text-(--foreground) sm:px-7">
<NodeArrayProperty class="flex flex-col" path={[...path, 'items']} />
</div>
</div>
Expand All @@ -30,14 +30,14 @@

{#snippet narrow_center()}
<Node class="ew-accordion" {path}>
<div class="mx-auto max-w-7xl w-full">
<div class="mx-auto w-full max-w-7xl">
<div
class={[
padding_top_wide ? 'pt-section-wide' : 'pt-section-narrow',
padding_bottom_wide ? 'pb-section-wide' : 'pb-section-narrow'
padding_top_generous ? 'pt-block-generous' : 'pt-block-compact',
padding_bottom_generous ? 'pb-block-generous' : 'pb-block-compact'
]}
>
<div class="mx-auto max-w-4xl px-5 sm:px-7 bg-(--background) text-(--foreground)">
<div class="mx-auto max-w-4xl bg-(--background) px-5 text-(--foreground) sm:px-7">
<NodeArrayProperty class="flex flex-col" path={[...path, 'items']} />
</div>
</div>
Expand All @@ -47,14 +47,14 @@

{#snippet narrow_right()}
<Node class="ew-accordion" {path}>
<div class="mx-auto max-w-7xl w-full">
<div class="mx-auto w-full max-w-7xl">
<div
class={[
padding_top_wide ? 'pt-section-wide' : 'pt-section-narrow',
padding_bottom_wide ? 'pb-section-wide' : 'pb-section-narrow'
padding_top_generous ? 'pt-block-generous' : 'pt-block-compact',
padding_bottom_generous ? 'pb-block-generous' : 'pb-block-compact'
]}
>
<div class="ml-auto max-w-4xl px-5 sm:px-7 bg-(--background) text-(--foreground)">
<div class="ml-auto max-w-4xl bg-(--background) px-5 text-(--foreground) sm:px-7">
<NodeArrayProperty class="flex flex-col" path={[...path, 'items']} />
</div>
</div>
Expand All @@ -64,12 +64,12 @@

{#snippet full_width()}
<Node class="ew-accordion" {path}>
<div class="mx-auto max-w-7xl w-full">
<div class="mx-auto w-full max-w-7xl">
<div
class={[
'px-5 sm:px-7',
padding_top_wide ? 'pt-section-wide' : 'pt-section-narrow',
padding_bottom_wide ? 'pb-section-wide' : 'pb-section-narrow'
padding_top_generous ? 'pt-block-generous' : 'pt-block-compact',
padding_bottom_generous ? 'pb-block-generous' : 'pb-block-compact'
]}
>
<div class="bg-(--background) text-(--foreground)">
Expand All @@ -82,12 +82,12 @@

{#snippet two_columns()}
<Node class="ew-accordion" {path}>
<div class="mx-auto max-w-7xl w-full">
<div class="mx-auto w-full max-w-7xl">
<div
class={[
'px-5 sm:px-7',
padding_top_wide ? 'pt-section-wide' : 'pt-section-narrow',
padding_bottom_wide ? 'pb-section-wide' : 'pb-section-narrow'
padding_top_generous ? 'pt-block-generous' : 'pt-block-compact',
padding_bottom_generous ? 'pb-block-generous' : 'pb-block-compact'
]}
>
<div class="bg-(--background) text-(--foreground)">
Expand Down
9 changes: 7 additions & 2 deletions src/app/components/App.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { setContext } from 'svelte';
import { setContext, type Snippet } from 'svelte';
import { dev } from '$app/env';
import { goto, invalidate, refreshAll } from '$app/navigation';
import { resolve } from '$app/paths';
Expand Down Expand Up @@ -29,7 +29,8 @@
is_new = false,
is_admin: server_is_admin = false,
can_edit = true,
origin = null
origin = null,
children
}: {
document?: any;
slug?: string | null;
Expand All @@ -38,6 +39,7 @@
is_admin?: boolean;
can_edit?: boolean;
origin?: string | null;
children?: Snippet;
} = $props();

// Backend availability and document editability are independent: read-only
Expand Down Expand Up @@ -69,6 +71,9 @@
let mobile_touch_started_at_page_end = $state(false);

const app = {
get page_content() {
return can_edit ? undefined : children;
},
get has_backend() {
return has_backend;
},
Expand Down
Loading