<div class="row" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()">
+ <h1 class="sr-only" i18n>Follows</h1>
<div class="col-xl-6 col-md-12">
- <div i18n class="subtitle">Followers instances</div>
+ <h2 i18n class="subtitle">Followers instances</h2>
<div i18n class="no-results" *ngIf="followersPagination.totalItems === 0">This instance does not have instances followers.</div>
</div>
<div class="col-xl-6 col-md-12">
- <div i18n class="subtitle">Followings instances</div>
+ <h2 i18n class="subtitle">Followings instances</h2>
<div i18n class="no-results" *ngIf="followingsPagination.totalItems === 0">This instance does not have instances followings.</div>
<div class="col-md-12 col-xl-6">
<div class="about-instance-title">
- <div i18n class="title">About {{ instanceName }}</div>
+ <h1 i18n class="title">About {{ instanceName }}</h1>
- <div i18n *ngIf="isContactFormEnabled" (click)="openContactModal()" role="button" class="contact-admin">Contact administrator</div>
+ <button i18n *ngIf="isContactFormEnabled" (click)="openContactModal()" (keydown.enter)="openContactModal()" class="contact-admin">Contact administrator</button>
</div>
<div class="block instance-badges">
<div i18n *ngIf="isNSFW" class="block dedicated-to-nsfw">This instance is dedicated to sensitive/NSFW content.</div>
</div>
- <div i18n class="middle-title" *ngIf="html.administrator || maintenanceLifetime || businessModel">
+ <h2 i18n class="middle-title" *ngIf="html.administrator || maintenanceLifetime || businessModel">
ADMINISTRATORS & SUSTAINABILITY
- </div>
+ </h2>
<div class="block administrator" *ngIf="html.administrator">
- <div i18n class="section-title">Who we are</div>
+ <h3 i18n class="section-title">Who we are</h3>
<div [innerHTML]="html.administrator"></div>
</div>
<div class="block creation-reason" *ngIf="creationReason">
- <div i18n class="section-title">Why we created this instance</div>
+ <h3 i18n class="section-title">Why we created this instance</h3>
<p>{{ creationReason }}</p>
</div>
<div class="block maintenance-lifetime" *ngIf="maintenanceLifetime">
- <div i18n class="section-title">How long we plan to maintain this instance</div>
+ <h3 i18n class="section-title">How long we plan to maintain this instance</h3>
<p>{{ maintenanceLifetime }}</p>
</div>
<div class="block business-model" *ngIf="businessModel">
- <div i18n class="section-title">How we will pay for this instance</div>
+ <h3 i18n class="section-title">How we will pay for this instance</h3>
<p>{{ businessModel }}</p>
</div>
- <div i18n class="middle-title" *ngIf="html.description">
+ <h2 i18n class="middle-title" *ngIf="html.description">
INFORMATION
- </div>
+ </h2>
<div class="block description">
- <div i18n class="section-title">Description</div>
+ <h3 i18n class="section-title">Description</h3>
<div [innerHTML]="html.description"></div>
</div>
- <div i18n class="middle-title" *ngIf="html.moderationInformation || html.codeOfConduct || html.terms">
+ <h2 i18n class="middle-title" *ngIf="html.moderationInformation || html.codeOfConduct || html.terms">
MODERATION
- </div>
+ </h2>
<div class="block moderation-information" *ngIf="html.moderationInformation">
- <div i18n class="section-title">Moderation information</div>
+ <h3 i18n class="section-title">Moderation information</h3>
<div [innerHTML]="html.moderationInformation"></div>
</div>
<div class="block code-of-conduct" *ngIf="html.codeOfConduct">
- <div i18n class="section-title">Code of conduct</div>
+ <h3 i18n class="section-title">Code of conduct</h3>
<div [innerHTML]="html.codeOfConduct"></div>
</div>
<div class="block terms">
- <div i18n class="section-title">Terms</div>
+ <h3 i18n class="section-title">Terms</h3>
<div [innerHTML]="html.terms"></div>
</div>
- <div i18n class="middle-title" *ngIf="html.hardwareInformation">
+ <h2 i18n class="middle-title" *ngIf="html.hardwareInformation">
OTHER INFORMATION
- </div>
+ </h2>
<div class="block hardware-information" *ngIf="html.hardwareInformation">
- <div i18n class="section-title">Hardware information</div>
+ <h3 i18n class="section-title">Hardware information</h3>
<div [innerHTML]="html.hardwareInformation"></div>
</div>
</div>
<div class="col-md-12 col-xl-6">
+ <h2 class="sr-only" i18n>FEATURES</h2>
<my-instance-features-table></my-instance-features-table>
</div>
<div class="col">
<div class="anchor" id="statistics"></div>
- <div i18n class="middle-title">STATISTICS</div>
+ <h2 i18n class="middle-title">STATISTICS</h2>
<my-instance-statistics></my-instance-statistics>
</div>
</div>
<ng-template #modal>
<div class="modal-header">
- <h4 i18n class="modal-title">Contact {{ instanceName }} administrator</h4>
- <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon>
+ <h1 i18n class="modal-title">Contact {{ instanceName }} administrator</h1>
+ <my-global-icon iconName="cross" aria-label="Close" tabindex="0" role="button" (click)="hide()" (keydown.enter)="hide()"></my-global-icon>
</div>
<div class="modal-body">
<div class="card">
<div class="card-body">
- <h5 class="card-title">
+ <div class="card-title">
<a i18n target="_blank" rel="noopener noreferrer" href="https://docs.joinpeertube.org/#/use-setup-account">Use PeerTube
documentation</a>
- </h5>
+ </div>
<div i18n class="card-text">
Discover how to setup your account, what is a channel, how to create a playlist and more!
<div class="card">
<div class="card-body">
- <h5 class="card-title">
+ <div class="card-title">
<a i18n target="_blank" rel="noopener noreferrer" href="https://docs.joinpeertube.org/#/use-third-party-application">PeerTube
Applications</a>
- </h5>
+ </div>
<div i18n class="card-text">
Discover unofficial Android applications or browser addons!
<div class="card">
<div class="card-body">
- <h5 class="card-title">
+ <div class="card-title">
<a i18n target="_blank" rel="noopener noreferrer" href="https://docs.joinpeertube.org/#/contribute-getting-started">Contribute on
PeerTube</a>
- </h5>
+ </div>
<div i18n class="card-text">
Want to help to improve PeerTube? You can translate the web interface, give your feedback or directly contribute to the code!
<my-about-peertube-contributors></my-about-peertube-contributors>
<div class="p2p-privacy">
- <h3 class="section-title">
+ <h2 class="section-title">
<div class="anchor" id="privacy"></div> <!-- privacy anchor -->
<ng-container i18n>P2P & Privacy</ng-container>
- </h3>
+ </h2>
<p i18n>
PeerTube uses the BitTorrent protocol to share bandwidth between users by default to help lower the load on the server,
tracker as long as you download or watch the video.
</p>
- <h6 i18n class="p2p-privacy-title">What are the consequences?</h6>
+ <h3 i18n class="p2p-privacy-title">What are the consequences?</h3>
<p i18n>
In theory, someone with enough technical skills could create a script that tracks which IP is downloading which video.
There are much more effective ways to get that kind of information.
</p>
- <h6 i18n class="p2p-privacy-title">How does PeerTube compare with YouTube?</h6>
+ <h3 i18n class="p2p-privacy-title">How does PeerTube compare with YouTube?</h3>
<p i18n>
The threats to privacy with YouTube are different from PeerTube's.
Moreover, YouTube is owned by Google/Alphabet, a company that tracks you across many websites (via AdSense or Google Analytics).
</p>
- <h6 i18n class="p2p-privacy-title">What can I do to limit the exposure of my IP address?</h6>
+ <h3 i18n class="p2p-privacy-title">What can I do to limit the exposure of my IP address?</h3>
<p i18n>
Your IP address is public so every time you consult a website, there is a number of actors (in addition to the final website) seeing
Thinking that removing P2P from PeerTube will give you back anonymity doesn't make sense.
</p>
- <h6 i18n class="p2p-privacy-title">What will be done to mitigate this problem?</h6>
+ <h3 i18n class="p2p-privacy-title">What will be done to mitigate this problem?</h3>
<p i18n>
PeerTube wants to deliver the best countermeasures possible, to give you more choice
}
}
}
+
+.card-title {
+ font-size: 1.25rem;
+}
+
+.p2p-privacy-title {
+ font-size: 20px;
+}
+<h1 class="sr-only" i18n>About</h1>
<div class="margin-content">
<div *ngIf="account" class="row no-gutters">
<div class="block col-md-6 col-sm-12 pr-2">
- <div i18n class="small-title">DESCRIPTION</div>
+ <h2 i18n class="small-title">DESCRIPTION</h2>
<div class="content" [innerHtml]="getAccountDescription()"></div>
</div>
<div class="block col-md-6 col-sm-12">
- <div i18n class="small-title">STATS</div>
+ <h2 i18n class="small-title">STATS</h2>
<div i18n class="content">Joined {{ account.createdAt | date }}</div>
</div>
+<h1 class="sr-only" i18n>Video channels</h1>
<div class="margin-content">
<div class="no-results" i18n *ngIf="channelPagination.totalItems === 0">This account does not have channels.</div>
<a [routerLink]="getVideoChannelLink(videoChannel)" i18n-title title="See this video channel">
<img [src]="videoChannel.avatarUrl" alt="Avatar" />
- <div>{{ videoChannel.displayName }}</div>
+ <h2 class="section-title">{{ videoChannel.displayName }}</h2>
<div class="followers" i18n>{videoChannel.followersCount, plural, =1 {1 subscriber} other {{{ videoChannel.followersCount }} subscribers}}</div>
</a>
+<h1 class="sr-only" i18n>Configuration</h1>
<form role="form" [formGroup]="form">
<div ngbNav #nav="ngbNav" class="nav-tabs">
<div class="admin-sub-header">
- <div i18n class="form-sub-title">Follows & redundancies</div>
+ <h1 i18n class="form-sub-title">Follows & redundancies</h1>
<div class="admin-sub-nav">
<a i18n routerLink="following-list" routerLinkActive="active">Following</a>
<div class="admin-sub-header">
- <div i18n class="form-sub-title">Moderation</div>
+ <h1 i18n class="form-sub-title">Moderation</h1>
<div class="admin-sub-nav">
<a *ngIf="hasVideoAbusesRight()" i18n routerLink="video-abuses/list" routerLinkActive="active">Video reports</a>
<div class="admin-sub-header">
- <div i18n class="form-sub-title">Plugins/Themes</div>
+ <h1 i18n class="form-sub-title">Plugins/Themes</h1>
<div class="admin-sub-nav">
<a i18n routerLink="list-installed" routerLinkActive="active">Installed</a>
<div class="admin-sub-header">
- <div i18n class="form-sub-title">System</div>
+ <h1 i18n class="form-sub-title">System</h1>
<div class="admin-sub-nav">
<a *ngIf="hasJobsRight()" i18n routerLink="jobs" routerLinkActive="active">Jobs</a>
<div class="admin-sub-header">
- <div i18n class="form-sub-title">Users list</div>
+ <h1 i18n class="form-sub-title">Users list</h1>
<a class="add-button" routerLink="/admin/users/create">
<my-global-icon iconName="add" aria-hidden="true"></my-global-icon>
<div class="admin-sub-header">
- <div i18n class="form-sub-title">Muted accounts</div>
+ <h1 i18n class="form-sub-title">Muted accounts</h1>
</div>
<p-table
<div class="admin-sub-header">
- <div i18n class="form-sub-title">Muted instances</div>
+ <h1 i18n class="form-sub-title">Muted instances</h1>
</div>
<p-table
+<h1 class="sr-only" i18n>History</h1>
<div class="top-buttons">
<div class="history-switch">
<p-inputSwitch [(ngModel)]="videosHistoryEnabled" (ngModelChange)="onVideosHistoryChange()"></p-inputSwitch>
+<h1 class="sr-only" i18n>Notifications</h1>
<div class="header">
<a routerLink="/my-account/settings" fragment="notifications" i18n>
<my-global-icon iconName="cog" aria-hidden="true"></my-global-icon>
<ng-template #modal let-close="close" let-dismiss="dismiss">
<div class="modal-header">
- <h4 i18n class="modal-title">Accept ownership</h4>
+ <h1 i18n class="modal-title">Accept ownership</h1>
<my-global-icon iconName="cross" aria-label="Close" role="button" (click)="dismiss()"></my-global-icon>
</div>
+<h1 class="sr-only" i18n>Ownership changes</h1>
<p-table
[value]="videoChangeOwnerships"
[lazy]="true"
+<h1 class="sr-only" i18n>Settings</h1>
<div class="form-row"> <!-- profile grid -->
<div class="form-group col-12 col-lg-4 col-xl-3">
- <div i18n class="account-title">PROFILE</div>
+ <h2 i18n class="account-title">PROFILE</h2>
</div>
<div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
<div class="form-row mt-5"> <!-- video settings grid -->
<div class="form-group col-12 col-lg-4 col-xl-3">
<div class="anchor" id="video-settings"></div> <!-- video settings anchor -->
- <div i18n class="account-title">VIDEO SETTINGS</div>
+ <h2 i18n class="account-title">VIDEO SETTINGS</h2>
</div>
<div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
<div class="form-row mt-5"> <!-- notifications grid -->
<div class="form-group col-12 col-lg-4 col-xl-3">
<div class="anchor" id="notifications"></div> <!-- notifications anchor -->
- <div i18n class="account-title">NOTIFICATIONS</div>
+ <h2 i18n class="account-title">NOTIFICATIONS</h2>
</div>
<div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
<div class="form-row mt-5"> <!-- interface grid -->
<div class="form-group col-12 col-lg-4 col-xl-3">
- <div i18n class="account-title">INTERFACE</div>
+ <h2 i18n class="account-title">INTERFACE</h2>
</div>
<div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
<div class="form-row mt-5" *ngIf="user.pluginAuth === null"> <!-- password grid -->
<div class="form-group col-12 col-lg-4 col-xl-3">
- <div i18n class="account-title">PASSWORD</div>
+ <h2 i18n class="account-title">PASSWORD</h2>
</div>
<div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
<div class="form-row mt-5"> <!-- email grid -->
<div class="form-group col-12 col-lg-4 col-xl-3">
- <div i18n class="account-title">EMAIL</div>
+ <h2 i18n class="account-title">EMAIL</h2>
</div>
<div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
<div class="form-row mt-5"> <!-- danger zone grid -->
<div class="form-group col-12 col-lg-4 col-xl-3">
- <div i18n class="account-title">DANGER ZONE</div>
+ <h2 i18n class="account-title">DANGER ZONE</h2>
</div>
<div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
+<h1 class="sr-only" i18n>Subscriptions</h1>
<div class="no-results" i18n *ngIf="pagination.totalItems === 0">You don't have any subscriptions yet.</div>
<div class="video-channels" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()">
+<h1 class="sr-only" i18n>My channels</h1>
<div class="video-channels-header">
<a class="create-button" routerLink="create">
<my-global-icon iconName="add" aria-hidden="true"></my-global-icon>
+<h1 class="sr-only" i18n>Imports</h1>
<p-table
[value]="videoImports" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage"
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id"
<div class="video-playlists-header">
- <h4 i18n>Playlists <span class="badge badge-secondary">{{ pagination.totalItems }}</span></h4>
+ <h1 i18n>Playlists <span class="badge badge-secondary">{{ pagination.totalItems }}</span></h1>
<input type="text" placeholder="Search your playlists" i18n-placeholder [(ngModel)]="videoPlaylistsSearch" (ngModelChange)="onVideoPlaylistSearchChanged()" />
input[type=text] {
@include peertube-input-text(300px);
}
+
+ h1 {
+ font-size: 1.5rem;
+ }
}
@media screen and (max-width: $small-view) {
<div class="videos-header">
- <h4 i18n>Videos <span class="badge badge-secondary">{{ pagination.totalItems }}</span></h4>
+ <h1 i18n>Videos <span class="badge badge-secondary">{{ pagination.totalItems }}</span></h1>
<input type="text" placeholder="Search your videos" i18n-placeholder [(ngModel)]="videosSearch" (ngModelChange)="onVideosSearchChanged()" />
justify-content: space-between;
margin: 20px 0 50px;
- h4,
+ h1,
.fake-element {
flex: 1;
+ font-size: 1.5rem;
}
input[type=text] {
<div class="actor-img-edit-container">
<div class="actor-img-edit-button" [ngbTooltip]="'(extensions: '+ avatarExtensions +', '+ maxSizeText +': '+ maxAvatarSizeInBytes +')'" placement="right" container="body">
<my-global-icon iconName="edit"></my-global-icon>
+ <label for="avatarfile" i18n>Change your avatar</label>
<input #avatarfileInput type="file" title=" " name="avatarfile" id="avatarfile" [accept]="avatarExtensions" (change)="onAvatarChange()"/>
</div>
</div>
<p i18n *ngIf="null === serverStats">Loading instance statistics...</p>
<section *ngIf="null !== serverStats">
- <h5 i18n>Local</h5>
+ <h3 i18n>Local</h3>
<div class="row">
<div class="col-6 col-lg-4 col-xl-3">
</div>
</div>
- <h5 i18n>Federation</h5>
+ <h3 i18n>Federation</h3>
<div class="row">
<div class="col-6 col-lg-4 col-xl-3">
+
+h3 {
+ font-size: 1.25rem;
+}
+
.stat {
text-align: center;
margin-bottom: 1em;
<div class="margin-content">
<div class="videos-header">
- <div *ngIf="titlePage" class="title-page title-page-single">
+ <h1 *ngIf="titlePage" class="title-page title-page-single">
<div placement="bottom" [ngbTooltip]="titleTooltip" container="body">
{{ titlePage }}
</div>
<my-feed *ngIf="titlePage" [syndicationItems]="syndicationItems"></my-feed>
- </div>
+ </h1>
<div class="action-block" *ngIf="actions.length > 0">
<a [routerLink]="action.routerLink" routerLinkActive="active" *ngFor="let action of actions">
class="videos"
>
<ng-container *ngFor="let video of videos; trackBy: videoById;">
- <div class="date-title" *ngIf="getCurrentGroupedDateLabel(video)">
+ <h2 class="date-title" *ngIf="getCurrentGroupedDateLabel(video)">
{{ getCurrentGroupedDateLabel(video) }}
- </div>
+ </h2>
<div class="video-wrapper">
<my-video-miniature
<div>
<div class="title-block">
- <div class="title-page title-page-single">
+ <h2 class="title-page title-page-single">
<ng-container *ngIf="componentPagination.totalItems > 0; then hasComments; else noComments"></ng-container>
<ng-template #hasComments>
<ng-container i18n *ngIf="componentPagination.totalItems === 1; else manyComments">1 Comment</ng-container>
<ng-template i18n #manyComments>{{ componentPagination.totalItems }} Comments</ng-template>
</ng-template>
<ng-template i18n #noComments>Comments</ng-template>
- </div>
+ </h2>
<my-feed [syndicationItems]="syndicationItems"></my-feed>
<div class="other-videos">
<ng-container *ngIf="hasVideos$ | async">
<div class="title-page-container">
- <div i18n class="title-page title-page-single">
+ <h2 i18n class="title-page title-page-single">
Other videos
- </div>
+ </h2>
<div *ngIf="!playlist" class="title-page-autoplay"
[ngbTooltip]="autoPlayNextVideoTooltip" placement="bottom-right auto"
>
+<h1 class="sr-only" i18n>Discover</h1>
<div class="margin-content">
<div class="no-results" i18n *ngIf="notResults">No results.</div>
<ng-container *ngFor="let overview of overviews">
<div class="section videos" *ngFor="let object of overview.categories">
- <div class="section-title">
+ <h1 class="section-title">
<a routerLink="/search" [queryParams]="{ categoryOneOf: [ object.category.id ] }">{{ object.category.label }}</a>
- </div>
+ </h1>
<div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)">
<my-video-miniature [video]="video" [fitWidth]="true" [user]="user" [displayVideoActions]="false">
</div>
<div class="section videos" *ngFor="let object of overview.tags">
- <div class="section-title">
+ <h2 class="section-title">
<a routerLink="/search" [queryParams]="{ tagsOneOf: [ object.tag ] }">#{{ object.tag }}</a>
- </div>
+ </h2>
<div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)">
<my-video-miniature [video]="video" [fitWidth]="true" [user]="user" [displayVideoActions]="false">
<a [routerLink]="[ '/video-channels', buildVideoChannelBy(object) ]">
<img [src]="buildVideoChannelAvatarUrl(object)" alt="Avatar" />
- <div>{{ object.channel.displayName }}</div>
+ <h2 class="section-title">{{ object.channel.displayName }}</h2>
</a>
</div>
margin-bottom: 15px;
display: flex;
justify-content: space-between;
- border-top: 1px solid $separator-border-color;
+
+ &:not(h2) {
+ border-top: 1px solid $separator-border-color;
+ }
a {
&:hover, &:focus:not(.focus-visible), &:active {