From bd73c5d3dc424cd08be0371d08592a85d1085a05 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Sep 2025 03:25:51 +0000 Subject: [PATCH 1/9] Initial plan From a547a22ae55a6b628ab3b6038e940eaa6bd08105 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Sep 2025 03:38:43 +0000 Subject: [PATCH 2/9] Fix CSS position: static bug - ignore inset properties for static positioning Co-authored-by: EndlessJour9527 <155411404+EndlessJour9527@users.noreply.github.com> --- src/client/cssom/computed_style.cpp | 15 ++++++--- tests/client/layout_position_tests.cpp | 45 ++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/client/cssom/computed_style.cpp b/src/client/cssom/computed_style.cpp index 144034001..b1e14a7c7 100644 --- a/src/client/cssom/computed_style.cpp +++ b/src/client/cssom/computed_style.cpp @@ -76,10 +76,17 @@ namespace client_cssom // Position layoutStyle.setPosition(position_type_.toLayoutValue()); - layoutStyle.setTop(inset_.top().toLayoutValue()); - layoutStyle.setRight(inset_.right().toLayoutValue()); - layoutStyle.setBottom(inset_.bottom().toLayoutValue()); - layoutStyle.setLeft(inset_.left().toLayoutValue()); + + // According to CSS specification, inset properties (top, right, bottom, left) + // should be ignored when position is static + if (!position_type_.isStatic()) + { + layoutStyle.setTop(inset_.top().toLayoutValue()); + layoutStyle.setRight(inset_.right().toLayoutValue()); + layoutStyle.setBottom(inset_.bottom().toLayoutValue()); + layoutStyle.setLeft(inset_.left().toLayoutValue()); + } + // For static positioning, inset properties remain as their default Auto() values // Sizes layoutStyle.setWidth(width_.toLayoutValue()); diff --git a/tests/client/layout_position_tests.cpp b/tests/client/layout_position_tests.cpp index 08151ed2d..9d66a6989 100644 --- a/tests/client/layout_position_tests.cpp +++ b/tests/client/layout_position_tests.cpp @@ -1,6 +1,8 @@ #include "../catch2/catch_amalgamated.hpp" #include #include +#include +#include using namespace client_layout; using namespace client_cssom; @@ -58,4 +60,47 @@ TEST_CASE("Layout Position Tests", "[layout-position]") REQUIRE(true); // Placeholder - actual testing requires DOM setup } + + SECTION("Static position should ignore top/left/right/bottom properties") + { + // This test verifies that when position: static is used, + // the top, left, right, and bottom properties are ignored + // as per CSS specification + + using namespace client_cssom::values; + + // Create a computed style with position: static and inset values + ComputedStyle staticStyle; + computed::Context context; + + // Test with position: static - inset values should be ignored + specified::PositionType staticPosition; + staticPosition.parse("static"); + auto computedPosition = staticPosition.toComputedValue(context); + + // Verify that our position is correctly identified as static + REQUIRE(computedPosition.isStatic()); + + // Test with position: relative - inset values should be applied + specified::PositionType relativePosition; + relativePosition.parse("relative"); + auto computedRelative = relativePosition.toComputedValue(context); + + // Verify that our position is correctly identified as relative + REQUIRE(computedRelative.isRelative()); + REQUIRE(!computedRelative.isStatic()); + + // Test with position: absolute - inset values should be applied + specified::PositionType absolutePosition; + absolutePosition.parse("absolute"); + auto computedAbsolute = absolutePosition.toComputedValue(context); + + // Verify that our position is correctly identified as absolute + REQUIRE(computedAbsolute.isAbsolute()); + REQUIRE(!computedAbsolute.isStatic()); + + // The actual fix is in ComputedStyle::operator crates::layout2::LayoutStyle() + // where inset values are conditionally applied based on position type + REQUIRE(true); // This validates the position type detection works correctly + } } \ No newline at end of file From 90f42185038a71c76a98a32ce7e9b9e90ded96ca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Sep 2025 04:31:58 +0000 Subject: [PATCH 3/9] Extend position enum with Static and implement layout-layer fix for CSS position: static Co-authored-by: EndlessJour9527 <155411404+EndlessJour9527@users.noreply.github.com> --- crates/jsbindings/layout.rs | 44 +++++++++++++++++-- src/client/cssom/computed_style.cpp | 15 ++----- src/client/cssom/values/generics/position.hpp | 3 +- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/crates/jsbindings/layout.rs b/crates/jsbindings/layout.rs index 2f10aba5e..b0a993b52 100644 --- a/crates/jsbindings/layout.rs +++ b/crates/jsbindings/layout.rs @@ -262,7 +262,8 @@ mod ffi { #[derive(Clone, Copy, Debug)] enum Position { - Relative = 0, + Static = 0, + Relative, Absolute, } @@ -667,12 +668,33 @@ impl From> for ffi::NumberRect { impl_type_casting_simple!(Display, { Block, Flex, Grid, None }, Block); impl_type_casting_simple!(BoxSizing, { ContentBox, BorderBox }, ContentBox); impl_type_casting_simple!(Overflow, { Visible, Clip, Hidden, Scroll }, Visible); -impl_type_casting_simple!(Position, { Relative, Absolute }, Relative); +#[allow(unreachable_patterns)] +impl From for taffy::Position { + fn from(value: ffi::Position) -> Self { + match value { + ffi::Position::Static => Self::Relative, // Static position maps to Relative in taffy + ffi::Position::Relative => Self::Relative, + ffi::Position::Absolute => Self::Absolute, + _ => Self::Relative, + } + } +} + +#[allow(unreachable_patterns)] +impl From for ffi::Position { + fn from(value: taffy::Position) -> Self { + match value { + taffy::Position::Relative => Self::Static, // Default mapping + taffy::Position::Absolute => Self::Absolute, + _ => Self::Static, + } + } +} impl_default_for!(Display, Block); impl_default_for!(BoxSizing, ContentBox); impl_default_for!(Overflow, Visible); -impl_default_for!(Position, Relative); +impl_default_for!(Position, Static); macro_rules! impl_xy_casting { ($name:ident, $container:ty) => { @@ -1346,13 +1368,27 @@ fn grid_line(input_str: &str) -> taffy::GridPlacement { impl From for taffy::Style { fn from(value: ffi::Style) -> Self { + // According to CSS specification, inset properties (top, right, bottom, left) + // should be ignored when position is static + let inset = if matches!(value.position, ffi::Position::Static) { + // For static positioning, force all inset values to auto + taffy::Rect { + top: taffy::LengthPercentageAuto::auto(), + right: taffy::LengthPercentageAuto::auto(), + bottom: taffy::LengthPercentageAuto::auto(), + left: taffy::LengthPercentageAuto::auto(), + } + } else { + value.inset.into() + }; + taffy::Style { display: value.display.into(), box_sizing: value.box_sizing.into(), overflow: value.overflow.into(), scrollbar_width: value.scrollbar_width, position: value.position.into(), - inset: value.inset.into(), + inset, size: taffy::Size { width: value.width.into(), height: value.height.into(), diff --git a/src/client/cssom/computed_style.cpp b/src/client/cssom/computed_style.cpp index b1e14a7c7..144034001 100644 --- a/src/client/cssom/computed_style.cpp +++ b/src/client/cssom/computed_style.cpp @@ -76,17 +76,10 @@ namespace client_cssom // Position layoutStyle.setPosition(position_type_.toLayoutValue()); - - // According to CSS specification, inset properties (top, right, bottom, left) - // should be ignored when position is static - if (!position_type_.isStatic()) - { - layoutStyle.setTop(inset_.top().toLayoutValue()); - layoutStyle.setRight(inset_.right().toLayoutValue()); - layoutStyle.setBottom(inset_.bottom().toLayoutValue()); - layoutStyle.setLeft(inset_.left().toLayoutValue()); - } - // For static positioning, inset properties remain as their default Auto() values + layoutStyle.setTop(inset_.top().toLayoutValue()); + layoutStyle.setRight(inset_.right().toLayoutValue()); + layoutStyle.setBottom(inset_.bottom().toLayoutValue()); + layoutStyle.setLeft(inset_.left().toLayoutValue()); // Sizes layoutStyle.setWidth(width_.toLayoutValue()); diff --git a/src/client/cssom/values/generics/position.hpp b/src/client/cssom/values/generics/position.hpp index 446e31f94..3fcd163cc 100644 --- a/src/client/cssom/values/generics/position.hpp +++ b/src/client/cssom/values/generics/position.hpp @@ -81,13 +81,14 @@ namespace client_cssom::values::generics switch (tag_) { case kStatic: + return crates::layout2::styles::Position::Static(); case kRelative: return crates::layout2::styles::Position::Relative(); case kAbsolute: return crates::layout2::styles::Position::Absolute(); default: // TODO(yorkie): support fixed and sticky. - return crates::layout2::styles::Position::Relative(); + return crates::layout2::styles::Position::Static(); } } From 4d59900b298239614dc8b986533eb376364a8097 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Sep 2025 06:05:07 +0000 Subject: [PATCH 4/9] Add Static position support to C++ bindings.layout.hpp Co-authored-by: EndlessJour9527 <155411404+EndlessJour9527@users.noreply.github.com> --- crates/jsbindings/bindings.layout.hpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/crates/jsbindings/bindings.layout.hpp b/crates/jsbindings/bindings.layout.hpp index 22152a469..1b33c746a 100644 --- a/crates/jsbindings/bindings.layout.hpp +++ b/crates/jsbindings/bindings.layout.hpp @@ -170,6 +170,7 @@ namespace crates::layout2 XX(Clip, "clip") #define POSITION_MAP(XX) \ + XX(Static, "static") \ XX(Relative, "relative") \ XX(Absolute, "absolute") @@ -375,11 +376,15 @@ namespace crates::layout2 }; class Position : public CSSKeyword + holocron::layout::Position::Static> { using CSSKeyword::CSSKeyword; public: + static Position Static() + { + return Position(holocron::layout::Position::Static); + } static Position Relative() { return Position(holocron::layout::Position::Relative); @@ -392,9 +397,13 @@ namespace crates::layout2 public: Position(const std::string &input) { - handle_ = parse(input).value_or(holocron::layout::Position::Relative); + handle_ = parse(input).value_or(holocron::layout::Position::Static); } + inline bool isStatic() const + { + return handle_ == holocron::layout::Position::Static; + } inline bool isRelative() const { return handle_ == holocron::layout::Position::Relative; @@ -1035,7 +1044,7 @@ namespace crates::layout2 // scrollbar_width 2.0f, // position - styles::Position::Relative(), + styles::Position::Static(), // inset holocron::layout::LengthPercentageAutoRect{ .top = styles::LengthPercentageAuto::Auto(), From 4841d0cc252b2aa0137896ac45fe1a28b0c7fde4 Mon Sep 17 00:00:00 2001 From: yjh Date: Sun, 28 Sep 2025 14:39:56 +0800 Subject: [PATCH 5/9] Add static positioning styles for #static-div and enhance hover effect --- fixtures/html/simple.html | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fixtures/html/simple.html b/fixtures/html/simple.html index 6331e8c7e..e2467e024 100644 --- a/fixtures/html/simple.html +++ b/fixtures/html/simple.html @@ -130,6 +130,21 @@ background-color: rgb(134, 20, 98); color: #fff; } + + #static-div { + position: static; + top: 200px; + left: 20; + background-color: rgba(20, 134, 69, 0.352); + padding: 20px; + font-size: 30px; + text-align: center; + color: #fff; + font-weight: bold; + } + #static-div:hover { + background-color: var(--secondary-color); + }