mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2026-04-18 18:00:31 +00:00
Instead of manually writing code to instantiate DOM elements in MediaControls.cpp, use a Python script to generate a separate C++ struct to create and store the DOM elements. The generator reads an HTML file and the HTML/SVG tags/attributes headers to create C++ source that instantiates the DOM elements. To enable embedding of stylesheets in shadow DOM, the generator replaces `<link rel="stylesheet">` elements with plain `<style>` elements containing the source from the linked stylesheet. Elements that should be stored in the resulting struct should be marked have the `data-name` attribute, which will be converted to snake_case and used as the public field's name. Optional elements can be marked with a 'data-option' attribute. Each unique option value will be converted to PascalCase and added to a bitwise enum named `Options` nested within the struct. Optional elements and all their children will not be instantiated unless their option is set in the constructor argument. The MediaControls class stores the generated MediaControlsDOM struct and sets up event handlers to implement user interactions.
207 lines
3.6 KiB
CSS
207 lines
3.6 KiB
CSS
.container {
|
|
--accent-color: #9d7cf2;
|
|
--dark-accent-color: #8a64e5;
|
|
--light-accent-color: #e0d4ff;
|
|
--foreground-color: white;
|
|
--track-color: rgb(20, 20, 20);
|
|
--panel-color: rgb(38, 38, 38);
|
|
|
|
overflow: hidden;
|
|
}
|
|
|
|
.container.video {
|
|
position: relative;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.controls {
|
|
display: flex;
|
|
flex-direction: column;
|
|
font-family: sans-serif;
|
|
font-size: 12px;
|
|
color: var(--foreground-color);
|
|
user-select: none;
|
|
}
|
|
|
|
.container.video > .controls {
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
background: color-mix(in srgb, var(--panel-color) 82%, transparent);
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
transition: opacity 150ms ease-in-out;
|
|
}
|
|
|
|
.container.video > .controls.visible {
|
|
opacity: 1;
|
|
pointer-events: auto;
|
|
}
|
|
|
|
.container.audio > .controls {
|
|
inset: 0;
|
|
background: var(--panel-color);
|
|
justify-content: center;
|
|
}
|
|
|
|
.timeline {
|
|
z-index: 1;
|
|
height: 5px;
|
|
padding: 5px 0;
|
|
margin: -5px 0;
|
|
background: var(--track-color);
|
|
background-clip: content-box;
|
|
cursor: pointer;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.timeline-fill {
|
|
height: 100%;
|
|
background: var(--accent-color);
|
|
width: 0%;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.button-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 4px 8px;
|
|
gap: 8px;
|
|
min-height: 30px;
|
|
}
|
|
|
|
.control-button {
|
|
background: none;
|
|
border: none;
|
|
cursor: pointer;
|
|
padding: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 24px;
|
|
height: 24px;
|
|
}
|
|
|
|
.icon {
|
|
width: 24px;
|
|
height: 24px;
|
|
}
|
|
|
|
.control-button .icon path {
|
|
fill: var(--foreground-color);
|
|
}
|
|
|
|
.control-button:hover .icon path {
|
|
fill: var(--light-accent-color);
|
|
}
|
|
|
|
.play-pause-icon path {
|
|
display: none;
|
|
}
|
|
.play-pause-icon:not(.playing) .play-path {
|
|
display: inline;
|
|
}
|
|
.play-pause-icon.playing .pause-path {
|
|
display: inline;
|
|
}
|
|
|
|
.mute-button {
|
|
margin-left: auto;
|
|
}
|
|
|
|
.mute-button:not(.low, .high) > .icon > .volume-low {
|
|
display: none;
|
|
}
|
|
.mute-button:not(.high) > .icon > .volume-high {
|
|
display: none;
|
|
}
|
|
|
|
.mute-button.muted > .icon > .volume-low,
|
|
.mute-button.muted > .icon > .volume-high,
|
|
.mute-button.muted > .icon > .speaker {
|
|
clip-path: url(#muted-clip);
|
|
}
|
|
.mute-button:not(.muted) > .icon > .muted-line {
|
|
display: none;
|
|
}
|
|
|
|
.timestamp {
|
|
min-width: 0;
|
|
overflow: clip;
|
|
white-space: nowrap;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
.volume-area {
|
|
max-width: 60px;
|
|
flex-grow: 1;
|
|
padding: 5px;
|
|
margin: -5px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.volume-area.hidden {
|
|
display: none;
|
|
}
|
|
|
|
.volume {
|
|
height: 6px;
|
|
background: var(--track-color);
|
|
border-radius: 3px;
|
|
overflow: hidden;
|
|
position: relative;
|
|
}
|
|
|
|
.volume-fill {
|
|
height: 100%;
|
|
width: 100%;
|
|
background: var(--accent-color);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.video-overlay {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.fullscreen-icon path {
|
|
display: none;
|
|
}
|
|
.fullscreen-icon:not(.fullscreen) .fullscreen-maximize-path {
|
|
display: inline;
|
|
}
|
|
.fullscreen-icon.fullscreen .fullscreen-minimize-path {
|
|
display: inline;
|
|
}
|
|
|
|
.placeholder-circle {
|
|
width: 80px;
|
|
height: 80px;
|
|
border-radius: 50%;
|
|
background: var(--panel-color);
|
|
opacity: 80%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.placeholder-circle:hover {
|
|
background: var(--panel-color);
|
|
opacity: 100%;
|
|
}
|
|
|
|
.placeholder-circle path {
|
|
fill: var(--light-accent-color);
|
|
}
|
|
|
|
.placeholder-icon {
|
|
width: 36px;
|
|
height: 36px;
|
|
margin-left: 4px;
|
|
}
|