Bug 1635675 - Implement the ::file-chooser-button pseudo-element. r=jwatt

As per https://github.com/w3c/csswg-drafts/issues/5049.

Don't enable it unconditionally just yet, as the name may change.

I had to move some rules in forms.css because otherwise you get
specificity conflicts.

Differential Revision: https://phabricator.services.mozilla.com/D76214
This commit is contained in:
Emilio Cobos Álvarez 2020-05-21 12:27:54 +00:00
Родитель 8017e73680
Коммит a39a3a3807
12 изменённых файлов: 98 добавлений и 51 удалений

Просмотреть файл

@ -748,6 +748,8 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
return true; return true;
case ":cue": case ":cue":
return node.nodeName == "VIDEO"; return node.nodeName == "VIDEO";
case ":file-chooser-button":
return node.nodeName == "INPUT" && node.type == "file";
case ":placeholder": case ":placeholder":
case ":-moz-placeholder": case ":-moz-placeholder":
return this._nodeIsTextfieldLike(node); return this._nodeIsTextfieldLike(node);

Просмотреть файл

@ -10692,7 +10692,8 @@ exports.PSEUDO_ELEMENTS = [
":-moz-range-thumb", ":-moz-range-thumb",
":-moz-meter-bar", ":-moz-meter-bar",
":placeholder", ":placeholder",
":-moz-color-swatch" ":-moz-color-swatch",
":file-chooser-button"
]; ];
/** /**

Просмотреть файл

@ -212,6 +212,7 @@ static already_AddRefed<Element> MakeAnonButton(Document* aDoc,
// NOTE: SetIsNativeAnonymousRoot() has to be called before setting any // NOTE: SetIsNativeAnonymousRoot() has to be called before setting any
// attribute. // attribute.
button->SetIsNativeAnonymousRoot(); button->SetIsNativeAnonymousRoot();
button->SetPseudoElementType(PseudoStyleType::fileChooserButton);
// Set the file picking button text depending on the current locale. // Set the file picking button text depending on the current locale.
nsAutoString buttonTxt; nsAutoString buttonTxt;

Просмотреть файл

@ -15,6 +15,7 @@
":marker", ":marker",
":backdrop", ":backdrop",
":cue", ":cue",
":file-chooser-button",
":first-letter", ":first-letter",
":first-line", ":first-line",
":placeholder", ":placeholder",

Просмотреть файл

@ -97,3 +97,7 @@ CSS_PSEUDO_ELEMENT(mozTextControlEditingRoot, ":-moz-text-control-editing-root",
// The element that shows the autofill value. // The element that shows the autofill value.
CSS_PSEUDO_ELEMENT(mozTextControlPreview, ":-moz-text-control-preview", CSS_PSEUDO_ELEMENT(mozTextControlPreview, ":-moz-text-control-preview",
CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS) CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS)
CSS_PSEUDO_ELEMENT(fileChooserButton, ":file-chooser-button",
CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS |
CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE)

Просмотреть файл

@ -118,12 +118,20 @@ class nsCSSPseudoElements {
CSS_PSEUDO_ELEMENT_IS_FLEX_OR_GRID_ITEM); CSS_PSEUDO_ELEMENT_IS_FLEX_OR_GRID_ITEM);
} }
static bool IsEnabled(Type aType, EnabledState aEnabledState) { static bool EnabledInContent(Type aType) {
if (!PseudoElementHasAnyFlag( switch (aType) {
aType, CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME)) { case Type::mozFocusOuter:
if (aType == Type::mozFocusOuter) {
return mozilla::StaticPrefs::layout_css_moz_focus_outer_enabled(); return mozilla::StaticPrefs::layout_css_moz_focus_outer_enabled();
} case Type::fileChooserButton:
return mozilla::StaticPrefs::layout_css_file_chooser_button_enabled();
default:
return !PseudoElementHasAnyFlag(
aType, CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME);
}
}
static bool IsEnabled(Type aType, EnabledState aEnabledState) {
if (EnabledInContent(aType)) {
return true; return true;
} }

Просмотреть файл

@ -124,7 +124,7 @@ textarea {
} }
/* A few properties that we don't want to inherit by default: */ /* A few properties that we don't want to inherit by default: */
input, textarea, select, button { input, textarea, select, button, ::file-chooser-button {
text-align: initial; text-align: initial;
text-indent: initial; text-indent: initial;
text-shadow: initial; text-shadow: initial;
@ -461,44 +461,6 @@ input[type="image"]:disabled {
cursor: unset; cursor: unset;
} }
/* file selector */
input[type="file"] {
white-space: nowrap !important;
overflow: hidden !important;
overflow-clip-box: padding-box;
color: unset;
/* Revert rules which apply on all inputs. */
-moz-appearance: none;
cursor: default;
border: none;
background-color: transparent;
padding: unset;
}
input[type="file"] > label {
display: inline-block;
min-inline-size: 12em;
padding-inline-start: 5px;
text-align: match-parent;
color: unset;
font-size: unset;
letter-spacing: unset;
user-select: none;
unicode-bidi: plaintext;
}
/* button part of file selector */
input[type="file"] > button {
font-size: unset;
letter-spacing: unset;
cursor: unset;
}
/* colored part of the color selector button */ /* colored part of the color selector button */
::-moz-color-swatch { ::-moz-color-swatch {
width: 100%; width: 100%;
@ -564,6 +526,7 @@ input[type="search"] {
/* Non text-related properties for buttons: these ones are shared with /* Non text-related properties for buttons: these ones are shared with
input[type="color"] */ input[type="color"] */
button, button,
::file-chooser-button,
input:is([type="color"], [type="reset"], [type="button"], [type="submit"]) { input:is([type="color"], [type="reset"], [type="button"], [type="submit"]) {
-moz-appearance: button; -moz-appearance: button;
/* The sum of border and padding on block-start and block-end /* The sum of border and padding on block-start and block-end
@ -581,6 +544,7 @@ input:is([type="color"], [type="reset"], [type="button"], [type="submit"]) {
/* Text-related properties for buttons: these ones are not shared with /* Text-related properties for buttons: these ones are not shared with
input[type="color"] */ input[type="color"] */
button, button,
::file-chooser-button,
input:is([type="reset"], [type="button"], [type="submit"]) { input:is([type="reset"], [type="button"], [type="submit"]) {
color: ButtonText; color: ButtonText;
font: -moz-button; font: -moz-button;
@ -594,7 +558,8 @@ input[type="color"] {
block-size: 23px; block-size: 23px;
} }
button { button,
::file-chooser-button {
/* Buttons should lay out like "normal" html, mostly */ /* Buttons should lay out like "normal" html, mostly */
white-space: unset; white-space: unset;
text-indent: 0; text-indent: 0;
@ -636,16 +601,19 @@ button {
justify-items: inherit; justify-items: inherit;
} }
::file-chooser-button:hover,
button:hover, button:hover,
input:is([type="reset"], [type="button"], [type="submit"], [type="color"]):hover { input:is([type="reset"], [type="button"], [type="submit"], [type="color"]):hover {
background-color: -moz-buttonhoverface; background-color: -moz-buttonhoverface;
} }
::file-chooser-button:hover,
button:hover, button:hover,
input:is([type="reset"], [type="button"], [type="submit"]):hover { input:is([type="reset"], [type="button"], [type="submit"]):hover {
color: -moz-buttonhovertext; color: -moz-buttonhovertext;
} }
::file-chooser-button:active:hover,
button:active:hover, button:active:hover,
input:is([type="reset"], [type="button"], [type="submit"], [type="color"]):active:hover { input:is([type="reset"], [type="button"], [type="submit"], [type="color"]):active:hover {
%ifndef XP_MACOSX %ifndef XP_MACOSX
@ -656,6 +624,7 @@ input:is([type="reset"], [type="button"], [type="submit"], [type="color"]):activ
background-color: ButtonFace; background-color: ButtonFace;
} }
::file-chooser-button:active:hover,
button:active:hover, button:active:hover,
input:is([type="reset"], [type="button"], [type="submit"]):active:hover { input:is([type="reset"], [type="button"], [type="submit"]):active:hover {
%ifdef MOZ_WIDGET_GTK %ifdef MOZ_WIDGET_GTK
@ -676,6 +645,7 @@ input:is([type="reset"], [type="button"], [type="submit"]):active:hover {
border-color: currentColor; border-color: currentColor;
} }
:is(:disabled, :disabled:active)::file-chooser-button,
button:is(:disabled, :disabled:active), button:is(:disabled, :disabled:active),
input:is([type="reset"], [type="button"], [type="submit"], [type="color"]):is(:disabled, :disabled:active), input:is([type="reset"], [type="button"], [type="submit"], [type="color"]):is(:disabled, :disabled:active),
select:is(:disabled, :disabled:active) > button { select:is(:disabled, :disabled:active) > button {
@ -687,12 +657,50 @@ select:is(:disabled, :disabled:active) > button {
cursor: unset; cursor: unset;
} }
:is(:disabled, :disabled:active)::file-chooser-button,
button:is(:disabled, :disabled:active), button:is(:disabled, :disabled:active),
input:is([type="reset"], [type="button"], [type="submit"]):is(:disabled, :disabled:active), input:is([type="reset"], [type="button"], [type="submit"]):is(:disabled, :disabled:active),
select:is(:disabled, :disabled:active) > button { select:is(:disabled, :disabled:active) > button {
color: GrayText; color: GrayText;
} }
/* file selector */
input[type="file"] {
white-space: nowrap !important;
overflow: hidden !important;
overflow-clip-box: padding-box;
color: unset;
/* Revert rules which apply on all inputs. */
-moz-appearance: none;
cursor: default;
border: none;
background-color: transparent;
padding: unset;
}
input[type="file"] > label {
display: inline-block;
min-inline-size: 12em;
padding-inline-start: 5px;
text-align: match-parent;
color: unset;
font-size: unset;
letter-spacing: unset;
user-select: none;
unicode-bidi: plaintext;
}
/* button part of file selector */
::file-chooser-button {
font-size: unset;
letter-spacing: unset;
cursor: unset;
}
/* /*
* Make form controls inherit 'unicode-bidi' transparently as required by * Make form controls inherit 'unicode-bidi' transparently as required by
* their various anonymous descendants and pseudo-elements: * their various anonymous descendants and pseudo-elements:

Просмотреть файл

@ -6218,6 +6218,13 @@
mirror: always mirror: always
rust: true rust: true
# Is support for the ::file-chooser-button pseudo-element enabled?
- name: layout.css.file-chooser-button.enabled
type: RelaxedAtomicBool
value: @IS_NIGHTLY_OR_DEV_EDITION@
mirror: always
rust: true
# Whether the computed value of line-height: normal returns the `normal` # Whether the computed value of line-height: normal returns the `normal`
# keyword rather than a pixel value based on the first available font. # keyword rather than a pixel value based on the first available font.
# #

Просмотреть файл

@ -37,7 +37,8 @@ impl ::selectors::parser::PseudoElement for PseudoElement {
PseudoElement::Before | PseudoElement::Before |
PseudoElement::After | PseudoElement::After |
PseudoElement::Marker | PseudoElement::Marker |
PseudoElement::Placeholder PseudoElement::Placeholder |
PseudoElement::FileChooserButton
) )
} }
@ -159,12 +160,12 @@ impl PseudoElement {
/// Whether this pseudo-element is enabled for all content. /// Whether this pseudo-element is enabled for all content.
pub fn enabled_in_content(&self) -> bool { pub fn enabled_in_content(&self) -> bool {
if (self.flags() & structs::CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME) != 0 {
return false;
}
match *self { match *self {
PseudoElement::MozFocusOuter => static_prefs::pref!("layout.css.moz-focus-outer.enabled"), PseudoElement::MozFocusOuter => static_prefs::pref!("layout.css.moz-focus-outer.enabled"),
_ => true, PseudoElement::FileChooserButton => static_prefs::pref!("layout.css.file-chooser-button.enabled"),
_ => {
(self.flags() & structs::CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME) == 0
}
} }
} }

Просмотреть файл

@ -0,0 +1,3 @@
<!doctype html>
<title>CSS Test Reference</title>
<input type="file">

Просмотреть файл

@ -0,0 +1,10 @@
<!doctype html>
<title>::file-chooser-button allows to customize the button in &lt;input type=file&gt;</title>
<link rel="mismatch" href="file-chooser-button-001-notref.html">
<style>
input::file-chooser-button {
background: green;
color: white;
}
</style>
<input type="file">

Просмотреть файл

@ -2489,6 +2489,7 @@ STATIC_ATOMS = [
PseudoElementAtom("PseudoElement_mozColorSwatch", ":-moz-color-swatch"), PseudoElementAtom("PseudoElement_mozColorSwatch", ":-moz-color-swatch"),
PseudoElementAtom("PseudoElement_mozTextControlEditingRoot", ":-moz-text-control-editing-root"), PseudoElementAtom("PseudoElement_mozTextControlEditingRoot", ":-moz-text-control-editing-root"),
PseudoElementAtom("PseudoElement_mozTextControlPreview", ":-moz-text-control-preview"), PseudoElementAtom("PseudoElement_mozTextControlPreview", ":-moz-text-control-preview"),
PseudoElementAtom("PseudoElement_fileChooserButton", ":file-chooser-button"),
# CSS anonymous boxes -- these must appear in the same order as # CSS anonymous boxes -- these must appear in the same order as
# in nsCSSAnonBoxList.h # in nsCSSAnonBoxList.h