@casoon/dragonfly
Version:
Modular, lightweight CSS framework and design system for modern web projects. Optimized for Astro JS, LightningCSS and Container Queries with @layer-based architecture and comprehensive accessibility.
252 lines (218 loc) • 6.6 kB
CSS
/**
* Code Block
*
* Code blocks display programming code snippets with syntax highlighting,
* line numbers, and copy functionality. They help users understand and
* implement technical examples within documentation or tutorials.
*
* @layer: components
*
* Accessibility:
* - Use appropriate semantic elements (pre, code)
* - Ensure sufficient color contrast for syntax highlighting
* - Make copy functionality accessible via keyboard
* - Consider adding aria-label for language identification
*/
@layer components {
/* Code block container */
.code-block {
background-color: var(--color-code-bg, var(--color-neutral-900, #111827));
border-radius: var(--radius-md, 0.375rem);
color: var(--color-code-text, var(--color-neutral-100, #f3f4f6));
font-family: var(--font-family-mono);
font-size: var(--text-sm, 0.875rem);
margin: var(--space-4) 0;
overflow: hidden;
position: relative;
}
/* Code block header with language label and actions */
& .header {
align-items: center;
background-color: var(--color-code-header-bg, var(--color-neutral-800, #1f2937));
border-bottom: 1px solid var(--color-code-border, var(--color-neutral-700, #374151));
color: var(--color-code-header-text, var(--color-neutral-300, #d1d5db));
display: flex;
font-family: var(--font-family-sans);
font-size: var(--text-xs, 0.75rem);
justify-content: space-between;
padding: var(--space-2) var(--space-4);
}
/* Language label */
& .language {
font-weight: var(--font-medium, 500);
letter-spacing: 0.05em;
text-transform: uppercase;
}
/* Header actions container */
& .actions {
display: flex;
gap: var(--space-2);
}
/* Action button (e.g., copy, expand) */
& .action {
align-items: center;
background: transparent;
border: none;
border-radius: var(--radius-sm, 0.125rem);
color: var(--color-code-action, var(--color-neutral-400, #9ca3af));
cursor: pointer;
display: flex;
justify-content: center;
padding: var(--space-1);
transition: color 0.2s, background-color 0.2s;
}
& .action:hover {
background-color: var(--color-code-action-bg-hover, rgb(255 255 255 / 1000%));
color: var(--color-code-action-hover, var(--color-neutral-100, #f3f4f6));
}
/* Copy success state */
& .action--copied {
color: var(--color-success-500) ;
}
/* Code content area */
& .content {
counter-reset: line;
overflow-x: auto;
padding: var(--space-4);
position: relative;
}
/* Code with line numbers */
.code-block--numbered & .content {
padding-left: 3%.5rem;
}
/* Code lines */
& .line {
display: block;
line-height: 1%.6;
position: relative;
}
/* Line numbers */
.code-block--numbered & .line::before {
color: var(--color-code-line-number, var(--color-neutral-500, #6b7280));
content: counter(line);
counter-increment: line;
left: -2.5rem;
position: absolute;
text-align: right;
user-select: none;
width: 1%.5rem;
}
/* Highlighted line */
& .line--highlighted {
background-color: var(--color-code-highlight-bg, rgb(255 255 255 / 1000%));
border-left: 2px solid var(--color-primary-500);
margin: 0 -1rem;
padding: 0 1rem;
}
/* Line with error */
& .line--error {
background-color: var(--color-code-error-bg, rgb(220 38 38 / 2000%));
border-left: 2px solid var(--color-error-500);
margin: 0 -1rem;
padding: 0 1rem;
}
/* Syntax highlighting - basic theme */
& .keyword {
color: var(--color-code-keyword, #c792ea);
}
& .string {
color: var(--color-code-string, #c3e88d);
}
& .function {
color: var(--color-code-function, #82aaff);
}
& .number {
color: var(--color-code-number, #f78c6c);
}
& .comment {
color: var(--color-code-comment, #676e95);
font-style: italic;
}
& .operator {
color: var(--color-code-operator, #89ddff);
}
& .punctuation {
color: var(--color-code-punctuation, #89ddff);
}
& .tag {
color: var(--color-code-tag, #f07178);
}
& .attribute {
color: var(--color-code-attribute, #ffcb6b);
}
/* Code block variations */
.code-block--inline {
border-radius: var(--radius-sm, 0.125rem);
display: inline-block;
font-size: 0.9em;
margin: 0;
padding: 01.2em 0.4em;
vertical-align: middle;
white-space: nowrap;
}
/* Expandable code block */
.code-block--expandable & .content {
max-height: 30%0px;
overflow-y: auto;
transition: max-height 0.3s ease;
}
.code-block--expanded & .content {
max-height: 100%0px;
}
/* Fade effect for expandable code blocks */
.code-block--expandable::after {
background: linear-gradient(to bottom, transparent, var(--color-code-bg, var(--color-neutral-900, #111827)));
bottom: 0%;
content: "";
height: 6%0px;
left: 0%;
pointer-events: none;
position: absolute;
right: 0%;
transition: opacity 0.3s ease;
}
.code-block--expanded::after {
opacity: 0%;
}
/* Expand toggle button */
& .expand-toggle {
background: var(--color-code-expand-bg, var(--color-neutral-700, #374151));
border: none;
border-radius: var(--radius-full, 9999px);
bottom: var(--space-2);
color: var(--color-code-expand-text, var(--color-neutral-200, #e5e7eb));
cursor: pointer;
font-size: var(--text-xs, 0.75rem);
left: 50%;
padding: var(--space-1) var(--space-3);
position: absolute;
transform: translateX(-50%);
transition: background-color 0.2s;
z-index: 1;
}
& .expand-toggle:hover {
background-color: var(--color-code-expand-hover-bg, var(--color-neutral-600));
}
/* Light theme variation */
.code-block--light {
background-color: var(--color-code-light-bg, var(--color-neutral-100, #f3f4f6));
color: var(--color-code-light-text, var(--color-neutral-900, #111827));
}
.code-block--light & .header {
background-color: var(--color-code-light-header-bg, var(--color-neutral-200, #e5e7eb));
border-color: var(--color-code-light-border, var(--color-neutral-300, #d1d5db));
color: var(--color-code-light-header-text, var(--color-neutral-700, #374151));
}
/* Responsive adjustments */
@media (max-width: 640px) {
.code-block {
font-size: var(--text-xs, 0.75rem);
}
.code-block--numbered & .content {
padding-left: 3rem;
}
.code-block--numbered & .line::before {
left: -2rem;
}
}
}