diff --git a/.changeset/mockup-browser.md b/.changeset/mockup-browser.md
new file mode 100644
index 000000000..d94f4a322
--- /dev/null
+++ b/.changeset/mockup-browser.md
@@ -0,0 +1,7 @@
+---
+'@tabler/core': minor
+'@tabler/preview': minor
+'@tabler/docs': minor
+---
+
+Added the mockup browser component: `.mockup-browser` wraps a screenshot or any content in a frame that looks like a browser window, with window dots and an address bar.
diff --git a/core/scss/_core.scss b/core/scss/_core.scss
index 2c69bf584..6218ad90e 100644
--- a/core/scss/_core.scss
+++ b/core/scss/_core.scss
@@ -76,6 +76,7 @@
@forward 'ui/lists';
@forward 'ui/loaders';
@forward 'ui/login';
+@forward 'ui/mockup-browser';
@forward 'ui/modals';
@forward 'ui/nav';
@forward 'ui/nav-overflow';
diff --git a/core/scss/_variables-dark.scss b/core/scss/_variables-dark.scss
index 6b478bf5d..df7d719bc 100644
--- a/core/scss/_variables-dark.scss
+++ b/core/scss/_variables-dark.scss
@@ -9,6 +9,7 @@ $darken-dark: adjust-lightness-css(var(--dark), -2%) !default;
$border-color-dark: adjust-lightness-css(var(--dark), 8%) !default;
$border-color-translucent-dark: rgba(128, 150, 172, 0.2) !default;
$border-dark-color-dark: adjust-lightness-css(var(--dark), 4%) !default;
+$border-light-color-dark: adjust-lightness-css(var(--dark), 6%) !default;
$border-active-color-dark: adjust-lightness-css(var(--dark), 12%) !default;
//new bootsrap variables
diff --git a/core/scss/_variables.scss b/core/scss/_variables.scss
index ba31bb158..1ab7ebada 100644
--- a/core/scss/_variables.scss
+++ b/core/scss/_variables.scss
@@ -1794,6 +1794,34 @@ $text-shimmer-loader-duration: 0.75s !default;
$text-shimmer-loader-opacity: 0.25 !default;
// scss-docs-end text-shimmer-variables
+// Mockup browser
+// scss-docs-start mockup-browser-variables
+$mockup-browser-bg: var(--bg-surface) !default;
+$mockup-browser-border-color: var(--border-light-color) !default;
+$mockup-browser-border-radius: var(--border-radius-lg) !default;
+$mockup-browser-box-shadow: var(--shadow-lg) !default;
+$mockup-browser-toolbar-min-height: 2rem !default;
+$mockup-browser-toolbar-padding-y: 0.5rem !default;
+$mockup-browser-toolbar-padding-x: 12.5% !default;
+$mockup-browser-toolbar-color: var(--secondary) !default;
+$mockup-browser-toolbar-bg: var(--bg-surface-secondary) !default;
+$mockup-browser-control-offset: 1rem !default;
+$mockup-browser-control-size: 0.75rem !default;
+$mockup-browser-control-gap: 0.5rem !default;
+$mockup-browser-control-colors: #ff5f57, #febc2e, #28c840 !default;
+$mockup-browser-url-font-size: $h5-font-size !default;
+$mockup-browser-url-line-height: 1rem !default;
+$mockup-browser-url-icon-size: 0.875rem !default;
+
+$mockup-browser-sm-border-radius: var(--border-radius) !default;
+$mockup-browser-sm-toolbar-min-height: 1.5rem !default;
+$mockup-browser-sm-toolbar-padding-y: 0.25rem !default;
+$mockup-browser-sm-control-size: 0.5rem !default;
+$mockup-browser-sm-control-gap: 0.25rem !default;
+$mockup-browser-sm-url-font-size: $h6-font-size !default;
+$mockup-browser-sm-url-icon-size: 0.75rem !default;
+// scss-docs-end mockup-browser-variables
+
// Steps
// scss-docs-start steps-variables
$steps-border-width: 2px !default;
diff --git a/core/scss/layout/_root.scss b/core/scss/layout/_root.scss
index 139a6c335..eea0b9ccc 100644
--- a/core/scss/layout/_root.scss
+++ b/core/scss/layout/_root.scss
@@ -43,7 +43,7 @@
--border-color-translucent: light-dark(#{$border-color-translucent}, var(--dark-mode-border-color-translucent));
--border-dark-color: light-dark(#{$border-dark-color}, var(--dark-mode-border-dark-color));
--border-dark-color-translucent: #{$border-dark-color-translucent};
- --border-light-color: #{$border-light-color};
+ --border-light-color: light-dark(#{$border-light-color}, var(--dark-mode-border-light-color));
--border-light-color-translucent: #{$border-light-color-translucent};
--border-active-color: light-dark(#{$border-active-color}, var(--dark-mode-border-active-color));
--border-active-color-translucent: #{$border-active-color-translucent};
@@ -65,6 +65,7 @@
--dark-mode-border-color-translucent: #{$border-color-translucent-dark};
--dark-mode-border-active-color: #{$border-active-color-dark};
--dark-mode-border-dark-color: #{$border-dark-color-dark};
+ --dark-mode-border-light-color: #{$border-light-color-dark};
--page-padding: #{$page-padding};
--page-padding-y: #{$page-padding-y};
diff --git a/core/scss/ui/_mockup-browser.scss b/core/scss/ui/_mockup-browser.scss
new file mode 100644
index 000000000..c89cee697
--- /dev/null
+++ b/core/scss/ui/_mockup-browser.scss
@@ -0,0 +1,111 @@
+@use 'sass:list';
+@use '../config' as *;
+
+// A frame that looks like a browser window, to show a page preview or a screenshot
+.mockup-browser {
+ // scss-docs-start mockup-browser-css-vars
+ --mockup-browser-bg: #{$mockup-browser-bg};
+ --mockup-browser-border-color: #{$mockup-browser-border-color};
+ --mockup-browser-border-radius: #{$mockup-browser-border-radius};
+ --mockup-browser-box-shadow: #{$mockup-browser-box-shadow};
+ --mockup-browser-toolbar-min-height: #{$mockup-browser-toolbar-min-height};
+ --mockup-browser-toolbar-padding-y: #{$mockup-browser-toolbar-padding-y};
+ --mockup-browser-toolbar-padding-x: #{$mockup-browser-toolbar-padding-x};
+ --mockup-browser-toolbar-color: #{$mockup-browser-toolbar-color};
+ --mockup-browser-toolbar-bg: #{$mockup-browser-toolbar-bg};
+ --mockup-browser-control-offset: #{$mockup-browser-control-offset};
+ --mockup-browser-control-size: #{$mockup-browser-control-size};
+ --mockup-browser-control-gap: #{$mockup-browser-control-gap};
+ --mockup-browser-control-color-1: #{list.nth($mockup-browser-control-colors, 1)};
+ --mockup-browser-control-color-2: #{list.nth($mockup-browser-control-colors, 2)};
+ --mockup-browser-control-color-3: #{list.nth($mockup-browser-control-colors, 3)};
+ --mockup-browser-url-font-size: #{$mockup-browser-url-font-size};
+ --mockup-browser-url-line-height: #{$mockup-browser-url-line-height};
+ --mockup-browser-url-icon-size: #{$mockup-browser-url-icon-size};
+ // scss-docs-end mockup-browser-css-vars
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ background: var(--mockup-browser-bg);
+ border: var(--border-width) solid var(--mockup-browser-border-color);
+ box-shadow: var(--mockup-browser-box-shadow);
+ @include border-radius(var(--mockup-browser-border-radius));
+}
+
+// Small: a 24px toolbar for thumbnails and cards
+.mockup-browser-sm {
+ --mockup-browser-border-radius: #{$mockup-browser-sm-border-radius};
+ --mockup-browser-toolbar-min-height: #{$mockup-browser-sm-toolbar-min-height};
+ --mockup-browser-toolbar-padding-y: #{$mockup-browser-sm-toolbar-padding-y};
+ --mockup-browser-control-size: #{$mockup-browser-sm-control-size};
+ --mockup-browser-control-gap: #{$mockup-browser-sm-control-gap};
+ --mockup-browser-url-font-size: #{$mockup-browser-sm-url-font-size};
+ --mockup-browser-url-icon-size: #{$mockup-browser-sm-url-icon-size};
+}
+
+// The top bar: the window dots sit at the start, the address bar fills the middle
+.mockup-browser-toolbar {
+ position: relative;
+ display: flex;
+ align-items: center;
+ min-height: var(--mockup-browser-toolbar-min-height);
+ padding: var(--mockup-browser-toolbar-padding-y) var(--mockup-browser-toolbar-padding-x);
+ color: var(--mockup-browser-toolbar-color);
+ background: var(--mockup-browser-toolbar-bg);
+ // Drawn as an inset shadow so the line does not add to the toolbar height
+ box-shadow: inset 0 calc(-1 * var(--border-width)) var(--mockup-browser-border-color);
+}
+
+// The three window dots, drawn with one element and two shadows. They are taken
+// out of the flow so the address bar stays centered whatever the frame width
+.mockup-browser-controls {
+ position: absolute;
+ inset-inline-start: var(--mockup-browser-control-offset);
+ width: var(--mockup-browser-control-size);
+ height: var(--mockup-browser-control-size);
+ background: var(--mockup-browser-control-color-1);
+ border-radius: 50%;
+ box-shadow:
+ calc(var(--mockup-browser-control-size) + var(--mockup-browser-control-gap)) 0 0 var(--mockup-browser-control-color-2),
+ calc(2 * (var(--mockup-browser-control-size) + var(--mockup-browser-control-gap))) 0 0 var(--mockup-browser-control-color-3);
+}
+
+// The address, plain centered text
+.mockup-browser-url {
+ display: flex;
+ gap: 0.25rem;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ min-width: 0;
+ font-size: var(--mockup-browser-url-font-size);
+ line-height: var(--mockup-browser-url-line-height);
+
+ > span {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .icon {
+ --icon-size: var(--mockup-browser-url-icon-size);
+ flex-shrink: 0;
+ }
+}
+
+// The page: a screenshot fills the width, other content keeps its own layout
+.mockup-browser-body {
+ flex: 1;
+ min-height: 0;
+
+ > img,
+ > iframe,
+ > video {
+ display: block;
+ width: 100%;
+ }
+
+ > iframe {
+ border: 0;
+ }
+}
diff --git a/docs/content/ui/components/mockup-browser.mdx b/docs/content/ui/components/mockup-browser.mdx
new file mode 100644
index 000000000..71c9483d1
--- /dev/null
+++ b/docs/content/ui/components/mockup-browser.mdx
@@ -0,0 +1,152 @@
+---
+title: Mockup browser
+summary: A mockup browser is a frame that looks like a browser window, with the window dots and an address bar, to show a page preview or a screenshot.
+description: Show a screenshot or any content inside a browser window frame with the mockup browser component. Add an address, a lock icon or your own colors.
+related: [/ui/components/image-label, /ui/components/card]
+source: core/scss/ui/_mockup-browser.scss
+css-vars: mockup-browser
+classnames:
+ component:
+ - class: mockup-browser
+ desc: The frame, with a border, rounded corners and a shadow
+ size:
+ - class: mockup-browser-sm
+ desc: A 24px toolbar with smaller dots and text, for thumbnails and cards
+ part:
+ - class: mockup-browser-toolbar
+ desc: The top bar with the window dots and the address bar
+ - class: mockup-browser-controls
+ desc: The three window dots
+ - class: mockup-browser-url
+ desc: The address, centered in the toolbar
+ - class: mockup-browser-body
+ desc: The page area that holds the screenshot or the content
+---
+import Example from '@components/Example.astro';
+import Icon from '@ui/Icon.astro';
+
+## Default markup
+
+A `.mockup-browser` has a `.mockup-browser-toolbar` with the window dots and an address bar, and a `.mockup-browser-body` with the page. An image in the body fills the width of the frame.
+
+Create an account
+
+ .mockup-browser frame, with the window dots and an address bar..mockup-browser-url for a plain window frame..mockup-browser-sm for a 24px toolbar with smaller dots and text, for thumbnails and cards.Create an account
+ --tblr-mockup-browser-* variables for a dark toolbar, other window dot colors or no shadow.