Open MarcSkovMadsen opened 1 year ago
I appreciate the refactored ReactiveHTML documentation, but it seems like the issue of applying the Panel native styles to custom ReactiveHTML widgets has not yet been addressed. Is this under active discussion anywhere? I tried using the style-copying technique from the above example (_stylesheets = pn.widgets.Select._stylesheets
), but am running into the same issue where the styling is not being correctly applied even though I have no obvious overrides to it. (The browser's element inspector shows that the relevant Bokeh (.bk-
) class is referenced on the element, but not all of the relevant styling is picked up.)
@MarcSkovMadsen: I did some more digging on this. It seems that the Bokeh stylesheets are baked into the underlying Bokeh widgets on the HTML+CSS side and are not surfaced via the _stylesheets
or stylesheets
attributes on the Python side, since those attributes are for extra stylesheets. The Less sources for those stylesheets are available at:
Instead of compiling the Less templates to CSS, I just took a dump of the CSS stylesheets directly with a browser's DOM inspector and had an LLM pretty them for me. Feels hacky to use so much CSS code directly like this, but here they are anyway:
:host {
--base-font: var(--bokeh-base-font, Helvetica, Arial, sans-serif);
--mono-font: var(--bokeh-mono-font, monospace);
--font-size: var(--bokeh-font-size, 12px);
--line-height: calc(20 / 14);
--line-height-computed: calc(var(--font-size) * var(--line-height));
--border-radius: 4px;
--padding-vertical: 6px;
--padding-horizontal: 12px;
--bokeh-top-level: 1000;
}
:host {
box-sizing: border-box;
font-family: var(--base-font);
font-size: var(--font-size);
line-height: var(--line-height);
}
*, *:before, *:after {
box-sizing: inherit;
font-family: inherit;
}
pre, code {
font-family: var(--mono-font);
margin: 0;
}
:host {
--input-min-height: calc(var(--line-height-computed) + 2*var(--padding-vertical) + 2px);
}
.bk-input {
position: relative;
display: inline-block;
width: 100%;
flex-grow: 1;
min-height: var(--input-min-height);
padding: 0 var(--padding-horizontal);
background-color: #fff;
border: 1px solid #ccc;
border-radius: var(--border-radius);
}
.bk-input:focus {
border-color: #66afe9;
outline: 0;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
}
.bk-input::placeholder,
.bk-input:-ms-input-placeholder,
.bk-input::-moz-placeholder,
.bk-input::-webkit-input-placeholder {
color: #999;
opacity: 1;
}
.bk-input[disabled],
.bk-input.bk-disabled {
cursor: not-allowed;
background-color: #eee;
opacity: 1;
}
.bk-input-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.bk-input-container .bk-input-prefix,
.bk-input-container .bk-input-suffix {
display: flex;
align-items: center;
flex: 0 1 0;
border: 1px solid #ccc;
border-radius: var(--border-radius);
padding: 0 var(--padding-horizontal);
background-color: #e6e6e6;
}
.bk-input-container .bk-input-prefix {
border-right: none;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.bk-input-container .bk-input-suffix {
border-left: none;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.bk-input-container .bk-input {
flex: 1 0 0;
}
.bk-input-container .bk-input:not(:first-child) {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.bk-input-container .bk-input:not(:last-child) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
input[type=file].bk-input {
padding-left: 0;
}
input[type=file]::file-selector-button {
box-sizing: inherit;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
select:not([multiple]).bk-input,
select:not([size]).bk-input {
height: auto;
appearance: none;
-webkit-appearance: none;
background-image: url('data:image/svg+xml;utf8,<svg version="1.1" viewBox="0 0 25 20" xmlns="http://www.w3.org/2000/svg"><path d="M 0,0 25,0 12.5,20 Z" fill="black" /></svg>');
background-position: right 0.5em center;
background-size: 8px 6px;
background-repeat: no-repeat;
padding-right: calc(var(--padding-horizontal) + 8px);
}
option {
padding: 0;
}
select[multiple].bk-input,
select[size].bk-input,
textarea.bk-input {
height: auto;
}
.bk-input-group {
position: relative;
width: 100%;
height: 100%;
display: inline-flex;
flex-wrap: nowrap;
align-items: start;
flex-direction: column;
white-space: nowrap;
}
.bk-input-group.bk-inline {
flex-direction: row;
}
.bk-input-group.bk-inline > *:not(:first-child) {
margin-left: 5px;
}
.bk-input-group > .bk-spin-wrapper {
display: inherit;
width: inherit;
height: inherit;
position: relative;
overflow: hidden;
padding: 0;
vertical-align: middle;
}
.bk-input-group > .bk-spin-wrapper input {
padding-right: 20px;
}
.bk-input-group > .bk-spin-wrapper > .bk-spin-btn {
position: absolute;
display: block;
height: 50%;
min-height: 0;
min-width: 0;
width: 30px;
padding: 0;
margin: 0;
right: 0;
border: none;
background: none;
cursor: pointer;
}
.bk-input-group > .bk-spin-wrapper > .bk-spin-btn:before {
content: "";
display: inline-block;
transform: translateY(-50%);
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
.bk-input-group > .bk-spin-wrapper > .bk-spin-btn.bk-spin-btn-up {
top: 0;
}
.bk-input-group > .bk-spin-wrapper > .bk-spin-btn.bk-spin-btn-up:before {
border-bottom: 5px solid black;
}
.bk-input-group > .bk-spin-wrapper > .bk-spin-btn.bk-spin-btn-up:disabled:before {
border-bottom-color: grey;
}
.bk-input-group > .bk-spin-wrapper > .bk-spin-btn.bk-spin-btn-down {
bottom: 0;
}
.bk-input-group > .bk-spin-wrapper > .bk-spin-btn.bk-spin-btn-down:before {
border-top: 5px solid black;
}
.bk-input-group > .bk-spin-wrapper > .bk-spin-btn.bk-spin-btn-down:disabled:before {
border-top-color: grey;
}
.bk-description {
position: relative;
display: inline-block;
margin-left: 0.25em;
vertical-align: middle;
margin-top: -2px;
cursor: pointer;
}
.bk-description > .bk-icon {
opacity: 0.5;
width: 18px;
height: 18px;
background-color: gray;
mask-image: var(--bokeh-icon-help);
mask-size: contain;
mask-repeat: no-repeat;
-webkit-mask-image: var(--bokeh-icon-help);
-webkit-mask-size: contain;
-webkit-mask-repeat: no-repeat;
}
label:hover > .bk-description > .bk-icon,
.bk-icon.bk-opaque {
opacity: 1;
}
Maybe this will help someone until a better mechanism exists and can be properly documented.
Sometimes I need a custom version of an existing Panel widget. For example to
I would like the custom widget to have the same styling as the native one across designs and templates. I don't know how to do this easily today. Please document.
Example
Here I would like the two widgets to have the same style. But as you can see for example the
<select>
padding is different. As soon as you interact, you will also see that the border etc is different.