Skip to content
149 changes: 149 additions & 0 deletions examples/index.html

Large diffs are not rendered by default.

173 changes: 172 additions & 1 deletion examples/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -421,4 +421,175 @@ h1 {
.form-actions .button {
width: 100%;
}
}
}

/* Tooltip Demo */
.tooltip-demo {
margin: 24px 16px;
background: #fff;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,.06);
padding: 28px;
}

.tooltip-demo h2 {
font-size: 22px;
margin-bottom: 24px;
color: #264653;
border-bottom: 2px solid #e76f51;
padding-bottom: 8px;
}

.tooltip-section {
margin-bottom: 24px;
}

.tooltip-section h3 {
font-size: 16px;
margin-bottom: 8px;
color: #333;
}

.tooltip-section p {
color: #666;
font-size: 14px;
line-height: 1.6;
margin-bottom: 12px;
}

.tooltip-section code {
background: #f0f0f5;
padding: 2px 6px;
border-radius: 4px;
font-size: 13px;
}

.tooltip-btn-row {
display: flex;
flex-wrap: wrap;
gap: 12px;
align-items: center;
}

.tooltip-target {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 10px 20px;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
border: none;
cursor: pointer;
}

.btn-blue { background: #3b82f6; color: #fff; }
.btn-green { background: #10b981; color: #fff; }
.btn-orange { background: #f59e0b; color: #fff; }
.btn-purple { background: #8b5cf6; color: #fff; }
.btn-pink { background: #ec4899; color: #fff; }

.tooltip-position-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}

.tooltip-position-cell {
display: flex;
align-items: center;
justify-content: center;
min-height: 120px;
background: #f8fafc;
border: 1px dashed #cbd5e1;
border-radius: 10px;
}

.edge-demo-area {
position: relative;
min-height: 180px;
background: #f8fafc;
border: 1px dashed #cbd5e1;
border-radius: 10px;
}

.edge-demo-area .tooltip-target {
position: absolute;
}

.edge-demo-area .edge-tl { top: 8px; left: 8px; }
.edge-demo-area .edge-tr { top: 8px; right: 8px; }
.edge-demo-area .edge-bl { bottom: 8px; left: 8px; }
.edge-demo-area .edge-br { bottom: 8px; right: 8px; }

.tooltip-scroll-container {
max-height: 200px;
overflow-y: auto;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 16px;
}

.tooltip-scroll-container .scroll-item {
padding: 12px 16px;
border-bottom: 1px solid #f0f0f5;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 14px;
}

.tooltip-scroll-container .scroll-item:last-child {
border-bottom: none;
}

.scroll-item-btn {
background: #e0e7ff;
color: #4f46e5;
border: none;
padding: 4px 12px;
border-radius: 6px;
font-size: 12px;
font-weight: 600;
cursor: pointer;
}

.tooltip-event-log {
background: #1e293b;
border-radius: 10px;
padding: 16px;
min-height: 80px;
max-height: 200px;
overflow-y: auto;
font-family: 'SF Mono', 'Fira Code', monospace;
font-size: 12px;
}

.tooltip-event-log .log-entry {
color: #94a3b8;
padding: 3px 0;
border-bottom: 1px solid #2d3748;
}

.tooltip-event-log .log-entry:last-child {
border-bottom: none;
}

.tooltip-event-log .log-entry .tag {
display: inline-block;
padding: 1px 6px;
border-radius: 3px;
font-size: 11px;
font-weight: 600;
margin-right: 6px;
}

.tag-shown { background: #065f46; color: #6ee7b7; }
.tag-action { background: #1e3a5f; color: #7dd3fc; }
.tag-error { background: #7f1d1d; color: #fca5a5; }
.tag-dismiss { background: #78350f; color: #fcd34d; }

.tooltip-event-log .no-events {
color: #475569;
font-style: italic;
}
2 changes: 1 addition & 1 deletion src/managers/gist-properties-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function resolveMessageProperties(message: GistMessage): ResolvedMessageP
if (!gist) return defaults;

return {
isEmbedded: !!gist.elementId,
isEmbedded: !!gist.elementId && !gist.tooltipPosition,
elementId: gist.elementId || '',
hasRouteRule: !!gist.routeRuleWeb,
routeRule: gist.routeRuleWeb || '',
Expand Down
28 changes: 14 additions & 14 deletions src/managers/message-component-manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ vi.mock('../templates/message', () => ({
}));
vi.mock('../templates/tooltip', () => ({
tooltipHTMLTemplate: vi.fn(
(_id: string, _props: unknown, url: string) =>
`<div id="gist-tooltip"><div id="gist-tooltip-container"><iframe id="${_id}" class="gist-tooltip-frame" src="${url}"></iframe></div></div>`
(_id: string, _props: unknown, url: string, _wrapperId?: string) =>
`<div class="gist-tooltip-inner"><div class="gist-tooltip-container"><iframe id="${_id}" class="gist-tooltip-frame" src="${url}"></iframe></div></div>`
),
}));
vi.mock('./page-component-manager', () => ({
Expand Down Expand Up @@ -193,7 +193,7 @@ describe('message-component-manager', () => {

it('cleans up existing position listeners before re-creating the tooltip', () => {
const mockCleanup = vi.fn();
vi.mocked(positionTooltip).mockReturnValue(mockCleanup);
vi.mocked(positionTooltip).mockReturnValue({ cleanup: mockCleanup, reposition: vi.fn() });

vi.mocked(resolveMessageProperties).mockReturnValue({
isEmbedded: false,
Expand Down Expand Up @@ -236,9 +236,9 @@ describe('message-component-manager', () => {
const wrapper = document.createElement('div');
wrapper.id = `gist-tooltip-${instanceId}`;
const tooltip = document.createElement('div');
tooltip.id = 'gist-tooltip';
tooltip.className = 'gist-tooltip-inner';
const container = document.createElement('div');
container.id = 'gist-tooltip-container';
container.className = 'gist-tooltip-container';
const iframe = document.createElement('iframe');
iframe.className = 'gist-tooltip-frame';
container.appendChild(iframe);
Expand All @@ -248,7 +248,7 @@ describe('message-component-manager', () => {
return wrapper;
}

it('adds gist-visible class to the tooltip iframe', () => {
it('adds gist-visible class to the tooltip container', () => {
setupTooltipWrapper('inst-1');
const message: GistMessage = {
messageId: 'msg-1',
Expand All @@ -258,8 +258,8 @@ describe('message-component-manager', () => {

showTooltipComponent(message);

const iframe = document.querySelector('.gist-tooltip-frame');
expect(iframe?.classList.contains('gist-visible')).toBe(true);
const container = document.querySelector('.gist-tooltip-container');
expect(container?.classList.contains('gist-visible')).toBe(true);
});

it('calls positionTooltip with the wrapper, selector, and position', () => {
Expand Down Expand Up @@ -291,7 +291,7 @@ describe('message-component-manager', () => {

showTooltipComponent(message);

const tooltipElement = document.getElementById('gist-tooltip');
const tooltipElement = document.querySelector('.gist-tooltip-inner');
expect(positionTooltip).toHaveBeenCalledWith(tooltipElement, '#target-el', 'top');
});

Expand Down Expand Up @@ -352,8 +352,8 @@ describe('message-component-manager', () => {
expect(log).toHaveBeenCalledWith('No target selector for tooltip inst-1');
expect(positionTooltip).not.toHaveBeenCalled();

const iframe = document.querySelector('.gist-tooltip-frame');
expect(iframe?.classList.contains('gist-visible')).toBe(false);
const container = document.querySelector('.gist-tooltip-container');
expect(container?.classList.contains('gist-visible')).toBe(false);
});
});

Expand All @@ -372,9 +372,9 @@ describe('message-component-manager', () => {
const wrapper = document.createElement('div');
wrapper.id = 'gist-tooltip-inst-1';
const tooltip = document.createElement('div');
tooltip.id = 'gist-tooltip';
tooltip.className = 'gist-tooltip-inner';
const container = document.createElement('div');
container.id = 'gist-tooltip-container';
container.className = 'gist-tooltip-container';
const iframe = document.createElement('iframe');
iframe.className = 'gist-tooltip-frame';
container.appendChild(iframe);
Expand All @@ -383,7 +383,7 @@ describe('message-component-manager', () => {
document.body.appendChild(wrapper);

const mockCleanup = vi.fn();
vi.mocked(positionTooltip).mockReturnValue(mockCleanup);
vi.mocked(positionTooltip).mockReturnValue({ cleanup: mockCleanup, reposition: vi.fn() });

vi.mocked(resolveMessageProperties).mockReturnValue({
isEmbedded: false,
Expand Down
Loading
Loading