view release on metacpan or search on metacpan
"el.style.cssText='pointer-events:auto;display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:var(--chandra-radius,6px);background:var(--chandra-surface,#1e1e1e);color:var(--chandra-text,#e0e0e0);box-shadow:var(--chandra-shadow,0 2p...
"var ic=document.createElement('span');"
"ic.style.cssText='font-size:1.2em;flex-shrink:0;';"
"ic.textContent=o.icon;el.appendChild(ic);"
"var bd=document.createElement('div');"
"bd.style.cssText='flex:1;min-width:0;';"
"bd.textContent=msg;el.appendChild(bd);"
"if(act&&act.label){"
"var btn=document.createElement('button');"
"btn.textContent=act.label;"
"btn.style.cssText='padding:4px 12px;border:1px solid var(--chandra-border,#333);border-radius:var(--chandra-radius,4px);background:transparent;color:var(--chandra-primary,#64B5F6);cursor:pointer;font-size:0.85em;flex-shrink:0;';"
"btn.onclick=function(e){e.stopPropagation();if(act.handler)window.chandra.invoke(act.handler,[]);dismiss(id);};"
"el.appendChild(btn);}"
"var cl=document.createElement('span');"
"cl.textContent='\\u00D7';"
"cl.style.cssText='cursor:pointer;opacity:0.5;font-size:1.2em;flex-shrink:0;padding:0 2px;';"
"cl.onclick=function(e){e.stopPropagation();dismiss(id);};"
"el.appendChild(cl);"
"el.onclick=function(){dismiss(id);};"
"while(c.children.length>=5){var ol=c.firstChild;if(ol)dismiss(ol.id);}"
"c.appendChild(el);t[id]=el;"
"requestAnimationFrame(function(){el.style.opacity='1';el.style.transform='translateX(0)';});"
"if(dur>0)setTimeout(function(){dismiss(id);},dur);}"
"function dismiss(id){"
"var el=t[id];if(!el)return;"
"el.style.opacity='0';el.style.transform='translateX(100%)';"
"modal.style.cssText='background:var(--chandra-bg,#fff);border:1px solid var(--chandra-border,#e0e0e0);border-radius:var(--chandra-radius,6px);box-shadow:var(--chandra-shadow,0 4px 16px rgba(0,0,0,0.2));padding:0;min-width:320px;max-width:'+(opts.wid...
/* Title bar */
"if(opts.title){"
"var hdr=document.createElement('div');"
"hdr.style.cssText='padding:16px 20px 12px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--chandra-border,#e0e0e0);';"
"var t=document.createElement('h3');"
"t.style.cssText='margin:0;font-size:1.1em;';t.textContent=opts.title;"
"hdr.appendChild(t);"
"if(opts.closable!==false){"
"var x=document.createElement('span');"
"x.textContent='\\u00D7';x.style.cssText='cursor:pointer;font-size:1.4em;opacity:0.5;padding:0 4px;';"
"x.onclick=function(){close(id);};hdr.appendChild(x);}"
"modal.appendChild(hdr);}"
/* Body */
"var body=document.createElement('div');"
"body.style.cssText='padding:16px 20px;';body.id=id+'_body';"
"if(opts.content)body.innerHTML=opts.content;"
"if(opts.message){var p=document.createElement('p');p.style.margin='0';p.textContent=opts.message;body.appendChild(p);}"
"if(opts.input){"
"var inp=document.createElement('input');"
"inp.type='text';inp.id=id+'_input';"
examples/assets_mount_example.pl view on Meta::CPAN
background: rgba(255,255,255,0.15);
backdrop-filter: blur(10px);
border-radius: 12px;
padding: 1.5em;
margin: 1em 0;
border: 1px solid rgba(255,255,255,0.2);
}
button {
background: #fff; color: #764ba2;
border: none; border-radius: 6px;
padding: 0.6em 1.2em; cursor: pointer;
font-weight: bold; font-size: 1em;
}
button:hover { opacity: 0.9; }
#status { color: #a5d6a7; font-weight: bold; }
CSS
_write("$asset_dir/js/main.js", <<'JS');
(function init() {
// Protocol-loaded scripts arrive after DOMContentLoaded,
// so run immediately when the DOM is already ready.
examples/bind_example.pl view on Meta::CPAN
padding: 15px;
margin: 10px 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
button {
background: rgb(76, 175, 80);
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
margin: 5px;
}
button:hover { background: rgb(69, 160, 73); }
input {
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
margin: 5px;
}
#result {
examples/bridge_extension_example.pl view on Meta::CPAN
h1 { text-align: center; margin-bottom: 16px; font-size: 22px; color: #e94560; }
.input-row {
display: flex; gap: 8px; margin-bottom: 16px;
}
.input-row input {
flex: 1; padding: 10px 14px; border-radius: 8px; border: 1px solid #333;
background: #1a1a2e; color: #fff; font-size: 14px; outline: none;
}
.input-row input:focus { border-color: #e94560; }
.input-row button, #stats-btn {
padding: 10px 18px; border-radius: 8px; border: none; cursor: pointer;
background: #e94560; color: #fff; font-size: 14px; font-weight: 600;
transition: background 0.2s;
}
.input-row button:hover, #stats-btn:hover { background: #c73652; }
ul#tasks { list-style: none; }
ul#tasks li {
display: flex; align-items: center; gap: 8px;
padding: 10px 14px; margin-bottom: 6px; border-radius: 8px;
background: rgba(255,255,255,0.06); transition: opacity 0.3s;
}
ul#tasks li .text { flex: 1; }
ul#tasks li .time { font-size: 11px; color: #888; }
ul#tasks li button {
padding: 4px 12px; border-radius: 6px; border: none;
background: #2ecc71; color: #fff; cursor: pointer; font-size: 12px;
}
ul#tasks li button:disabled { background: #555; cursor: default; }
ul#tasks li.done .text { text-decoration: line-through; color: #666; }
#toasts {
position: fixed; bottom: 12px; right: 12px; z-index: 999;
display: flex; flex-direction: column; gap: 6px;
}
.toast {
padding: 8px 16px; border-radius: 8px; font-size: 13px;
animation: fadeIn 0.3s ease;
}
.toast-info { background: #2980b9; color: #fff; }
examples/canvas_demo.pl view on Meta::CPAN
.canvas-wrapper {
background: #fff;
border-radius: 12px;
padding: 10px;
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
margin-bottom: 20px;
}
canvas {
display: block;
border-radius: 8px;
cursor: crosshair;
}
.toolbar {
display: flex;
gap: 15px;
flex-wrap: wrap;
justify-content: center;
margin-bottom: 15px;
}
.tool-group {
background: rgba(255,255,255,0.1);
examples/canvas_demo.pl view on Meta::CPAN
font-size: 12px;
color: #aaa;
margin-right: 5px;
}
button {
background: #3498db;
color: #fff;
border: none;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-size: 13px;
transition: all 0.2s;
}
button:hover {
background: #2980b9;
transform: translateY(-1px);
}
button.active {
background: #e74c3c;
}
examples/canvas_demo.pl view on Meta::CPAN
background: #27ae60;
}
button.demo:hover {
background: #219a52;
}
.color-btn {
width: 28px;
height: 28px;
border-radius: 50%;
border: 2px solid transparent;
cursor: pointer;
transition: all 0.2s;
}
.color-btn:hover {
transform: scale(1.1);
}
.color-btn.active {
border-color: #fff;
box-shadow: 0 0 10px rgba(255,255,255,0.5);
}
.status {
examples/chat_window.pl view on Meta::CPAN
outline: none;
}
#input:focus { border-color: #e94560; }
#send-btn {
padding: 8px 20px;
border-radius: 20px;
border: none;
background: #e94560;
color: #fff;
font-size: 14px;
cursor: pointer;
}
#send-btn:hover { background: #c83b54; }
</style>
</head>
<body>
<div id="header">
<span>Chat — <span class="name">$name</span></span>
<span id="users"></span>
</div>
<div id="messages"></div>
examples/contextmenu_example.pl view on Meta::CPAN
<head>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
margin: 0; display: flex; flex-direction: column; height: 100vh;
background: #f5f5f5; color: #333; }
.header { padding: 12px 16px; background: #2c3e50; color: white;
font-size: 14px; font-weight: 600; }
.main { display: flex; flex: 1; overflow: hidden; }
.sidebar { width: 200px; background: #ecf0f1; border-right: 1px solid #ddd;
padding: 8px 0; overflow-y: auto; }
.list-item { padding: 8px 16px; cursor: pointer; font-size: 13px; }
.list-item:hover { background: #dfe6e9; }
#editor { flex: 1; padding: 16px; font-family: monospace; font-size: 13px;
white-space: pre-wrap; background: #fff; overflow-y: auto;
line-height: 1.6; min-height: 200px; }
#log { height: 120px; overflow-y: auto; background: #2d2d2d; color: #0f0;
font-family: monospace; font-size: 12px; padding: 8px; border-top: 2px solid #444; }
.log-entry { padding: 2px 0; }
.hint { color: #888; font-size: 12px; padding: 8px 16px; background: #fafafa;
border-top: 1px solid #eee; }
</style>
examples/counter_app.pl view on Meta::CPAN
}
#count.bump { transform: scale(1.2); }
.buttons { display: flex; gap: 12px; justify-content: center; margin-top: 20px; }
button {
width: 50px; height: 50px;
border-radius: 50%;
border: 2px solid rgba(255,255,255,0.5);
background: rgba(255,255,255,0.2);
color: #fff;
font-size: 24px;
cursor: pointer;
transition: all 0.15s ease;
}
button:hover { background: rgba(255,255,255,0.35); transform: scale(1.1); }
button:active { transform: scale(0.95); }
.reset {
margin-top: 16px;
width: auto;
border-radius: 8px;
padding: 8px 24px;
font-size: 14px;
examples/devtools_example.pl view on Meta::CPAN
my $ui = Chandra::Element->new({
tag => 'div',
style => { padding => '20px', 'font-family' => 'sans-serif' },
children => [
{ tag => 'h1', data => 'DevTools Demo' },
{ tag => 'p', data => 'Press F12 to open the DevTools panel.' },
{
tag => 'button',
data => 'Trigger Error',
style => 'padding:8px 16px;margin:4px;cursor:pointer;',
onclick => sub {
my ($event, $app) = @_;
$app->eval_js("window.chandra.invoke('trigger_error', [])");
},
},
{
tag => 'button',
data => 'Say Hello',
style => 'padding:8px 16px;margin:4px;cursor:pointer;',
onclick => sub {
my ($event, $app) = @_;
$app->eval_js("window.chandra.invoke('greet', ['World']).then(function(r){ document.getElementById('output').textContent = r; })");
},
},
{ tag => 'p', id => 'output', data => '', style => 'color:#333;margin-top:12px;' },
],
});
$app->set_content($ui);
examples/dialog_example.pl view on Meta::CPAN
margin-bottom: 12px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
button {
background: #3498db;
color: #fff;
border: none;
padding: 10px 16px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
margin-right: 8px;
margin-bottom: 8px;
}
button:hover {
background: #2980b9;
}
button.warning {
background: #f39c12;
}
examples/dragdrop_example.pl view on Meta::CPAN
#upload-zone { min-height: 80px; }
#upload-status { color: #4ecca3; margin-top: 8px; }
.columns { display: flex; gap: 16px; margin-top: 12px; }
.column {
flex: 1; background: #16213e; border-radius: 8px;
padding: 12px; min-height: 100px;
}
.draggable {
background: #0f3460; padding: 8px 12px; border-radius: 6px;
margin: 6px 0; cursor: grab; user-select: none;
}
.draggable:active { cursor: grabbing; }
.log { max-height: 120px; overflow-y: auto; margin-top: 8px; }
.entry { padding: 4px 0; border-bottom: 1px solid #333; font-size: 13px; }
</style>
</head>
<body>
<h1>Drag & Drop</h1>
<h2>File Drop</h2>
<div id="upload-zone" class="drop-zone">
examples/element_example.pl view on Meta::CPAN
{
tag => 'input',
type => 'text',
id => 'new-item',
placeholder => 'Add item...',
style => 'flex:1; padding:8px; border:1px solid #ccc; border-radius:4px; font-size:14px',
},
{
tag => 'button',
data => 'Add',
style => 'padding:8px 20px; background:#4CAF50; color:#fff; border:none; border-radius:4px; cursor:pointer; font-size:14px',
onclick => sub {
$app->dispatch_eval(
"var v=document.getElementById('new-item').value;" .
"if(v){window.chandra.invoke('add_item',[v]).then(function(){" .
"document.getElementById('new-item').value='';});}"
);
},
},
],
},
examples/element_example.pl view on Meta::CPAN
my $item = $_;
{
tag => 'li',
id => "item-$item->{id}",
style => 'display:flex; justify-content:space-between; align-items:center; padding:10px; margin:4px 0; background:#f9f9f9; border-radius:4px',
children => [
{ tag => 'span', data => $item->{name}, style => 'font-size:14px' },
{
tag => 'button',
data => 'x',
style => 'background:#e74c3c; color:#fff; border:none; border-radius:50%; width:24px; height:24px; cursor:pointer; font-size:12px',
onclick => sub {
$app->dispatch_eval(
"window.chandra.invoke('remove_item',[$item->{id}])"
);
},
},
],
}
} @items
],
examples/form_example.pl view on Meta::CPAN
fieldset.chandra-group {
border: 1px solid #444; border-radius: 6px;
padding: 12px 14px; margin: 16px 0;
}
fieldset.chandra-group legend {
font-size: 14px; font-weight: 600; padding: 0 6px;
}
.chandra-submit {
padding: 10px 28px; font-size: 14px; font-weight: 600;
background: #0078d4; color: #fff; border: none;
border-radius: 4px; cursor: pointer; margin-top: 8px;
}
.chandra-submit:hover { background: #106ebe; }
.chandra-error {
display: block; font-size: 12px; color: #f44;
min-height: 16px; margin-top: 2px;
}
#result {
display: none; margin-top: 12px; padding: 10px;
background: #1b5e20; border-radius: 4px;
font-size: 14px; text-align: center;
examples/multiwindow_example.pl view on Meta::CPAN
my $del_btn = $is_dark ? '#555' : '#ccc';
return qq(
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: system-ui, sans-serif; margin: 0; background: $bg; color: $li_fg; }
h1 { background: #e74c3c; color: #fff; margin: 0; padding: 16px 20px; font-size: 1.4em; }
.toolbar { display:flex; gap:8px; padding:12px 20px; background:$toolbar_bg; border-bottom:1px solid $toolbar_bdr; }
button { cursor:pointer; border:none; border-radius:4px; padding:6px 12px; font-size:.9em; }
.btn-add { background:#e74c3c; color:#fff; }
.btn-settings { background:$btn_bg; color:$btn_fg; margin-left:auto; }
.filters { display:flex; gap:4px; }
.filters button { background:$btn_bg; color:$btn_fg; }
.filters button.active { background:#3498db; color:#fff; }
ul { list-style:none; margin:0; padding:0 20px; }
li { display:flex; align-items:center; gap:8px; padding:10px 0;
border-bottom:1px solid $li_border; }
li input[type=checkbox] { width:18px; height:18px; cursor:pointer; }
li span { flex:1; }
li button { background:transparent; color:$del_btn; font-size:1.1em; padding:2px 6px; }
li button:hover { color:#e74c3c; }
.footer { padding:12px 20px; color:$footer_fg; font-size:.85em; }
</style>
</head>
<body>
<h1>Todos</h1>
<div class="toolbar">
<button class="btn-add"
examples/multiwindow_example.pl view on Meta::CPAN
return qq(
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family:system-ui,sans-serif; margin:0; padding:20px; background:$bg; color:$fg; }
h2 { margin-top:0; font-size:1.1em; }
input[type=text] { width:100%; box-sizing:border-box; padding:8px; font-size:1em;
border:1px solid $input_bd; border-radius:4px; background:$input_bg; color:$fg; }
.buttons { display:flex; gap:8px; margin-top:12px; justify-content:flex-end; }
button { border:none; border-radius:4px; padding:8px 16px; cursor:pointer; font-size:.9em; }
.ok { background:#e74c3c; color:#fff; }
.cancel { background:$btn_bg; color:$btn_fg; }
</style>
</head>
<body>
<h2>New Todo</h2>
<input type="text" id="txt" placeholder="What needs to be done?"
onkeydown="if(event.key==='Enter') document.getElementById('ok').click()">
<div class="buttons">
<button class="cancel"
examples/multiwindow_example.pl view on Meta::CPAN
my $fg = $is_dark ? '#eee' : '#333';
return qq(
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family:system-ui,sans-serif; margin:0; padding:20px; background:$bg; color:$fg; }
h2 { margin-top:0; font-size:1.1em; }
label { display:flex; align-items:center; gap:8px; margin:10px 0; }
button { border:none; border-radius:4px; padding:8px 16px; cursor:pointer;
background:#e74c3c; color:#fff; margin-top:12px; font-size:.9em; }
</style>
</head>
<body>
<h2>Settings</h2>
<label>
<input type="checkbox" id="dark" $checked
onchange="window.chandra.invoke('set_theme',[this.checked?'dark':'light'])">
Dark theme
</label>
examples/pack_example/lib/PackedCounter.pm view on Meta::CPAN
}
#count.bump { transform: scale(1.2); }
.buttons { display: flex; gap: 12px; justify-content: center; margin-top: 20px; }
button {
width: 50px; height: 50px;
border-radius: 50%;
border: 2px solid rgba(255,255,255,0.5);
background: rgba(255,255,255,0.2);
color: #fff;
font-size: 24px;
cursor: pointer;
transition: all 0.15s ease;
}
button:hover { background: rgba(255,255,255,0.35); transform: scale(1.1); }
button:active { transform: scale(0.95); }
.reset {
margin-top: 16px;
width: auto;
border-radius: 8px;
padding: 8px 24px;
font-size: 14px;
include/chandra/chandra_devtools.h view on Meta::CPAN
" header.appendChild(title);\n"
"\n"
" var tabs = ['Console', 'Bindings', 'Elements'];\n"
" var self = this;\n"
" tabs.forEach(function(tab) {\n"
" var btn = document.createElement('button');\n"
" btn.textContent = tab;\n"
" btn.className = '__cdt-tab';\n"
" btn.setAttribute('data-tab', tab.toLowerCase());\n"
" btn.style.cssText = 'background:none;border:1px solid #45475a;color:#cdd6f4;' +\n"
" 'padding:2px 8px;margin:0 2px;cursor:pointer;border-radius:3px;font-size:11px;';\n"
" btn.onclick = function() { self.showTab(tab.toLowerCase()); };\n"
" header.appendChild(btn);\n"
" });\n"
"\n"
" var reloadBtn = document.createElement('button');\n"
" reloadBtn.textContent = '\\u27F3 Reload';\n"
" reloadBtn.style.cssText = 'background:none;border:1px solid #45475a;color:#a6e3a1;' +\n"
" 'padding:2px 8px;margin:0 2px;cursor:pointer;border-radius:3px;font-size:11px;';\n"
" reloadBtn.onclick = function() {\n"
" if (window.chandra) window.chandra.invoke('__devtools_reload', []);\n"
" };\n"
" header.appendChild(reloadBtn);\n"
"\n"
" var clearBtn = document.createElement('button');\n"
" clearBtn.textContent = '\\u2718 Clear';\n"
" clearBtn.style.cssText = 'background:none;border:1px solid #45475a;color:#f9e2af;' +\n"
" 'padding:2px 8px;margin:0 2px;cursor:pointer;border-radius:3px;font-size:11px;';\n"
" clearBtn.onclick = function() { self.clearConsole(); };\n"
" header.appendChild(clearBtn);\n"
"\n"
" var closeBtn = document.createElement('button');\n"
" closeBtn.textContent = '\\u2715';\n"
" closeBtn.style.cssText = 'background:none;border:none;color:#f38ba8;padding:2px 6px;' +\n"
" 'cursor:pointer;font-size:14px;margin-left:4px;';\n"
" closeBtn.onclick = function() { self.toggle(); };\n"
" header.appendChild(closeBtn);\n"
"\n"
" this.panel.appendChild(header);\n"
"\n"
" this.content = document.createElement('div');\n"
" this.content.style.cssText = 'height:calc(100% - 30px);overflow-y:auto;padding:8px;';\n"
" this.panel.appendChild(this.content);\n"
"\n"
" document.body.appendChild(this.panel);\n"
lib/Chandra/Breadcrumb.pm view on Meta::CPAN
sub css {
return <<'CSS';
.chandra-breadcrumb-list {
list-style: none; margin: 0; padding: 0;
display: flex; align-items: center; gap: 0;
font-size: 0.9em;
}
.chandra-breadcrumb-item { display: flex; align-items: center; }
.chandra-breadcrumb-link {
color: var(--chandra-primary, #2196F3);
text-decoration: none; cursor: pointer;
}
.chandra-breadcrumb-link:hover { text-decoration: underline; }
.chandra-breadcrumb-current { color: var(--chandra-text-muted, #757575); }
.chandra-breadcrumb-sep {
margin: 0 8px;
color: var(--chandra-text-muted, #999);
}
CSS
}
lib/Chandra/Nav.pm view on Meta::CPAN
}
.chandra-nav-sidebar.chandra-nav-collapsed .chandra-nav-label,
.chandra-nav-sidebar.chandra-nav-collapsed .chandra-nav-badge { display: none; }
.chandra-nav-sidebar.chandra-nav-collapsed .chandra-nav-link {
justify-content: center;
padding: 10px 0;
}
.chandra-nav-sidebar .chandra-nav-link {
display: flex; align-items: center; gap: 10px;
padding: 10px 16px; color: var(--chandra-text, #212121);
text-decoration: none; cursor: pointer;
transition: background 0.15s;
}
.chandra-nav-sidebar .chandra-nav-link:hover { background: var(--chandra-hover, #e8e8e8); }
.chandra-nav-sidebar .chandra-nav-active .chandra-nav-link {
background: var(--chandra-selected, #e3f2fd);
color: var(--chandra-primary, #2196F3);
font-weight: 600;
}
.chandra-nav-separator { border-top: 1px solid var(--chandra-border, #e0e0e0); margin: 4px 12px; }
.chandra-nav-toggle {
width: 52px; border: none;
background: transparent;
font-size: 1.1em; cursor: pointer;
color: var(--chandra-text-muted, #757575);
flex-shrink: 0;
text-align: center;
}
.chandra-nav-icon { font-size: 1.1em; flex-shrink: 0; width: 24px; text-align: center; }
.chandra-nav-badge {
margin-left: auto; background: var(--chandra-primary, #2196F3);
color: #fff; padding: 1px 8px; border-radius: 10px; font-size: 0.75em;
}
/* Topbar */
.chandra-nav-topbar {
background: var(--chandra-surface, #f5f5f5);
border-bottom: 1px solid var(--chandra-border, #e0e0e0);
padding: 0 8px;
}
.chandra-nav-topbar .chandra-nav-list { display: flex; gap: 0; }
.chandra-nav-topbar .chandra-nav-link {
display: flex; align-items: center; gap: 6px;
padding: 12px 16px; color: var(--chandra-text, #212121);
text-decoration: none; cursor: pointer;
border-bottom: 2px solid transparent;
transition: border-color 0.15s, color 0.15s;
}
.chandra-nav-topbar .chandra-nav-link:hover { color: var(--chandra-primary, #2196F3); }
.chandra-nav-topbar .chandra-nav-active .chandra-nav-link {
color: var(--chandra-primary, #2196F3);
border-bottom-color: var(--chandra-primary, #2196F3);
font-weight: 600;
}
.chandra-nav-topbar .chandra-nav-separator { display: none; }
lib/Chandra/Table.pm view on Meta::CPAN
}
# ââ CSS ââââââââââââââââââââââââââââââââââââââââââââââââââââ
sub css {
return <<'CSS';
.chandra-table-wrap { font-family: system-ui, -apple-system, sans-serif; }
.chandra-table { width: 100%; border-collapse: collapse; }
.chandra-table th, .chandra-table td { padding: 8px 12px; text-align: left; border-bottom: 1px solid #e0e0e0; }
.chandra-table th { background: #f5f5f5; font-weight: 600; user-select: none; }
.chandra-table-sortable { cursor: pointer; }
.chandra-table-sortable:hover { background: #e8e8e8; }
.chandra-table-stripe { background: #fafafa; }
.chandra-table-selected { background: #e3f2fd !important; }
.chandra-table-select { width: 40px; text-align: center; }
.chandra-table-empty, .chandra-table-loading { text-align: center; padding: 24px; color: #999; }
.chandra-table-filters { padding: 8px 0; display: flex; gap: 8px; flex-wrap: wrap; }
.chandra-table-filter { padding: 4px 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 13px; }
.chandra-table-pagination { display: flex; align-items: center; justify-content: center; gap: 4px; padding: 12px 0; }
.chandra-table-page-btn { padding: 4px 10px; border: 1px solid #ddd; border-radius: 4px; background: #fff; cursor: pointer; font-size: 13px; }
.chandra-table-page-btn:hover { background: #f0f0f0; }
.chandra-table-page-active { background: #2196F3 !important; color: #fff; border-color: #2196F3; }
.chandra-table-info { margin-right: 12px; font-size: 13px; color: #666; }
CSS
}
1;
__END__
lib/Chandra/Tabs.pm view on Meta::CPAN
.chandra-tabs-header {
display: flex;
border-bottom: 1px solid var(--chandra-border, #e0e0e0);
gap: 0;
}
.chandra-tab {
padding: 10px 20px;
border: none;
background: transparent;
color: var(--chandra-text-muted, #757575);
cursor: pointer;
font-size: inherit;
font-family: inherit;
border-bottom: 2px solid transparent;
transition: color 0.15s, border-color 0.15s;
display: flex;
align-items: center;
gap: 6px;
}
.chandra-tab:hover { color: var(--chandra-text, #212121); }
.chandra-tab-active {
lib/Chandra/Theme.pm view on Meta::CPAN
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 16px;
border: 1px solid var(--chandra-border);
border-radius: var(--chandra-radius);
background: var(--chandra-surface);
color: var(--chandra-text);
font-family: inherit;
font-size: inherit;
cursor: pointer;
transition: background 0.15s, border-color 0.15s;
}
button:hover, .chandra-btn:hover { background: var(--chandra-hover); }
button:disabled { opacity: 0.5; cursor: not-allowed; }
.chandra-btn-primary {
background: var(--chandra-primary);
color: #fff;
border-color: var(--chandra-primary);
}
.chandra-btn-primary:hover { opacity: 0.9; }
.chandra-btn-danger {
background: var(--chandra-danger);
lib/Chandra/Theme.pm view on Meta::CPAN
.chandra-form { display: flex; flex-direction: column; gap: 12px; }
.chandra-field { display: flex; flex-direction: column; gap: 4px; }
.chandra-label { font-weight: 500; font-size: 0.9em; color: var(--chandra-text-muted); }
.chandra-submit {
align-self: flex-start;
padding: 8px 24px;
background: var(--chandra-primary);
color: #fff;
border: none;
border-radius: var(--chandra-radius);
cursor: pointer;
font-weight: 500;
}
.chandra-submit:hover { opacity: 0.9; }
.chandra-error { color: var(--chandra-danger); font-size: 0.85em; }
.chandra-group { border: 1px solid var(--chandra-border); border-radius: var(--chandra-radius); padding: 12px; }
.chandra-group legend { font-weight: 600; padding: 0 6px; }
/* ââ Table (Chandra::Table) âââââââââââââââââââââââââââââ */
.chandra-table-wrap { font-family: inherit; }
lib/Chandra/Theme.pm view on Meta::CPAN
.chandra-table th, .chandra-table td {
padding: 8px 12px;
text-align: left;
border-bottom: 1px solid var(--chandra-border);
}
.chandra-table th {
background: var(--chandra-surface);
font-weight: 600;
user-select: none;
}
.chandra-table-sortable { cursor: pointer; }
.chandra-table-sortable:hover { background: var(--chandra-hover); }
.chandra-table-stripe { background: var(--chandra-surface); }
.chandra-table-selected { background: var(--chandra-selected) !important; }
.chandra-table-select { width: 40px; text-align: center; }
.chandra-table-empty, .chandra-table-loading {
text-align: center;
padding: 24px;
color: var(--chandra-text-muted);
}
.chandra-table-filters { padding: 8px 0; display: flex; gap: 8px; flex-wrap: wrap; }
lib/Chandra/Theme.pm view on Meta::CPAN
.chandra-context-menu {
background: var(--chandra-bg);
border: 1px solid var(--chandra-border);
border-radius: var(--chandra-radius);
box-shadow: var(--chandra-shadow);
padding: 4px 0;
min-width: 180px;
}
.chandra-context-menu-item {
padding: 6px 16px;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
}
.chandra-context-menu-item:hover { background: var(--chandra-hover); }
/* ââ Scrollbar (webkit) âââââââââââââââââââââââââââââââââ */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
xs/contextmenu.xs view on Meta::CPAN
".chandra-ctx-menu{"
"position:fixed;z-index:999999;min-width:160px;"
"background:#fff;border:1px solid #ccc;border-radius:6px;"
"box-shadow:0 4px 16px rgba(0,0,0,.18);padding:4px 0;"
"font:13px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;"
"color:#222;user-select:none;opacity:0;transform:scale(.96);"
"transition:opacity .12s,transform .12s;"
"}"
".chandra-ctx-menu.show{opacity:1;transform:scale(1);}"
".chandra-ctx-item{"
"padding:6px 32px 6px 28px;cursor:pointer;white-space:nowrap;"
"display:flex;align-items:center;position:relative;"
"}"
".chandra-ctx-item:hover{background:#e8f0fe;}"
".chandra-ctx-item.disabled{color:#999;pointer-events:none;}"
".chandra-ctx-sep{height:1px;background:#e0e0e0;margin:4px 8px;}"
".chandra-ctx-icon{width:20px;margin-right:6px;text-align:center;}"
".chandra-ctx-sc{margin-left:auto;padding-left:24px;color:#888;font-size:12px;}"
".chandra-ctx-check{position:absolute;left:8px;}"
".chandra-ctx-sub-arrow{margin-left:auto;padding-left:16px;color:#888;}"
".chandra-ctx-sub{position:fixed;}"