Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## unreleased

* Support rendering tooltips. ([#26][#26])

[#26]: https://github.com/azriel91/disposition/pull/26


## 0.1.0 (2026-04-11)

* Add `playground`. ([#16][#16], [#17][#17])
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Playground: <https://azriel.im/disposition>.
* [x] Circle as node shape.
* [x] Light and dark modes.
* [x] Dependencies between process steps.
* [ ] Tooltips.
* [x] Tooltips.
* [ ] Images in nodes.
* [ ] Responsive layout.

Expand Down
54 changes: 0 additions & 54 deletions app/playground/assets/tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@
--spacing: 0.25rem;
--container-sm: 24rem;
--container-lg: 32rem;
--container-2xl: 42rem;
--container-3xl: 48rem;
--container-4xl: 56rem;
--text-xs: 0.75rem;
--text-xs--line-height: calc(1 / 0.75);
--text-sm: 0.875rem;
Expand All @@ -46,8 +44,6 @@
--text-lg--line-height: calc(1.75 / 1.125);
--text-xl: 1.25rem;
--text-xl--line-height: calc(1.75 / 1.25);
--text-2xl: 1.5rem;
--text-2xl--line-height: calc(2 / 1.5);
--font-weight-semibold: 600;
--font-weight-bold: 700;
--tracking-wide: 0.025em;
Expand Down Expand Up @@ -292,9 +288,6 @@
.mr-1 {
margin-right: calc(var(--spacing) * 1);
}
.mb-0 {
margin-bottom: calc(var(--spacing) * 0);
}
.mb-0\.5 {
margin-bottom: calc(var(--spacing) * 0.5);
}
Expand Down Expand Up @@ -331,9 +324,6 @@
.inline-block {
display: inline-block;
}
.table {
display: table;
}
.h-4 {
height: calc(var(--spacing) * 4);
}
Expand Down Expand Up @@ -418,9 +408,6 @@
.shrink-0 {
flex-shrink: 0;
}
.border-collapse {
border-collapse: collapse;
}
.rotate-90 {
rotate: 90deg;
}
Expand All @@ -439,9 +426,6 @@
.cursor-pointer {
cursor: pointer;
}
.resize {
resize: both;
}
.list-inside {
list-style-position: inside;
}
Expand Down Expand Up @@ -591,9 +575,6 @@
.border-b-transparent {
border-bottom-color: transparent;
}
.bg-black {
background-color: var(--color-black);
}
.bg-black\/50 {
background-color: color-mix(in srgb, #000000 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
Expand Down Expand Up @@ -636,9 +617,6 @@
.p-4 {
padding: calc(var(--spacing) * 4);
}
.px-0 {
padding-inline: calc(var(--spacing) * 0);
}
.px-0\.5 {
padding-inline: calc(var(--spacing) * 0.5);
}
Expand All @@ -654,9 +632,6 @@
.px-4 {
padding-inline: calc(var(--spacing) * 4);
}
.py-0 {
padding-block: calc(var(--spacing) * 0);
}
.py-0\.5 {
padding-block: calc(var(--spacing) * 0.5);
}
Expand Down Expand Up @@ -747,9 +722,6 @@
.text-nowrap {
text-wrap: nowrap;
}
.text-wrap {
text-wrap: wrap;
}
.whitespace-nowrap {
white-space: nowrap;
}
Expand Down Expand Up @@ -804,9 +776,6 @@
.line-through {
text-decoration-line: line-through;
}
.underline {
text-decoration-line: underline;
}
.accent-blue-500 {
accent-color: var(--color-blue-500);
}
Expand All @@ -831,10 +800,6 @@
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.outline {
outline-style: var(--tw-outline-style);
outline-width: 1px;
}
.blur {
--tw-blur: blur(8px);
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
Expand All @@ -843,9 +808,6 @@
--tw-invert: invert(100%);
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
}
.filter {
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
}
.transition-all {
transition-property: all;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
Expand Down Expand Up @@ -1161,11 +1123,6 @@
flex-direction: row;
}
}
.\[\&_\*\]\:mb-2 {
& * {
margin-bottom: calc(var(--spacing) * 2);
}
}
.\[\&_\*\]\:mb-3 {
& * {
margin-bottom: calc(var(--spacing) * 3);
Expand Down Expand Up @@ -1222,11 +1179,6 @@
}
}
}
.\[\&\>li\]\:mb-2 {
&>li {
margin-bottom: calc(var(--spacing) * 2);
}
}
.\[\&\>rect\]\:fill-gray-300 {
&>rect {
fill: var(--color-gray-300);
Expand Down Expand Up @@ -1416,11 +1368,6 @@
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-outline-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@property --tw-blur {
syntax: "*";
inherits: false;
Expand Down Expand Up @@ -1504,7 +1451,6 @@
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-offset-shadow: 0 0 #0000;
--tw-outline-style: solid;
--tw-blur: initial;
--tw-brightness: initial;
--tw-contrast: initial;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ use disposition::input_model::InputDiagram;

use crate::{
components::editor::{
EntityTypesPage, ProcessesPage, RenderOptionsPage, TagsPage, TextPage, ThemeBaseStylesPage,
EntityPage, ProcessesPage, RenderOptionsPage, TagsPage, TextPage, ThemeBaseStylesPage,
ThemeDependenciesStylesPage, ThemeProcessStepStylesPage, ThemeStyleAliasesPage,
ThemeTagsFocusPage, ThemeTypesStylesPage, ThingCopyTextPage, ThingDependenciesPage,
ThingEntityDescsPage, ThingEntityTooltipsPage, ThingInteractionsPage, ThingLayoutPage,
ThingNamesPage,
ThingEntityDescsPage, ThingInteractionsPage, ThingLayoutPage, ThingNamesPage,
},
editor_state::{EditorPage, EditorPageTheme, EditorPageThing},
};
Expand All @@ -32,14 +31,13 @@ pub fn EditorPageContent(
EditorPageThing::Names => rsx! { ThingNamesPage { input_diagram } },
EditorPageThing::CopyText => rsx! { ThingCopyTextPage { input_diagram } },
EditorPageThing::EntityDescs => rsx! { ThingEntityDescsPage { input_diagram } },
EditorPageThing::EntityTooltips => rsx! { ThingEntityTooltipsPage { input_diagram } },
},
EditorPage::ThingLayout => rsx! { ThingLayoutPage { input_diagram } },
EditorPage::ThingDependencies => rsx! { ThingDependenciesPage { input_diagram } },
EditorPage::ThingInteractions => rsx! { ThingInteractionsPage { input_diagram } },
EditorPage::Processes => rsx! { ProcessesPage { input_diagram } },
EditorPage::Tags => rsx! { TagsPage { input_diagram } },
EditorPage::EntityTypes => rsx! { EntityTypesPage { input_diagram } },
EditorPage::Entity(_) => rsx! { EntityPage { active_page, input_diagram } },
EditorPage::RenderOptions => rsx! { RenderOptionsPage { input_diagram } },
EditorPage::Theme(sub) => match sub {
EditorPageTheme::BaseStyles => rsx! { ThemeBaseStylesPage { input_diagram } },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ use dioxus::{
use crate::editor_state::EditorPage;

use self::{
editor_tab_bar_tabs::EditorTabBarTabs, editor_tab_bar_theme::EditorTabBarTheme,
editor_tab_bar_thing::EditorTabBarThing, editor_tab_bar_thing_pages::EditorTabBarThingPages,
editor_tab_bar_entity::EditorTabBarEntity, editor_tab_bar_tabs::EditorTabBarTabs,
editor_tab_bar_theme::EditorTabBarTheme, editor_tab_bar_thing::EditorTabBarThing,
editor_tab_bar_thing_pages::EditorTabBarThingPages,
};

mod editor_tab_bar_entity;
mod editor_tab_bar_entity_pages;
mod editor_tab_bar_tabs;
mod editor_tab_bar_theme;
mod editor_tab_bar_theme_pages;
Expand Down Expand Up @@ -123,16 +126,16 @@ pub fn EditorTabBar(active_page: Signal<EditorPage>) -> Element {
EditorTabBarTabs { active_page }
}

// === Things sub-tabs (only visible when a Things page is active) === //
// === Sub-tabs (only visible when a grouped page is active) === //
match current_page {
EditorPage::Thing(_) => rsx! { EditorTabBarThing { active_page } },
EditorPage::Entity(_) => rsx! { EditorTabBarEntity { active_page } },
EditorPage::Theme(_) => rsx! { EditorTabBarTheme { active_page } },
EditorPage::ThingLayout |
EditorPage::ThingDependencies |
EditorPage::ThingInteractions |
EditorPage::Processes |
EditorPage::Tags |
EditorPage::EntityTypes |
EditorPage::RenderOptions |
EditorPage::Text => rsx! {},
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use dioxus::{
prelude::{
component, dioxus_core, dioxus_elements, dioxus_signals, document, rsx, Element, Key, Props,
},
signals::Signal,
};

use crate::{
components::disposition_editor::editor_tab_bar::editor_tab_bar_entity_pages::EditorTabBarEntityPages,
editor_state::EditorPage,
};

#[component]
pub(crate) fn EditorTabBarEntity(active_page: Signal<EditorPage>) -> Element {
rsx! {
div {
class: "
flex
flex-row
flex-wrap
gap-1
border-b
border-gray-700
mb-1
pl-2
",
role: "tablist",

onkeydown: move |evt| {
match evt.key() {
Key::ArrowLeft => {
evt.prevent_default();
document::eval(
"(() => {\
let el = document.activeElement;\
if (!el || el.getAttribute('role') !== 'tab') return;\
let prev = el.previousElementSibling;\
if (prev) prev.focus();\
else { let last = el.parentElement?.lastElementChild; if (last) last.focus(); }\
})()"
);
}
Key::ArrowRight => {
evt.prevent_default();
document::eval(
"(() => {\
let el = document.activeElement;\
if (!el || el.getAttribute('role') !== 'tab') return;\
let next = el.nextElementSibling;\
if (next) next.focus();\
else { let first = el.parentElement?.firstElementChild; if (first) first.focus(); }\
})()"
);
}
_ => {}
}
},

EditorTabBarEntityPages { active_page }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use dioxus::{
prelude::{component, dioxus_core, dioxus_elements, dioxus_signals, rsx, Element, Key, Props},
signals::{ReadableExt, Signal, WritableExt},
};

use crate::{
components::disposition_editor::editor_tab_bar::{SUB_TAB_CLASS, TAB_ACTIVE, TAB_INACTIVE},
editor_state::{EditorPage, EditorPageEntity},
};

#[component]
pub fn EditorTabBarEntityPages(active_page: Signal<EditorPage>) -> Element {
let current_page = active_page.read().clone();

rsx! {
for sub in enum_iterator::all::<EditorPageEntity>() {
{
let sub_page = EditorPage::Entity(sub.clone());
let is_active = current_page == sub_page;
let css = format!(
"{SUB_TAB_CLASS} {}",
if is_active { TAB_ACTIVE } else { TAB_INACTIVE }
);
let tab_index = if is_active { "0" } else { "-1" };
let sub_page_click = sub_page.clone();
let sub_page_key = sub_page.clone();

rsx! {
span {
key: "{sub.label()}",
role: "tab",
tabindex: "{tab_index}",
"aria-selected": if is_active { "true" } else { "false" },
class: "{css}",
onclick: {
let page = sub_page_click.clone();
move |_| {
active_page.set(page.clone());
}
},
onkeydown: {
let page = sub_page_key.clone();
move |evt| {
let activate = match evt.key() {
Key::Enter => true,
Key::Character(ref c) if c == " " => true,
_ => false,
};
if activate {
evt.prevent_default();
active_page.set(page.clone());
}
}
},
"{sub.label()}"
}
}
}
}
}
}
Loading
Loading