mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 20:15:17 +00:00
LibWeb/HTMLInputElement: Improve appearance of color picker
Instead of a plain ButtonBox, it now appears as a color well styled after the buttons.
This commit is contained in:
parent
63cd6b0d3c
commit
a1cce69db0
Notes:
sideshowbarker
2024-07-18 03:23:00 +09:00
Author: https://github.com/circl-lastname Commit: https://github.com/SerenityOS/serenity/commit/a1cce69db0 Pull-request: https://github.com/SerenityOS/serenity/pull/21438 Reviewed-by: https://github.com/AtkinsSJ ✅ Reviewed-by: https://github.com/trflynn89
3 changed files with 52 additions and 3 deletions
|
@ -26,7 +26,7 @@ label {
|
|||
}
|
||||
|
||||
/* FIXME: This is a temporary hack until we can render a native-looking frame for these. */
|
||||
input:not([type=submit], input[type=button], input[type=reset], input[type=checkbox], input[type=radio]), textarea {
|
||||
input:not([type=submit], input[type=button], input[type=reset], input[type=color], input[type=checkbox], input[type=radio]), textarea {
|
||||
border: 1px solid ButtonBorder;
|
||||
min-width: 80px;
|
||||
min-height: 16px;
|
||||
|
|
|
@ -61,6 +61,7 @@ void HTMLInputElement::visit_edges(Cell::Visitor& visitor)
|
|||
visitor.visit(m_text_node);
|
||||
visitor.visit(m_placeholder_element);
|
||||
visitor.visit(m_placeholder_text_node);
|
||||
visitor.visit(m_color_well_element);
|
||||
visitor.visit(m_legacy_pre_activation_behavior_checked_element_in_group.ptr());
|
||||
visitor.visit(m_selected_files);
|
||||
}
|
||||
|
@ -70,7 +71,7 @@ JS::GCPtr<Layout::Node> HTMLInputElement::create_layout_node(NonnullRefPtr<CSS::
|
|||
if (type_state() == TypeAttributeState::Hidden)
|
||||
return nullptr;
|
||||
|
||||
if (type_state() == TypeAttributeState::SubmitButton || type_state() == TypeAttributeState::Button || type_state() == TypeAttributeState::ResetButton || type_state() == TypeAttributeState::FileUpload || type_state() == TypeAttributeState::Color)
|
||||
if (type_state() == TypeAttributeState::SubmitButton || type_state() == TypeAttributeState::Button || type_state() == TypeAttributeState::ResetButton || type_state() == TypeAttributeState::FileUpload)
|
||||
return heap().allocate_without_realm<Layout::ButtonBox>(document(), *this, move(style));
|
||||
|
||||
if (type_state() == TypeAttributeState::Checkbox)
|
||||
|
@ -317,6 +318,9 @@ void HTMLInputElement::did_pick_color(Optional<Color> picked_color)
|
|||
m_value = value_sanitization_algorithm(picked_color.value().to_deprecated_string_without_alpha());
|
||||
m_dirty_value = true;
|
||||
|
||||
if (m_color_well_element)
|
||||
MUST(m_color_well_element->style_for_bindings()->set_property(CSS::PropertyID::BackgroundColor, m_value));
|
||||
|
||||
// the user agent must queue an element task on the user interaction task source
|
||||
queue_an_element_task(HTML::Task::Source::UserInteraction, [this] {
|
||||
// given the input element to fire an event named input at the input element, with the bubbles and composed attributes initialized to true
|
||||
|
@ -387,7 +391,9 @@ WebIDL::ExceptionOr<void> HTMLInputElement::set_value(String const& value)
|
|||
auto old_value = move(m_value);
|
||||
|
||||
// 2. Set the element's value to the new value.
|
||||
// NOTE: This is done as part of step 4 below.
|
||||
// NOTE: For the TextNode this is done as part of step 4 below.
|
||||
if (type_state() == TypeAttributeState::Color && m_color_well_element)
|
||||
MUST(m_color_well_element->style_for_bindings()->set_property(CSS::PropertyID::BackgroundColor, m_value));
|
||||
|
||||
// 3. Set the element's dirty value flag to true.
|
||||
m_dirty_value = true;
|
||||
|
@ -514,7 +520,9 @@ void HTMLInputElement::create_shadow_tree_if_needed()
|
|||
case TypeAttributeState::SubmitButton:
|
||||
case TypeAttributeState::ResetButton:
|
||||
case TypeAttributeState::ImageButton:
|
||||
break;
|
||||
case TypeAttributeState::Color:
|
||||
create_color_input_shadow_tree();
|
||||
break;
|
||||
// FIXME: This could be better factored. Everything except the above types becomes a text input.
|
||||
default:
|
||||
|
@ -572,6 +580,35 @@ void HTMLInputElement::create_text_input_shadow_tree()
|
|||
set_shadow_root(shadow_root);
|
||||
}
|
||||
|
||||
void HTMLInputElement::create_color_input_shadow_tree()
|
||||
{
|
||||
auto shadow_root = heap().allocate<DOM::ShadowRoot>(realm(), document(), *this, Bindings::ShadowRootMode::Closed);
|
||||
|
||||
auto color = value_sanitization_algorithm(m_value);
|
||||
|
||||
auto border = DOM::create_element(document(), HTML::TagNames::div, Namespace::HTML).release_value_but_fixme_should_propagate_errors();
|
||||
MUST(border->set_attribute(HTML::AttributeNames::style, R"~~~(
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
padding: 4px;
|
||||
border: 1px solid ButtonBorder;
|
||||
background-color: ButtonFace;
|
||||
)~~~"_string));
|
||||
|
||||
m_color_well_element = DOM::create_element(document(), HTML::TagNames::div, Namespace::HTML).release_value_but_fixme_should_propagate_errors();
|
||||
MUST(m_color_well_element->set_attribute(HTML::AttributeNames::style, R"~~~(
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 1px solid ButtonBorder;
|
||||
box-sizing: border-box;
|
||||
)~~~"_string));
|
||||
MUST(m_color_well_element->style_for_bindings()->set_property(CSS::PropertyID::BackgroundColor, color));
|
||||
|
||||
MUST(border->append_child(*m_color_well_element));
|
||||
MUST(shadow_root->append_child(border));
|
||||
set_shadow_root(shadow_root);
|
||||
}
|
||||
|
||||
void HTMLInputElement::did_receive_focus()
|
||||
{
|
||||
auto* browsing_context = document().browsing_context();
|
||||
|
@ -615,11 +652,17 @@ void HTMLInputElement::attribute_changed(FlyString const& name, Optional<Depreca
|
|||
if (!m_dirty_value) {
|
||||
m_value = DeprecatedString::empty();
|
||||
update_placeholder_visibility();
|
||||
|
||||
if (type_state() == TypeAttributeState::Color && m_color_well_element)
|
||||
MUST(m_color_well_element->style_for_bindings()->set_property(CSS::PropertyID::BackgroundColor, m_value));
|
||||
}
|
||||
} else {
|
||||
if (!m_dirty_value) {
|
||||
m_value = value_sanitization_algorithm(*value);
|
||||
update_placeholder_visibility();
|
||||
|
||||
if (type_state() == TypeAttributeState::Color && m_color_well_element)
|
||||
MUST(m_color_well_element->style_for_bindings()->set_property(CSS::PropertyID::BackgroundColor, m_value));
|
||||
}
|
||||
}
|
||||
} else if (name == HTML::AttributeNames::placeholder) {
|
||||
|
@ -954,10 +997,14 @@ void HTMLInputElement::reset_algorithm()
|
|||
|
||||
// and then invoke the value sanitization algorithm, if the type attribute's current state defines one.
|
||||
m_value = value_sanitization_algorithm(m_value);
|
||||
|
||||
if (m_text_node) {
|
||||
m_text_node->set_data(MUST(String::from_deprecated_string(m_value)));
|
||||
update_placeholder_visibility();
|
||||
}
|
||||
|
||||
if (type_state() == TypeAttributeState::Color && m_color_well_element)
|
||||
MUST(m_color_well_element->style_for_bindings()->set_property(CSS::PropertyID::BackgroundColor, m_value));
|
||||
}
|
||||
|
||||
void HTMLInputElement::form_associated_element_was_inserted()
|
||||
|
|
|
@ -167,6 +167,7 @@ private:
|
|||
static TypeAttributeState parse_type_attribute(StringView);
|
||||
void create_shadow_tree_if_needed();
|
||||
void create_text_input_shadow_tree();
|
||||
void create_color_input_shadow_tree();
|
||||
WebIDL::ExceptionOr<void> run_input_activation_behavior();
|
||||
void set_checked_within_group();
|
||||
|
||||
|
@ -180,6 +181,7 @@ private:
|
|||
JS::GCPtr<DOM::Text> m_placeholder_text_node;
|
||||
|
||||
JS::GCPtr<DOM::Element> m_inner_text_element;
|
||||
JS::GCPtr<DOM::Element> m_color_well_element;
|
||||
JS::GCPtr<DOM::Text> m_text_node;
|
||||
bool m_checked { false };
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue