wayBetter for X 1.0.2

This commit is contained in:
CRTkafa 2026-10-02 02:54:04 +07:00
parent 7e2515aa42
commit 467aea2e28
212 changed files with 10208 additions and 2345 deletions

View file

@ -42,9 +42,14 @@ export const X_PARTS: PartMap = {
search: { sel: 'form[role="search"] > div > div', text: 'form[role="search"] input' },
composer: { sel: '[data-testid="tweetTextarea_0"]', text: '[data-testid="tweetTextarea_0"] :is(span,div)' },
composerTool: { sel: '[data-testid="toolBar"] nav [role="button"]', text: '[data-testid="toolBar"] nav [role="button"] svg' },
sidebarCard: { sel: '[data-testid="sidebarColumn"] div:has(> :is(aside[role="complementary"],section[role="region"]))' },
// Live 2026-10-01: the painted, bordered card is the grandparent of X's aside/section (a plain div sits
// between), or the parent of a `*_sidebar` module (news, scores).
sidebarCard: { sel: '[data-testid="sidebarColumn"] div:has(> div > :is(aside[role="complementary"],section[role="region"])),[data-testid="sidebarColumn"] div:has(> [data-testid$="_sidebar"])' },
menu: { sel: '#layers [role="menu"]' },
hoverCard: { sel: '#layers [data-testid="HoverCard"]' },
// The compose dialog's painted sheet (the child of the modal that has a composer toolbar). Never every modal: the photo
// viewer shares X's dialog attributes and its scrim must stay dark. Fixture markup; not read live.
dialog: { sel: '#layers [role="dialog"][aria-modal="true"]:has([data-testid="toolBar"]) > div' },
};
/** Where X's decoration goes. */
@ -135,20 +140,40 @@ export const X_SKINS: VariantSkins<XSkinContext> = {
function bar(edge: 'top' | 'bottom', colors: RoleColors): string {
const inner = `${RAIL} > div > div`;
return `${WIDE}{
${NOT_CHAT} ${RAIL}{position:fixed !important;${edge}:0;left:0;right:0;z-index:30;height:56px;width:auto !important;flex-grow:0 !important;align-items:stretch !important;background-color:${colors.surface};border-${edge === 'top' ? 'bottom' : 'top'}:1px solid ${colors.border};box-shadow:0 ${edge === 'top' ? '1px' : '-1px'} 6px rgba(0, 0, 0, 0.12)}
${NOT_CHAT} ${RAIL}{position:fixed !important;${edge}:0;left:0;right:0;z-index:30;height:56px;width:auto !important;flex-grow:0 !important;align-items:stretch !important;background-color:var(--wb-part-nav-fill, ${colors.surface});background-image:var(--wb-part-nav-fill-1, none);box-shadow:var(--wb-part-nav-bevel, 0 ${edge === 'top' ? '1px' : '-1px'} 0 ${colors.border}, 0 ${edge === 'top' ? '1px' : '-1px'} 6px rgba(0, 0, 0, 0.12))}
/* The bar is the nav's surface: its fill and edge move from the nav (a box inside the bar) to the whole bar. */
${NOT_CHAT} ${NAV}{--wb-part-nav-fill:transparent;--wb-part-nav-fill-1:none;--wb-part-nav-bevel:none}
${NOT_CHAT} ${RAIL} > div{width:100% !important;height:56px !important}
${NOT_CHAT} ${inner}{position:static !important;width:100% !important;height:56px !important;max-width:1280px;margin:0 auto !important}
${NOT_CHAT} ${inner} > div{flex-direction:row !important;align-items:center !important;justify-content:space-between !important;height:56px !important;width:100% !important;padding:0 16px !important;overflow:visible !important}
${NOT_CHAT} ${inner} > div > div{flex-direction:row !important;align-items:center !important;height:56px !important;gap:4px}
${NOT_CHAT} ${inner}{position:static !important;width:100% !important;height:56px !important;${edge === 'top' ? 'max-width:1280px;' : ''}margin:0 auto !important}
${NOT_CHAT} ${inner} > div{flex-direction:row !important;align-items:center !important;justify-content:space-between !important;gap:8px;height:56px !important;width:100% !important;padding:0 8px !important;overflow:visible !important;box-sizing:border-box}
${NOT_CHAT} ${inner} > div > div{flex-direction:row !important;align-items:center !important;height:56px !important;gap:4px;min-width:0 !important}
/* The group with the logo, the items and the Post button takes the row; the account stays whole at the end. */
${NOT_CHAT} ${inner} > div > div:first-child{flex:1 1 auto !important}
${NOT_CHAT} ${inner} > div > div:last-child{flex:0 0 auto !important}
/* The same for the groups inside the row (the nav and the Post button sit in full-width wrappers). */
${NOT_CHAT} ${inner} > div > div > div{width:auto !important;flex:0 1 auto !important;min-width:0 !important}
${NOT_CHAT} ${NAV}{flex-direction:row !important;align-items:center !important;flex-wrap:nowrap !important;gap:2px}
/* X sizes each rail item to the rail (width:100%, flex-grow:1): in a row that is one window per item. */
${NOT_CHAT} ${NAV} > :is(a,button){width:auto !important;flex:0 1 auto !important;min-width:0 !important}
${NOT_CHAT} ${NAV} > :is(a,button) > div{padding:8px 10px !important}
${NOT_CHAT} ${NAV}{min-width:0 !important;overflow:hidden}
/* Items share the bar like taskbar buttons: each up to 160px, all shrinking alike, the label ending in an
ellipsis and then only the icon (live 2026-10-02: X shows up to 12 items, more than a row of whole labels). */
${NOT_CHAT} ${NAV} > :is(a,button){width:auto !important;flex:0 1 176px !important;min-width:36px !important;overflow:hidden}
${NOT_CHAT} ${NAV} > :is(a,button) > div{padding:8px 8px !important;gap:0 !important;min-width:0 !important;max-width:100% !important;box-sizing:border-box;justify-content:flex-start !important}
${NOT_CHAT} ${NAV} > :is(a,button) > div > div:first-child{flex:none !important}
${NOT_CHAT} ${NAV} > :is(a,button) > div > div:last-child:not(:first-child){display:block !important;flex:0 1 auto !important;margin-left:8px !important;margin-right:0 !important;padding-right:0 !important;min-width:0 !important;overflow:hidden !important;text-overflow:ellipsis !important;white-space:nowrap !important}
${NOT_CHAT} ${NAV} > :is(a,button) > div > div:last-child:not(:first-child) span{display:inline !important;white-space:nowrap !important}
${NOT_CHAT} ${RAIL} [data-testid="SideNav_NewTweet_Button"]{margin:0 0 0 8px !important;width:auto !important;min-height:40px !important;padding:0 16px !important}
${NOT_CHAT} ${RAIL} [data-testid="SideNav_AccountSwitcher_Button"]{margin:0 !important}
${NOT_CHAT} main[role="main"]{padding-${edge}:56px !important;align-items:center !important}
/* X's floating Grok and Chat buttons (bottom right) ride above a bottom bar instead of over its last items. */
${edge === 'bottom' ? `${NOT_CHAT} :is([data-testid="chat-drawer-root"],[data-testid="GrokDrawer"]){transform:translateY(-56px)}` : ''}
${NOT_CHAT} ${COLUMN} > div > div:first-child{${edge === 'top' ? 'top:56px !important' : ''}}
}
/* Too narrow for words: the items are icon buttons (a label cut to one letter reads as noise). */
@media (min-width:700px) and (max-width:1199px){
${NOT_CHAT} ${NAV} > :is(a,button){flex:0 1 48px !important}
${NOT_CHAT} ${NAV} > :is(a,button) > div{justify-content:center !important}
/* Only a label is hidden: below 1265px X itself renders the items with their icon alone (live 2026-10-02). */
${NOT_CHAT} ${NAV} > :is(a,button) > div > div:last-child:not(:first-child){display:none !important}
}`;
}