vojo/src/app/features/call-status/callIcons.tsx

134 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// These exports are folds `IconSrc` callbacks — `(filled?: boolean) =>
// JSX.Element` — that the folds `<Icon>` component invokes as `src(filled)`
// to populate the inner SVG content. They are NOT React components (they
// are never mounted via JSX as `<CallMicIcon />`), so the
// `react/function-component-definition` rule's "use a function
// declaration" guidance is misapplied here.
/* eslint-disable react/function-component-definition */
// Custom call-control icon set, drawn to match the design-system style
// captured in `docs/design/new-direct-messages-design/project/shared.jsx`
// (lines 4-19): 24×24 viewBox, stroke-only (no fill), 1.6px stroke weight
// for handset/mic/video glyphs, round line joins/caps, currentColor — so
// the same icons read consistently across the green/red/neutral variant
// flips of the IncomingCallStrip / CallControl buttons.
//
// Folds' `Icon` component owns the outer `<svg>` (viewBox=0 0 24 24,
// fill=none, sizing class via the `size` prop). An `IconSrc` therefore
// returns only the inner shapes — same convention as the stock
// `Icons.*` table (see folds/dist/index.js Icons block).
//
// `filled` is intentionally ignored: this is an outline icon family,
// the muted/active distinction is carried by the diagonal slash plus
// the button's variant color, not by an alternate filled shape.
import React from 'react';
import { IconSrc } from 'folds';
const STROKE = {
stroke: 'currentColor',
strokeWidth: 1.6,
strokeLinecap: 'round' as const,
strokeLinejoin: 'round' as const,
fill: 'none',
};
// Slightly heavier than the body strokes so the «muted» indicator
// reads as a deliberate cancellation rather than ornamentation.
const SLASH = {
...STROKE,
strokeWidth: 2,
};
export const CallMicIcon: IconSrc = () => (
<>
<rect x="9" y="3" width="6" height="12" rx="3" {...STROKE} />
<path d="M5 11a7 7 0 0 0 14 0" {...STROKE} />
<path d="M12 18v3" {...STROKE} />
</>
);
export const CallMicMuteIcon: IconSrc = () => (
<>
<rect x="9" y="3" width="6" height="12" rx="3" {...STROKE} />
<path d="M5 11a7 7 0 0 0 14 0" {...STROKE} />
<path d="M12 18v3" {...STROKE} />
<path d="M3 3l18 18" {...SLASH} />
</>
);
export const CallHeadphoneIcon: IconSrc = () => (
<>
<path d="M4 14a8 8 0 0 1 16 0" {...STROKE} />
<path d="M4 14v4a2 2 0 0 0 2 2h2v-7H6a2 2 0 0 0-2 2z" {...STROKE} />
<path d="M20 14v4a2 2 0 0 1-2 2h-2v-7h2a2 2 0 0 1 2 2z" {...STROKE} />
</>
);
export const CallHeadphoneMuteIcon: IconSrc = () => (
<>
<path d="M4 14a8 8 0 0 1 16 0" {...STROKE} />
<path d="M4 14v4a2 2 0 0 0 2 2h2v-7H6a2 2 0 0 0-2 2z" {...STROKE} />
<path d="M20 14v4a2 2 0 0 1-2 2h-2v-7h2a2 2 0 0 1 2 2z" {...STROKE} />
<path d="M3 3l18 18" {...SLASH} />
</>
);
export const CallVideoIcon: IconSrc = () => (
<>
<rect x="3" y="6" width="13" height="12" rx="2" {...STROKE} />
<path d="M16 10l5-3v10l-5-3" {...STROKE} />
</>
);
export const CallVideoMuteIcon: IconSrc = () => (
<>
<rect x="3" y="6" width="13" height="12" rx="2" {...STROKE} />
<path d="M16 10l5-3v10l-5-3" {...STROKE} />
<path d="M3 3l18 18" {...SLASH} />
</>
);
export const CallScreenShareIcon: IconSrc = () => (
<>
<rect x="3" y="4" width="18" height="13" rx="2" {...STROKE} />
<path d="M9 21h6M12 17v4" {...STROKE} />
<path d="M8.5 11l3.5-3.5L15.5 11" {...STROKE} />
<path d="M12 7.5V14" {...STROKE} />
</>
);
// Screenshare-off carries the same slash convention as the other muted
// glyphs so the on/off state has both a shape cue and a variant cue —
// matters for high-contrast / monochrome modes where the
// Success-vs-Surface variant flip alone is too subtle.
export const CallScreenShareMuteIcon: IconSrc = () => (
<>
<rect x="3" y="4" width="18" height="13" rx="2" {...STROKE} />
<path d="M9 21h6M12 17v4" {...STROKE} />
<path d="M8.5 11l3.5-3.5L15.5 11" {...STROKE} />
<path d="M12 7.5V14" {...STROKE} />
<path d="M3 3l18 18" {...SLASH} />
</>
);
// Classic «pick up» handset, used on the IncomingCallStrip Answer
// button. Kept upright (no rotation) so it reads as «receive call».
export const CallPhoneIcon: IconSrc = () => (
<path
d="M5 4h4l2 5-3 2a12 12 0 0 0 6 6l2-3 5 2v4a2 2 0 0 1-2 2A17 17 0 0 1 3 6a2 2 0 0 1 2-2z"
{...STROKE}
/>
);
// Same handset rotated 135° — universal «hang up / decline» glyph
// (handset tilted off the cradle). Reused for Decline (IncomingCallStrip)
// and Hangup (CallControl).
export const CallPhoneDownIcon: IconSrc = () => (
<g transform="rotate(135 12 12)">
<path
d="M5 4h4l2 5-3 2a12 12 0 0 0 6 6l2-3 5 2v4a2 2 0 0 1-2 2A17 17 0 0 1 3 6a2 2 0 0 1 2-2z"
{...STROKE}
/>
</g>
);