Skip to content
Components

Design language · 2027

A stage for ideas, not a theme around them.

The TEDxEleusis system is editorial, architectural and direct. It gives every idea room to speak while making the whole event unmistakably ours.

Principles

The system is intentionally restrained. These principles help us decide when to stay quiet and when a moment has earned more energy.

Clarity before decoration

Content leads. Every visual decision should make an idea easier to understand, navigate or remember.

Structure creates confidence

Consistent grids, borders and spacing give many kinds of content one recognizable TEDxEleusis frame.

Contrast creates rhythm

Quiet neutral pages make black panels, red accents and expressive imagery feel deliberate rather than constant.

Motion has a purpose

Interaction confirms state, reveals hierarchy and supports orientation. It never competes with the speaker or idea.

Typography

One voice, two registers.

The sans face carries ideas with warmth and clarity. Monospace labels provide orientation, metadata and a subtle institutional voice.

Display · 72

Ideas change how we see.

Utility · 12

Eleusis · May 2027 · Ideas worth spreading

A restrained palette.

Paper and ink do most of the work. TEDx red identifies ownership. Blue and richer gradients appear only when the experience needs a signal or a shift in energy.

Paper

#FAFAFA

Ink

#000000

TEDx red

#E62B1E

Signal blue

#0057FF

Structure

Borders define the stage.

The outer rails connect pages. Internal rules create rhythm without filling the interface with cards, shadows or decorative containers.

01 · Frame

Space is an active part of the identity.

Expressive moments

Energy should feel earned.

Dithered gradients and saturated colour mark high-value moments—tickets, key announcements and transitions—without becoming visual wallpaper.

UI in practice

The language becomes an interface.

These compositions show how the system moves from principles into useful moments across discovery, planning and conversion.

Component family

Announcement banner

Brand
Neutral
Dark
Component family

Person card

The same speaker content shown in every supported layout.

Stacked · Monochrome
Portrait of the fictional speaker Alexandra Markou

Alexandra Markou

Urban researcher and educator

Component family

Session list

Both variants below receive the same complete sessions. Timeline exposes schedule data; directory prioritises titles and people.

Timeline
  1. 10:30

    Saturday, 18 September

    What ancient places can teach future cities

    Main stage · 45 min

    A conversation about memory, civic space and the futures cities choose to build.

    Alexandra Markou (Urban researcher)

  2. 11:20

    Saturday, 18 September

    Designing with collective memory

    Main stage · 20 min

    How architecture can retain the traces of a place while making room for new uses.

    Nikos Pappas (Architect)

Component family

Journal card

Standard and featured stories share the same metadata order: date, title, summary, then action.

Application patterns

Composed examples

Ticket release

Be in the room.

A full day of talks, performances and conversations at the IRIS Cultural Center.

Get tickets

Across the ecosystem

Event energy. Hub longevity.

The event site creates urgency around one gathering. The hub gives talks and stories a longer life. Shared rules make both experiences feel related without making them identical.

Hub · Talk detail14:20

Society

What ancient places can teach future cities

00:0014:20

Eleni Markou

Eleusis · 2027

Hub · Community CTA

Ideas need people behind them.

A focused conversion pattern for volunteering, partnerships or newsletter participation.

Join the team

Shared components

Consistent by default.

The package turns the principles into reusable behavior: square geometry, clear labels, visible focus and predictable spacing.

Optional supporting context.

Developer handoff

One package, clear roles.

Start with the composed components. Reach for primitives only when the product genuinely needs a new composition. Every public export and option is listed below; examples stay folded away until needed.

01
Link workspace package

02
Load tokens and source

03
Import by name

Project setup
// package.json
"@tedxeleusis/ui": "workspace:*"

/* global.css */
@source "../../../../packages/ui/src";
@import "@tedxeleusis/ui/styles";

---
import { Button } from "@tedxeleusis/ui";
---

Foundations & shell

Page width, orientation and shared site chrome.

ContainerConstrains content width and applies the shared responsive gutter.
OptionsAstro
  • as: "div" | "section" | "main" | "article" | "header" | "footer"
  • size: "full" | "content" | "narrow" — default "content"
  • class and standard HTML attributes
import { Container } from "@tedxeleusis/ui";

<Container as="main" size="narrow">...</Container>
ContentFrameAdds the event’s bordered page rails on top of Container.
OptionsAstro
  • as: "div" | "section" | "main" | "article" — default "div"
  • class and standard HTML attributes
import { ContentFrame } from "@tedxeleusis/ui";

<ContentFrame as="main" class="py-20">...</ContentFrame>
MonoLabelConsistent uppercase utility labels and metadata.
OptionsAstro
  • as: "span" | "p" | "div" | "label" | "legend"
  • muted: boolean — default false
  • class and standard HTML attributes
import { MonoLabel } from "@tedxeleusis/ui";

<MonoLabel as="p" muted>Session · 10:30</MonoLabel>
SkipLinkKeyboard-accessible jump link for every page shell.
OptionsAstro
  • href: string — default "#main-content"
  • label: string — default "Skip to content"
  • class
import { SkipLink } from "@tedxeleusis/ui";

<SkipLink />
SiteNavigationShared desktop and mobile header with active states and analytics hooks.
OptionsAstro
  • items: SiteNavigationItem[] — required
  • action: SiteNavigationItem
  • id, homeHref, homeLabel, logoSrc: string
  • presentation: "site" | "preview" — default "site"
  • defaultMenuOpen: boolean
  • mobileOpenEvent: string
  • class
  • Item options: label, href, active, analyticsEvent
import { SiteNavigation } from "@tedxeleusis/ui";

<SiteNavigation
  id="event-navigation"
  items={[{ label: "Speakers", href: "/speakers", active: true }]}
  action={{ label: "Tickets", href: "/tickets" }}
/>
SiteFooterShared footer navigation, copyright line and back-to-top control.
OptionsAstro
  • links: SiteFooterLink[] — required; each item has label and href
  • organisation: string — default "TEDxEleusis"
  • year: number — defaults to current year
  • backToTopHref: string — default "#top"
  • class
import { SiteFooter } from "@tedxeleusis/ui";

<SiteFooter links={[{ label: "About", href: "/about" }]} />

Content & actions

Reusable editorial and conversion patterns.

ActionCalloutImage-backed campaign CTA for tickets, volunteering, registration and partnerships.
OptionsAstro
  • title, description, actionLabel: string — required
  • backgroundImage: URL string | Astro ImageMetadata
  • backgroundAlt, eyebrow, href, headingId: string
  • headingLevel: "h2" | "h3" | "h4"
  • loading: "eager" | "lazy"
  • Without href, the action renders as an aria-disabled status
  • class
import { ActionCallout } from "@tedxeleusis/ui";

<ActionCallout
  eyebrow="Ticket release"
  title="Early-bird tickets"
  description="Registration opens soon."
  backgroundImage={campaignImage}
  actionLabel="Tickets coming soon"
/>
AnnouncementBannerSite-wide announcement with optional action and persistent dismissal.
OptionsAstro
  • message: string — required
  • href, linkLabel: string
  • dismissible: boolean — default false
  • variant: "brand" | "neutral" | "dark"
  • id: string — required when dismissible
  • class
  • Named slot: "action" for a custom CTA
import { AnnouncementBanner } from "@tedxeleusis/ui";

<AnnouncementBanner
  id="tickets-live"
  message="Tickets are available."
  href="/tickets"
  variant="brand"
  dismissible
/>
ButtonA link or button with consistent hierarchy and sizing.
OptionsAstro
  • href: string — renders an anchor when present
  • type: "button" | "submit" | "reset"
  • variant: "primary" | "secondary" | "ghost"
  • size: "sm" | "md" | "lg"
  • disabled: boolean
  • class and standard button/anchor attributes
import { Button } from "@tedxeleusis/ui";

<Button href="/tickets" variant="primary" size="lg">
  Get tickets
</Button>
JournalCardJournal stories with one shared metadata order in standard and featured layouts.
OptionsAstro
  • title: string — required
  • href, date, datetime, description, imageAlt, linkLabel: string
  • image: URL string | Astro ImageMetadata
  • variant: "standard" | "featured"
  • headingLevel: "h2" | "h3" | "h4"
  • loading: "eager" | "lazy"
  • class
import { JournalCard } from "@tedxeleusis/ui";

<JournalCard
  title="A city shaped by memory"
  date="May 18, 2027"
  image={heroImage}
  variant="featured"
  href="/blog/a-city-shaped-by-memory"
/>
PersonCardSpeakers and organisers with stacked or editorial split layouts.
OptionsAstro
  • name: string — required
  • role, imageAlt, href, eyebrow, indexLabel: string
  • image: URL string | Astro ImageMetadata
  • variant: "stacked" | "split"
  • imageTreatment: "monochrome" | "color"
  • headingLevel: "h2" | "h3" | "h4"
  • loading: "eager" | "lazy"
  • class
import { PersonCard } from "@tedxeleusis/ui";

<PersonCard
  name="Alexandra Markou"
  role="Urban researcher"
  image={portrait}
  variant="split"
  imageTreatment="color"
/>
SessionListEvent sessions as a speaker directory or compact timeline.
OptionsAstro
  • sessions: SessionListItem[] — required
  • variant: "directory" | "timeline"
  • headingLevel: "h2" | "h3" | "h4"
  • titleLabel, peopleLabel, emptyMessage: string
  • showHeader: boolean
  • class
  • Item options: id, title, href, time, date, location, duration, meta, description, speakers[]
  • Speaker options: name, role, photoUrl
import { SessionList } from "@tedxeleusis/ui";

<SessionList
  variant="timeline"
  sessions={[{
    time: "10:30",
    title: "Opening session",
    meta: "Main stage · 45 min"
  }]}
/>

Forms & selection

Accessible form structure, controls and state.

FormStackPredictable vertical spacing for form groups.
OptionsAstro
  • as: "div" | "fieldset"
  • gap: "sm" | "md" | "lg"
  • class and standard HTML attributes
import { FormStack } from "@tedxeleusis/ui";

<FormStack as="fieldset" gap="lg">...</FormStack>
FormFieldConnects labels, descriptions and validation messages to a control.
OptionsAstro
  • label, htmlFor: string — required
  • description, error: string
  • required: boolean
  • class
  • Default slot: the input control
import { FormField, Input } from "@tedxeleusis/ui";

<FormField label="Email" htmlFor="email" required>
  <Input id="email" name="email" type="email" />
</FormField>
InputStyled native input that retains the browser’s form behaviour.
OptionsAstro
  • invalid: boolean
  • class
  • All native input attributes including type, name, value and autocomplete
import { Input } from "@tedxeleusis/ui";

<Input name="email" type="email" autocomplete="email" invalid={false} />
TextareaResizable multiline native control with shared validation styling.
OptionsAstro
  • invalid: boolean
  • class
  • All native textarea attributes and default-value slot
import { Textarea } from "@tedxeleusis/ui";

<Textarea name="message" rows="6" />
CheckboxNative checkbox with consistent focus and invalid states.
OptionsAstro
  • invalid: boolean
  • class
  • All native checkbox attributes including name, value, checked and disabled
import { Checkbox } from "@tedxeleusis/ui";

<label><Checkbox name="updates" value="yes" /> Updates</label>
NativeSelectNative select for simple or progressively enhanced forms.
OptionsAstro
  • invalid: boolean
  • class
  • All native select attributes
  • Default slot: option and optgroup elements
import { NativeSelect } from "@tedxeleusis/ui";

<NativeSelect name="role">
  <option value="volunteer">Volunteer</option>
</NativeSelect>
DropdownBranded Radix select with grouped options; hydrate it in Astro.
OptionsReact
  • groups: DropdownGroup[] — required
  • id, name, value, defaultValue, placeholder: string
  • disabled, required, invalid: boolean
  • className
  • aria-label, aria-labelledby, aria-describedby
  • onValueChange(value)
  • Group options: label, options[]; item options: value, label, disabled
import { Dropdown } from "@tedxeleusis/ui";

<Dropdown
  client:load
  name="attendance"
  groups={[{ options: [{ value: "in-person", label: "In person" }] }]}
/>
Select primitivesLower-level Radix parts for bespoke dropdown compositions.
OptionsReact
  • Exports: Select, SelectTrigger, SelectValue, SelectContent
  • SelectGroup, SelectLabel, SelectItem, SelectSeparator
  • SelectTrigger adds invalid: boolean
  • Other options follow the matching Radix Select primitive props
  • Use Dropdown for standard forms; use primitives only for custom composition
import {
  Select, SelectTrigger, SelectValue,
  SelectContent, SelectItem
} from "@tedxeleusis/ui";