feat: set css to adapt custom theming

This commit is contained in:
Aleix Soler 2025-04-04 15:35:05 +02:00
parent 492a64c3db
commit 3b1a472b99
3 changed files with 176 additions and 151 deletions

167
main.ts
View file

@ -80,60 +80,25 @@ class StatusPaneView extends View {
async setupPane() {
const { containerEl } = this;
containerEl.empty();
containerEl.addClass('status-pane');
containerEl.style.cssText = `
padding: 10px;
background: var(--background-secondary);
color: var(--text-normal);
font-family: var(--font-interface);
overflow-y: auto;
height: 100%;
`;
containerEl.addClass('note-status-pane', 'nav-files-container');
const searchContainer = containerEl.createDiv({ cls: 'status-pane-search' });
const searchContainer = containerEl.createDiv({ cls: 'note-status-search search-input-container' });
this.searchInput = searchContainer.createEl('input', {
type: 'text',
placeholder: 'Search notes...',
cls: 'status-pane-search-input'
});
this.searchInput.style.cssText = `
width: 100%;
padding: 8px 12px;
margin-bottom: 10px;
border: 1px solid var(--background-modifier-border);
border-radius: 4px;
background: var(--background-primary);
color: var(--text-normal);
outline: none;
transition: border-color 0.2s ease;
`;
this.searchInput.addEventListener('focus', () => {
this.searchInput!.style.borderColor = 'var(--interactive-accent)';
});
this.searchInput.addEventListener('blur', () => {
this.searchInput!.style.borderColor = 'var(--background-modifier-border)';
cls: 'note-status-search-input search-input'
});
this.searchInput.addEventListener('input', () => {
this.renderGroups(this.searchInput!.value.toLowerCase());
});
const actionsContainer = containerEl.createDiv({ cls: 'status-pane-actions-container' });
// Add refresh button for manual updates
const refreshButton = actionsContainer.createEl('button', {
type: 'button',
title: 'Refresh Statuses',
text: 'Refresh',
cls: 'status-pane-actions-refresh'
cls: 'note-status-actions-refresh clickable-icon mod-cta'
});
refreshButton.style.cssText = `
padding: 6px 12px;
margin: 5px 0 5px 10px;
background: var(--background-primary);
border: 1px solid var(--background-modifier-border);
border-radius: 4px;
cursor: pointer;
`;
refreshButton.addEventListener('click', async () => {
await this.renderGroups(this.searchInput?.value.toLowerCase() || '');
new Notice('Status pane refreshed');
@ -155,12 +120,11 @@ class StatusPaneView extends View {
for (const file of files) {
const cachedMetadata = this.app.metadataCache.getFileCache(file);
let status = 'unknown';
if (cachedMetadata?.frontmatter?.status) {
const frontmatterStatus = cachedMetadata.frontmatter.status.toLowerCase();
const matchingStatus = this.plugin.settings.customStatuses.find(s => s.name.toLowerCase() === frontmatterStatus);
if (matchingStatus) {
status = matchingStatus.name; // Use the exact name from settings
status = matchingStatus.name;
}
}
statusGroups[status].push(file);
@ -177,15 +141,7 @@ class StatusPaneView extends View {
text: `${status} ${this.plugin.getStatusIcon(status)} (${filteredFiles.length})`,
cls: `status-${status}`
});
titleSpan.style.cssText = `
color: ${this.plugin.settings.statusColors[status] || '#808080'};
font-weight: 600;
padding: 8px 12px;
display: flex;
align-items: center;
gap: 5px;
transition: background 0.2s ease;
`;
titleSpan.style.color = this.plugin.settings.statusColors[status]; // Keep color override
titleEl.style.cursor = 'pointer';
const isCollapsed = this.plugin.settings.collapsedStatuses[status] ?? false;
if (isCollapsed) {
@ -198,23 +154,8 @@ class StatusPaneView extends View {
this.plugin.settings.collapsedStatuses[status] = !this.plugin.settings.collapsedStatuses[status];
this.plugin.saveSettings();
});
titleEl.addEventListener('mouseover', () => {
titleSpan.style.background = 'var(--background-modifier-hover)';
});
titleEl.addEventListener('mouseout', () => {
titleSpan.style.background = 'transparent';
});
const childrenEl = groupEl.createDiv({ cls: 'nav-folder-children' });
childrenEl.style.cssText = `
padding-left: 20px;
border-left: 1px solid var(--background-modifier-border);
display: ${isCollapsed ? 'none' : 'block'};
`;
titleEl.addEventListener('click', () => {
childrenEl.style.display = childrenEl.style.display === 'none' ? 'block' : 'none';
});
filteredFiles.sort((a, b) => a.basename.localeCompare(b.basename)).forEach(file => {
const fileEl = childrenEl.createDiv({ cls: 'nav-file' });
const fileTitleEl = fileEl.createDiv({ cls: 'nav-file-title' });
@ -222,22 +163,10 @@ class StatusPaneView extends View {
text: file.basename,
cls: 'nav-file-title-content'
});
linkEl.style.cssText = `
padding: 6px 12px;
display: block;
color: var(--text-normal);
transition: background 0.2s ease;
`;
fileEl.addEventListener('click', (e) => {
e.preventDefault();
this.app.workspace.openLinkText(file.path, file.path, true);
});
fileEl.addEventListener('mouseover', () => {
linkEl.style.background = 'var(--background-modifier-hover)';
});
fileEl.addEventListener('mouseout', () => {
linkEl.style.background = 'transparent';
});
});
}
});
@ -269,7 +198,7 @@ export default class NoteStatus extends Plugin {
});
this.statusBarItem = this.addStatusBarItem();
this.statusBarItem.style.cursor = 'pointer';
this.statusBarItem.addClass('note-status-bar');
this.statusBarItem.addEventListener('click', () => {
this.settings.showStatusDropdown = !this.settings.showStatusDropdown;
this.updateStatusDropdown();
@ -657,14 +586,18 @@ export default class NoteStatus extends Plugin {
updateStatusBar() {
this.statusBarItem.empty();
this.statusBarItem.removeClass('left', 'hidden', 'auto-hide', 'visible');
this.statusBarItem.addClass('note-status-bar');
if (!this.settings.showStatusBar) {
this.statusBarItem.style.display = 'none';
this.statusBarItem.addClass('hidden');
return;
}
this.statusBarItem.style.display = 'flex';
this.statusBarItem.style.justifyContent = this.settings.statusBarPosition === 'left' ? 'flex-start' : 'flex-end';
if (this.settings.statusBarPosition === 'left') {
this.statusBarItem.addClass('left');
}
const statusEl = this.statusBarItem.createEl('span', {
text: `Status: ${this.currentStatus}`,
cls: `note-status-${this.currentStatus}`
@ -672,20 +605,18 @@ export default class NoteStatus extends Plugin {
statusEl.style.color = this.settings.statusColors[this.currentStatus];
this.statusBarItem.createEl('span', {
text: this.getStatusIcon(this.currentStatus),
cls: 'status-icon'
cls: 'note-status-icon'
});
if (this.settings.autoHideStatusBar && this.currentStatus === 'unknown') {
this.statusBarItem.style.opacity = '0';
this.statusBarItem.style.transition = 'opacity 0.5s ease';
this.statusBarItem.addClass('auto-hide');
setTimeout(() => {
if (this.currentStatus === 'unknown' && this.settings.showStatusBar) {
this.statusBarItem.style.display = 'none';
this.statusBarItem.addClass('hidden');
}
}, 500);
} else {
this.statusBarItem.style.opacity = '1';
this.statusBarItem.style.display = 'flex';
this.statusBarItem.addClass('visible');
}
}
@ -770,47 +701,24 @@ export default class NoteStatus extends Plugin {
this.statusDropdownContainer = this.settings.dropdownPosition === 'top'
? contentEl.insertBefore(document.createElement('div'), contentEl.firstChild)
: contentEl.appendChild(document.createElement('div'));
this.statusDropdownContainer.className = 'note-status-dropdown';
this.statusDropdownContainer.style.cssText = `
padding: 5px;
background: var(--background-secondary);
border-${this.settings.dropdownPosition === 'top' ? 'bottom' : 'top'}: 1px solid var(--background-modifier-border);
position: sticky;
${this.settings.dropdownPosition}: 0;
z-index: 10;
display: flex;
align-items: center;
gap: 10px;
`;
this.statusDropdownContainer.addClass('note-status-dropdown', this.settings.dropdownPosition);
}
this.statusDropdownContainer.empty();
const label = this.statusDropdownContainer.createEl('span', {
text: 'Status:',
cls: 'status-label'
cls: 'note-status-label'
});
label.style.fontWeight = 'bold';
const select = this.statusDropdownContainer.createEl('select', {
cls: 'status-select'
cls: 'note-status-select dropdown'
});
select.style.cssText = `
padding: 4px 8px;
border: 1px solid var(--background-modifier-border);
border-radius: 4px;
background: var(--background-primary);
color: var(--text-normal);
cursor: pointer;
outline: none;
transition: all 0.2s ease;
`;
this.settings.customStatuses.forEach(status => {
const option = select.createEl('option', {
text: `${status.name} ${status.icon}`,
value: status.name
});
option.style.color = this.settings.statusColors[status.name] || '#808080';
option.style.color = this.settings.statusColors[status.name];
if (status.name === this.currentStatus) {
option.selected = true;
}
@ -823,38 +731,16 @@ export default class NoteStatus extends Plugin {
}
});
select.addEventListener('mouseover', () => {
select.style.boxShadow = '0 2px 4px var(--background-modifier-box-shadow)';
});
select.addEventListener('mouseout', () => {
select.style.boxShadow = 'none';
});
const hideButton = this.statusDropdownContainer.createEl('button', {
text: 'Hide Bar',
cls: 'hide-status-bar-button'
cls: 'note-status-hide-button clickable-icon mod-cta'
});
hideButton.style.cssText = `
padding: 4px 8px;
border: 1px solid var(--background-modifier-border);
border-radius: 4px;
background: var(--background-primary);
color: var(--text-normal);
cursor: pointer;
transition: all 0.2s ease;
`;
hideButton.addEventListener('click', () => {
this.settings.showStatusDropdown = false;
this.updateStatusDropdown();
this.saveSettings();
new Notice('Status dropdown hidden');
});
hideButton.addEventListener('mouseover', () => {
hideButton.style.backgroundColor = 'var(--background-modifier-hover)';
});
hideButton.addEventListener('mouseout', () => {
hideButton.style.backgroundColor = 'var(--background-primary)';
});
}
async updateFileExplorerIcons(file: TFile) {
@ -862,7 +748,6 @@ export default class NoteStatus extends Plugin {
const cachedMetadata = this.app.metadataCache.getFileCache(file);
let status = 'unknown';
if (cachedMetadata?.frontmatter?.status) {
const frontmatterStatus = cachedMetadata.frontmatter.status.toLowerCase();
const matchingStatus = this.settings.customStatuses.find(s => s.name.toLowerCase() === frontmatterStatus);
@ -881,12 +766,10 @@ export default class NoteStatus extends Plugin {
if (existingIcon) existingIcon.remove();
const iconEl = titleEl.createEl('span', {
cls: 'note-status-icon',
cls: 'note-status-icon nav-file-tag',
text: this.getStatusIcon(status)
});
iconEl.style.marginLeft = '5px';
iconEl.style.color = this.settings.statusColors[status];
iconEl.style.fontSize = '12px';
}
}
}

View file

@ -15,5 +15,6 @@
"icon": "status-pane",
"repository": "https://github.com/devonthesofa/obsidian-note-status",
"issues": "https://github.com/devonthesofa/obsidian-note-status/issues",
"releaseNotes": "Initial release with status management, customizable UI, and file explorer integration."
"releaseNotes": "Initial release with status management, customizable UI, and file explorer integration.",
"css": "styles.css"
}

View file

@ -1,8 +1,149 @@
/*
This CSS file will be included with your plugin, and
available in the app when your plugin is enabled.
If your plugin does not need CSS, delete this file.
*/
/* Status Pane */
.note-status-pane {
padding: var(--size-4-2);
background: var(--background-secondary);
color: var(--text-normal);
font-family: var(--font-interface);
overflow-y: auto;
height: 100%;
}
.note-status-search {
margin-bottom: var(--size-4-2);
}
.note-status-search-input {
width: 100%;
padding: var(--input-padding);
border: var(--input-border-width) solid var(--background-modifier-border);
border-radius: var(--input-radius);
background: var(--background-primary);
color: var(--text-normal);
outline: none;
transition: border-color 0.2s ease;
}
.note-status-search-input:focus {
border-color: var(--interactive-accent);
}
.note-status-actions-refresh {
padding: var(--size-4-1) var(--size-4-3);
border: var(--input-border-width) solid var(--background-modifier-border);
border-radius: var(--button-radius);
background: var(--background-primary);
color: var(--text-normal);
cursor: pointer;
}
.note-status-actions-refresh:hover {
background: var(--background-modifier-hover);
}
/* Status Group Titles */
.status-group .nav-folder-title .status-active,
.status-group .nav-folder-title .status-onHold,
.status-group .nav-folder-title .status-completed,
.status-group .nav-folder-title .status-dropped,
.status-group .nav-folder-title .status-unknown {
font-weight: 600;
padding: var(--size-4-2) var(--size-4-3);
display: flex;
align-items: center;
gap: var(--size-4-1);
transition: background 0.2s ease;
}
.status-group .nav-folder-title:hover span {
background: var(--background-modifier-hover);
}
/* Status Dropdown */
.note-status-dropdown {
padding: var(--size-4-1);
background: var(--background-secondary);
position: sticky;
z-index: var(--layer-popover);
display: flex;
align-items: center;
gap: var(--size-4-2);
}
.note-status-dropdown.top {
border-bottom: var(--border-width) solid var(--background-modifier-border);
top: 0;
}
.note-status-dropdown.bottom {
border-top: var(--border-width) solid var(--background-modifier-border);
bottom: 0;
}
.note-status-label {
font-weight: bold;
}
.note-status-select {
padding: var(--input-padding);
border: var(--input-border-width) solid var(--background-modifier-border);
border-radius: var(--input-radius);
background: var(--background-secondary); /* Ensure clean background */
color: var(--text-normal);
cursor: pointer;
outline: none;
transition: all 0.2s ease;
appearance: auto; /* Restore native dropdown styling */
min-width: 120px; /* Prevent collapse */
}
.note-status-select:hover {
box-shadow: 0 2px 4px var(--background-modifier-box-shadow);
}
.note-status-select option {
background: var(--background-primary); /* Clean option background */
color: var(--text-normal);
}
.note-status-hide-button {
padding: var(--size-4-1) var(--size-4-2);
border: var(--input-border-width) solid var(--background-modifier-border);
border-radius: var(--button-radius);
background: var(--background-primary);
color: var(--text-normal);
cursor: pointer;
transition: all 0.2s ease;
}
.note-status-hide-button:hover {
background: var(--background-modifier-hover);
}
/* File Explorer Icons */
.note-status-icon {
margin-left: var(--size-4-1);
font-size: var(--font-ui-small);
}
/* Status Bar */
.note-status-bar {
display: flex;
justify-content: flex-end; /* Default, will be overridden by settings */
}
.note-status-bar.left {
justify-content: flex-start;
}
.note-status-bar.hidden {
display: none;
}
.note-status-bar.auto-hide {
opacity: 0;
transition: opacity 0.5s ease;
}
.note-status-bar.auto-hide.visible {
opacity: 1;
}