mirror of
https://github.com/hugo-fixit/FixIt.git
synced 2026-08-24 15:28:57 +00:00
feat(code): add shadow effect for code blocks (#713)
This commit is contained in:
@@ -53,6 +53,25 @@ def greet(name):
|
||||
return f"Hello, {name}!"
|
||||
```
|
||||
|
||||
## Shadow
|
||||
|
||||
```js {group=tab-shadow name="Always" shadow="always"}
|
||||
function greet(name) {
|
||||
return `Hello, ${name}!`
|
||||
}
|
||||
```
|
||||
|
||||
```python {group=tab-shadow name="Hover" shadow="hover"}
|
||||
def greet(name):
|
||||
return f"Hello, {name}!"
|
||||
```
|
||||
|
||||
```go {group=tab-shadow name="Never" shadow="never"}
|
||||
func greet(name string) string {
|
||||
return fmt.Sprintf("Hello, %s!", name)
|
||||
}
|
||||
```
|
||||
|
||||
## Mode
|
||||
|
||||
```ts {group=tab-mode name="Classic"}
|
||||
@@ -121,3 +140,27 @@ function shortFunction() {
|
||||
console.log('This is a short function.')
|
||||
}
|
||||
```
|
||||
|
||||
## Code tabs inside other blocks
|
||||
|
||||
> [!NOTE]+
|
||||
>
|
||||
> ```python {group=tab-nested}
|
||||
> print("Python")
|
||||
> ```
|
||||
>
|
||||
> ```go {group=tab-nested}
|
||||
> fmt.Println("Go")
|
||||
> ```
|
||||
|
||||
{{< details open=true >}}
|
||||
|
||||
```python {group=tab2}
|
||||
print("Python")
|
||||
```
|
||||
|
||||
```go {group=tab2}
|
||||
fmt.Println("Go")
|
||||
```
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
@@ -64,6 +64,38 @@ hello('FixIt')
|
||||
// Hello, FixIt!
|
||||
```
|
||||
|
||||
## Shadow
|
||||
|
||||
{{< tabs >}}
|
||||
{{% tab title="Always" %}}
|
||||
|
||||
```js {shadow="always"}
|
||||
function hello(x = 'world') {
|
||||
console.log(`Hello, ${x}!`)
|
||||
}
|
||||
```
|
||||
|
||||
{{% /tab %}}
|
||||
{{% tab title="Hover" %}}
|
||||
|
||||
```js {shadow="hover"}
|
||||
function hello(x = 'world') {
|
||||
console.log(`Hello, ${x}!`)
|
||||
}
|
||||
```
|
||||
|
||||
{{% /tab %}}
|
||||
{{% tab title="Never" %}}
|
||||
|
||||
```js {shadow="never"}
|
||||
function hello(x = 'world') {
|
||||
console.log(`Hello, ${x}!`)
|
||||
}
|
||||
```
|
||||
|
||||
{{% /tab %}}
|
||||
{{< /tabs >}}
|
||||
|
||||
## Collapsed/Expanded
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/// Mixin to apply box-shadow with timing control
|
||||
/// @param {String} $when - When to show shadow: always | hover | never (default: always)
|
||||
/// @param {List} $shadow - The box-shadow value
|
||||
/// @example
|
||||
/// @include box-shadow;
|
||||
/// @include box-shadow(hover);
|
||||
/// @include box-shadow(never);
|
||||
/// @include box-shadow(always, 0 4px 8px rgba(0, 0, 0, 0.15));
|
||||
@mixin box-shadow(
|
||||
$when: always,
|
||||
$shadow: (0 1px 2px -2px rgba(0, 0, 0, 0.08), 0 3px 6px 0 rgba(0, 0, 0, 0.06), 0 5px 12px 4px rgba(0, 0, 0, 0.04))
|
||||
) {
|
||||
@if $when == always {
|
||||
box-shadow: $shadow;
|
||||
} @else if $when == hover {
|
||||
transition: box-shadow 0.3s fixit-var(bezier);
|
||||
|
||||
&:hover {
|
||||
box-shadow: $shadow;
|
||||
}
|
||||
} @else if $when == never {
|
||||
box-shadow: none;
|
||||
} @else {
|
||||
@warn "box-shadow mixin: unknown $when value '#{$when}'. Expected always, hover, or never.";
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
@import 'theme-vars';
|
||||
@import 'blur';
|
||||
@import 'border-radius';
|
||||
@import 'box-shadow';
|
||||
@import 'compatibility';
|
||||
@import 'link';
|
||||
@import 'loading';
|
||||
@import 'scrollbar-width';
|
||||
@import 'theme-vars';
|
||||
@import 'z-index';
|
||||
|
||||
@@ -55,6 +55,9 @@
|
||||
scrollbar-width: thin,
|
||||
scrollbar-width-legacy: 12px,
|
||||
|
||||
// Animations
|
||||
bezier: cubic-bezier(.4, 0, .2, 1),
|
||||
|
||||
// Other utilities
|
||||
breadcrumb-height: 0px,
|
||||
divider-edge-weak: linear-gradient(to right, transparent, fixit-var(divider-bg, #d0d0d5), transparent),
|
||||
|
||||
@@ -154,7 +154,8 @@
|
||||
}
|
||||
}
|
||||
[data-header-desktop='sticky'] {
|
||||
.page .content .highlight.code-block .code-header {
|
||||
.page .content .highlight.code-block .code-header,
|
||||
.page .content .code-tabs .tabs-header {
|
||||
top: calc(#{fixit-var(header-height)} + #{fixit-var(breadcrumb-height)});
|
||||
}
|
||||
}
|
||||
@@ -193,7 +194,8 @@
|
||||
}
|
||||
}
|
||||
[data-header-mobile='sticky'] {
|
||||
.page .content .highlight.code-block .code-header {
|
||||
.page .content .highlight.code-block .code-header,
|
||||
.page .content .code-tabs .tabs-header {
|
||||
top: calc(#{fixit-var(header-height)} + #{fixit-var(breadcrumb-height)});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +132,14 @@ pre {
|
||||
|
||||
// code fences blocks wrapped
|
||||
&.code-block {
|
||||
&[data-shadow='always'] {
|
||||
@include box-shadow(always);
|
||||
}
|
||||
|
||||
&[data-shadow='hover'] {
|
||||
@include box-shadow(hover);
|
||||
}
|
||||
|
||||
&.instant-height .code-wrapper {
|
||||
transition: height 0s !important;
|
||||
}
|
||||
@@ -267,10 +275,7 @@ pre {
|
||||
|
||||
&.is-fullscreen {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
inset: 0;
|
||||
margin: 0 !important;
|
||||
overflow: auto;
|
||||
@include z-index(fixed, 1);
|
||||
@@ -567,6 +572,14 @@ pre {
|
||||
border: 1px solid fixit-var(global-border-color);
|
||||
@include border-radius;
|
||||
|
||||
&[data-shadow='always'] {
|
||||
@include box-shadow(always);
|
||||
}
|
||||
|
||||
&[data-shadow='hover'] {
|
||||
@include box-shadow(hover);
|
||||
}
|
||||
|
||||
&:has(.code-block.active .code-expand-btn) {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
@@ -585,6 +598,9 @@ pre {
|
||||
font-size: fixit-var(code-block-font-size);
|
||||
color: fixit-var(code-header-color);
|
||||
background-color: fixit-var(code-header-background-color);
|
||||
position: sticky;
|
||||
top: fixit-var(breadcrumb-height);
|
||||
@include z-index(base);
|
||||
@include border-radius(top);
|
||||
|
||||
.tabs-items {
|
||||
@@ -662,6 +678,7 @@ pre {
|
||||
display: none;
|
||||
margin: 0;
|
||||
@include border-radius(bottom);
|
||||
@include box-shadow(never);
|
||||
|
||||
&.active {
|
||||
display: block;
|
||||
|
||||
@@ -60,7 +60,8 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.code-block .code-header {
|
||||
.code-block .code-header,
|
||||
.code-tabs .tabs-header {
|
||||
top: initial !important;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -671,7 +671,15 @@ class FixIt {
|
||||
$tabs.forEach(b => b.classList.remove('active'));
|
||||
$tab.classList.add('active');
|
||||
|
||||
// 4. move new buttons to actions
|
||||
// 4. sync shadow mode data attribute
|
||||
const shadowMode = $tab?.dataset.shadow;
|
||||
if (shadowMode) {
|
||||
$container.dataset.shadow = shadowMode;
|
||||
} else {
|
||||
delete $container.dataset.shadow;
|
||||
}
|
||||
|
||||
// 5. move new buttons to actions
|
||||
const $codeHeader = $tab.querySelector('.code-header');
|
||||
if ($codeHeader) {
|
||||
$codeHeader.querySelectorAll('.action-btn').forEach(btn => $actions.appendChild(btn));
|
||||
|
||||
@@ -1144,6 +1144,8 @@ mode = "classic"
|
||||
wrapperClass = ""
|
||||
# the maximum number of lines to show in the code block preview
|
||||
maxShownLines = 10
|
||||
# whether to show shadow effect for code blocks, available values: ["always", "hover", "never"]
|
||||
shadow = "never"
|
||||
# whether to enable code copy button
|
||||
copyable = true
|
||||
# [classic] whether to enable code download button in the code block header
|
||||
|
||||
@@ -58,11 +58,25 @@
|
||||
(printf `class="%s" data-copyable="%v"` $class $config.copyable)
|
||||
-}}
|
||||
{{- end -}}
|
||||
{{- if ne $config.shadow "never" -}}
|
||||
{{- $wrapper =
|
||||
replace $wrapper
|
||||
(printf `class="%s"` $class)
|
||||
(printf `class="%s" data-shadow="%s"` $class $config.shadow)
|
||||
-}}
|
||||
{{- end -}}
|
||||
{{- if $config.group -}}
|
||||
{{- $tabTitle := $config.name | default (strings.FirstUpper .Type) | default "Code" -}}
|
||||
{{- $wrapper =
|
||||
replace $wrapper
|
||||
(printf `class="%s"` $class)
|
||||
(printf `class="%s" data-tab-group="%s" data-tab-title="%s"` $class $config.group $tabTitle) -}}
|
||||
{{- end -}}
|
||||
{{- if ne .Options.linenostart nil -}}
|
||||
{{- $wrapper =
|
||||
replace $wrapper
|
||||
`class="code-wrapper"`
|
||||
(printf `class="code-wrapper" data-line-start="%v"` .)
|
||||
(printf `class="code-wrapper" data-line-start="%v"` .Options.linenostart)
|
||||
-}}
|
||||
{{- end -}}
|
||||
{{- $wrapperStyle := printf "--fi-max-shown-lines:%v;--fi-line-digit:%v;--fi-line-start:%v;" $maxShownLines $lineNosDigit $lineNoStart -}}
|
||||
@@ -80,10 +94,6 @@
|
||||
$lineNosDigit
|
||||
)
|
||||
-}}
|
||||
{{- if $config.group -}}
|
||||
{{- $tabTitle := $config.name | default (strings.FirstUpper .Type) | default "Code" -}}
|
||||
{{- $wrapper = replace $wrapper (printf `class="%s"` $class) (printf `class="%s" data-tab-group="%s" data-tab-title="%s"` $class $config.group $tabTitle) -}}
|
||||
{{- end -}}
|
||||
{{- $wrapper =
|
||||
replace $wrapper
|
||||
(printf `class="%s"` $class)
|
||||
|
||||
Reference in New Issue
Block a user